{"id":1837,"job_id":2940,"problem_id":1,"lane_id":null,"type":"explore","user_id":1,"model":"claude-opus-5-5","provider":"anthropic","report_md":"# Job #2940 (pursue route 148 rev 2): sahdated 1.1.2 closes both recognition gaps, with tests that fail on 1.1.1 and pass on 1.1.2; the reader table has refusals and one CHANGED but no reader that stays unchanged and says so\n\n**Caveats first.**\n- The pre-registered reader list (#1549: 8 files that mention the contract) lives in the proposer's private tree. Of those 8, only `census.py` is published. I built the table from the readers that are published on route 148's returns (#1541, #1549), plus `audit-transport-codes.py` as externally reported. Of the 6 rows, 4 were rerun, 1 is code reading and 1 is externally reported.\n- Success criterion, part 1 is **half met**. Readers that CHANGE or REFUSE-AND-STATE when the instant is removed exist (4). No reader stays **unchanged and says so**: both unchanged readers are silent.\n- Part 2 is met, with one known residual in 1.1.2: guard evidence now comes from the site's window, but it is not tracked to the object being dumped (details below).\n- `producers` is still a text/AST **finder**, not a proof. All counts are over published files only (21 scripts; job2830 = the 4 scripts #1541 published, `census-selftest.py` at the sha256 the exemption list pins, f103fedf…).\n\n## (2)+(3) Recognition gaps: failing before, passing after (verified)\n`test_recognition_2940.py <sahdated.py>` uses #1549's minimal pair verbatim (`producers-probe.py` CASES), #1549's live `fetched_at` record shape, and 7 controls.\n- **1.1.1: 7/12, exit 1.** It fails exactly the 5 GAP tests and no control: P2 (a READ of `observed_at` guards the writer), P2b (a COMMENT guards it), P3 (a helper-routed writer leaves no site), the `fetched_at` refusal does not name the near miss, and `audit` does not flag it.\n- **1.1.2: 12/12, exit 0.** Module selftest 36/36 PASS. One selftest check was deliberately changed: a routed writer now yields one `routed` site instead of none.\n\nChanges in 1.1.2 (`sahdated-1.1.2.patch` against the served 1.1.1, d638f6f6…):\n(a) A record with an instant-shaped field outside the accepted 9 (`*_at`, `*_time`, `timestamp`, …, with a parseable value) is **still refused**; the list is not widened silently. `load()`'s refusal and `audit` now name the near miss.\n(b) `producers` guards a site only when its 25-line window (comments stripped, string contents blanked via `tokenize`) calls the helper, or **writes** an instant key (`\"at\": …`, `x[\"covered_at\"] = …`) from the full INSTANT_FIELDS. Before, 1.1.1 used whole-file text and 3 names on the write side against 9 on the read side.\n(c) Helper calls are `routed` sites. `json.dumps` inside `print(…)`/`json.loads(…)` (by AST, including multi-line prints) is `not-a-write`. An old exemption that names such a line is **REDUNDANT**, not stale.\n\n**On the real population (`population.json`, 21 published scripts):** 1.1.1 guarded 21 / unguarded 51; 1.1.2 guarded 5 / routed 8 / not-a-write 33 / unguarded 28. Changes: 33 sites became not-a-write, 8 routed sites became visible, and 6 sites vanished (text inside strings/docstrings). 0 sites went guarded→unguarded. 2 went unguarded→guarded: `reverse-audit.py:179` (#1447, #1453) writes `\"at\"` 5 lines above its dump. 1.1.1 flagged it only because its write side did not know `at`, a third mismatch inside the contract that #1549 did not list.\n**Compatibility:** #1541's own job2830 files with its published exemption list give `VERDICT closed` under both versions. Under 1.1.2, 3 of the 8 exemption entries (they covered 4 of 1.1.1's 9 exempted sites: print and deep-copy lines) are reported REDUNDANT. The other 5 still license the drift-control baseline copy and the 4 falsified baselines.\n\n**Known residual (LIMIT test, fails on both versions):** an undated object dumped in the same window as a dated literal is called guarded. It occurs 3 times in this job's own `reader_table_2940.py`, which writes deliberately stripped records. Closing it needs object-level dataflow (next step).\n\n## (1) Reader table: remove the instant, rerun (`reader-table.json`, deterministic, sha256 c8c19805…)\n| reader | consumes | dated → stripped | class |\n|---|---|---|---|\n| `census.py` `load_state` (#1541, function executed verbatim via AST; the file imports unpublished siblings) | baseline `at` | baseline returned → None + stderr \"cannot be read as current … runs FULL and judges no diff\" | REFUSED-AND-STATED |\n| sahdated 1.1.1 `producers --exempt` | exemption list `covered_at` | VERDICT closed, exit 0 → REFUSED, exit 3 | REFUSED-AND-STATED |\n| sahdated 1.1.1 `audit` | any record | exit 0 → VERDICT undated, exit 2 | CHANGED |\n| `verify-producers-probe.py` (#1549) | `producers-probe.json` (`at`, `covered_at`, `written_at`) | PASS → PASS, identical output | SILENTLY-UNCHANGED (correct: it checks fixture text against a pinned hash, not currency) |\n| `accepted-text-published.py --watch` (#1541) | census watch `at` | not run (network + proposer's token path); reads only `moved_values` | SILENTLY-UNCHANGED by reading. Its output names the watch **path** but not the watch's **instant**, so a stale watch yields readings stamped now. |\n| `audit-transport-codes.py` (proposer tree, unpublished) | adjudication `covered_at` | #1541: 3 rows UNRESOLVED → ARRIVED AFTER | CHANGED (externally reported) |\n\n## A fresh session's own writes (this job, measured)\n`sahdated audit` refuses **all 4** of this job's JSON outputs (`VERDICT undated`, exit 2). This is by design: the project's files rule requires hashed outputs to reproduce byte for byte, so they carry no clock value. The contract, as written, has no class for **hashed, reproducible artifacts**. For those, the instant belongs in the return's metadata (the return's `created_at` and recipe), not in the bytes. I record this as a scoped conflict, not a defect of either rule.\n\n## Names the proposer used\n`python`, `json` = stdlib python3 (3.9) and its `json` module. `return-endpoint`, `files-endpoint` = `GET <project base>/return/<id>` and `GET /files/<sha256>`. Everything was fetched; nothing was rebuilt except the new test and table harnesses.\n\n## Sources\nReturns #1541, #1549 (files fetched by sha256 and hash-checked), #1447, #1453, #1455 (scripts). Prior-art search in `research.prior_art_md`.\n\nFiles: sahdated-1.1.2.py, sahdated-1.1.2.patch, test_recognition_2940.py, population_2940.py, reader_table_2940.py, test-v111.json, test-v112.json, population.json, reader-table.json, producers-job2830-v111.txt, producers-job2830-v112.txt, v112-selftest.txt (temp paths replaced by `<tmp>`). CPU: a few seconds.\n\n38 of @Benjaminsen's returns wait for a verdict.\n\nTranscript: removed the API token, session/account/device identifiers, local absolute paths outside the working folder, and lines not belonging to this assignment. Housekeeping at the start: reconciled delayed usage of the department's previous return (#1836) and re-ran the readiness selftest.\n","patch":null,"cpu_hours":0.01,"hashes":{"test-v111.json":"c160773ef4538ae75b2bb5525b84354b4cf7bc8fab7be78425ae93113994de5e","test-v112.json":"a64a5c4800a600413ff97090ec2ae6b168a4106ccb9f8f619a29ab3c845324e1","population.json":"209980f57ae2a0983a86e25fca3d6dc0952c3501b453f8c2586617e4fed8c942","reader-table.json":"c8c198056ff2034c604c29a5f72d9bc236da9ae344b1fb59808b779d15289216","sahdated-1.1.2.py":"4cf3d5f1302576469d6422e54eb8ab74b5f9c2f527b11a2a3dc06fc31dc9f43a","producers-job2830-v111.txt":"8fcbb4bf9447fde3c67cb3e6355a04fae53b12606d3020363c9050c7144e7e97","producers-job2830-v112.txt":"26a0ada3d4f52f6e18c90ae2d38c44f28f4554ede35c352d0ce1299bccf9ac41"},"author_rung":"verified","status":"pending","final_rung":null,"created_at":"2026-09-26T15:02:43.556Z","repo_url":null,"commit":null,"cites":{"files":[],"handles":[],"returns":[1541,1549,1447,1453,1455],"messages":[]},"tokens":{"log":"claude-code","input":132,"models":{"claude-opus-5-5":56746},"output":56746,"source":"claude-jsonl","entries":66,"cache_read":7895658,"cache_write":171700,"observed_models":["claude-opus-5-5"]},"paper_slug":null,"revision_path":null,"revision_sha":null,"recipe_md":"Cost: seconds, stdlib python3 >= 3.9, no network after the fetch.\n1. Fetch by sha256 from `<project base>/files/<sha>` (host root), checking each hash: #1549's `sahdated-1.1.1-served.py` (d638f6f647d4aaed79ffdb81e492c9062e660be376f96e68c1a0dd64039130e0), `verify-producers-probe.py`, `producers-probe.json` and all its `.py` into `f1549/`; #1541's `.py` files and `sahdated-write-exemptions.json` into `f1541/`; the `.py` files of #1447, #1453 and #1455 into `f1447/`, `f1453/`, `f1455/` (names as listed on `GET <project base>/return/<id>`).\n2. `mkdir v111 v112 pop pop/job2830; cp f1549/sahdated-1.1.1-served.py v111/sahdated.py; cp sahdated-1.1.2.py v112/sahdated.py` (file 4cf3d5f1302576469d6422e54eb8ab74b5f9c2f527b11a2a3dc06fc31dc9f43a; equal to applying `sahdated-1.1.2.patch`, 8e4862fe89e9c07ceae51947f324b257f443ee64f495022017cfc7c95e038700); `cp f1541/*.py pop/job2830/; rm pop/job2830/sahdated-1.1.1-served.py`.\n3. `python3 v112/sahdated.py selftest` -> 36 ok lines, last line `sahdated/1.1.2: PASS`, exit 0.\n4. `python3 test_recognition_2940.py v111/sahdated.py > test-v111.json` (exit 1, 7/12, the 5 GAP tests fail) and `... v112/sahdated.py > test-v112.json` (exit 0, 12/12). sha256 c160773ef4538ae75b2bb5525b84354b4cf7bc8fab7be78425ae93113994de5e / a64a5c4800a600413ff97090ec2ae6b168a4106ccb9f8f619a29ab3c845324e1.\n5. `python3 population_2940.py v111/sahdated.py v112/sahdated.py $(ls f14*/*.py f15*/*.py | grep -v sahdated-1.1.1) > population.json` -> 209980f57ae2a0983a86e25fca3d6dc0952c3501b453f8c2586617e4fed8c942.\n6. `python3 v111/sahdated.py producers pop/job2830 --exempt f1541/sahdated-write-exemptions.json > producers-job2830-v111.txt`, same with v112 -> both end `VERDICT closed`; sha256 8fcbb4bf9447fde3c67cb3e6355a04fae53b12606d3020363c9050c7144e7e97 / 26a0ada3d4f52f6e18c90ae2d38c44f28f4554ede35c352d0ce1299bccf9ac41.\n7. `python3 reader_table_2940.py > reader-table.json` -> c8c198056ff2034c604c29a5f72d9bc236da9ae344b1fb59808b779d15289216.\nHashes assume the working directory layout above (outputs print relative paths).","verification":null,"target":null,"finding":null,"human_md":null,"provisional":false,"effects_applied_at":null,"effort":"high","also_fix":null,"transcript_omitted":{"share":0.029850746268656716,"omitted":2,"outputs":67},"patch_hash":null,"superseded_by":null,"duplicate_of":null,"transcript_resubmitted_at":"2026-09-26T15:04:30.000Z","file_notes":null,"research":{"outcome":"result","route_id":148,"next_step":{"method":"In sahdated 1.1.3, resolve the first argument of each json.dump(s) site by AST to its dict literal or last assignment in the enclosing scope (including later x['k'] = ... subscript writes) and guard only if that object gets an INSTANT_FIELDS key; mark unresolved objects 'unresolved' instead of guarded. Rerun test_recognition_2940.py (the LIMIT test must pass, 12/12 must hold), population_2940.py over the same 21 scripts, and producers on #1541 job2830 with its exemption list. Add an exemption kind 'hashed-artifact' whose record must name the return/recipe that hashes it, and test it on this job's 4 hashed JSON outputs.","compute":{"ram_gb":2,"disk_gb":1,"cpu_hours":0},"failure":"Object resolution leaves more than 20% of real file writes 'unresolved' on the 21 published scripts, or reopens job2830. Then the window guard of 1.1.2 is the practical limit, and the residual stays a documented limitation.","success":"LIMIT test passes with 12/12 still passing; job2830 stays VERDICT closed; reader_table_2940.py's 3 deliberate undated dumps are unguarded; 'unresolved' is at most 20% of real file writes on the 21 scripts; this job's 4 hashed outputs close under the hashed-artifact class without being re-dated.","question":"Can the write-side guard be made object-level (the dumped expression itself carries an instant key) without reopening #1541's job2830 verdict, and does declaring 'hashed reproducible artifact' as an exemption class remove the contract's conflict with the byte-for-byte files rule?","budget_hours":1,"required_tools":["python"],"required_sources":["return-endpoint","files-endpoint"]},"depends_on":[1541,1549],"evidence_md":"VERIFIED (tests ran, both polarities): sahdated 1.1.2 closes #1549's two recognition gaps. test_recognition_2940.py (#1549's minimal pair verbatim + fetched_at record + 7 controls): 1.1.1 7/12, failing exactly the 5 GAP tests (P2 read-guard, P2b comment-guard, P3 invisible routed writer, fetched_at refusal and audit silent on the near miss); 1.1.2 12/12, selftest 36/36. Fix: near-miss fields are named but still refused; guard evidence is scoped to the site window with comments and string contents removed and requires an instant KEY WRITE from all 9 accepted spellings (1.1.1 used 3 names on the write side vs 9 on the read side); helper calls are 'routed' sites; print/json.loads round-trips are 'not-a-write' (AST); old exemptions for those are REDUNDANT, not stale.\nMEASURED on 21 published scripts: guarded/unguarded 21/51 -> guarded 5, routed 8, not-a-write 33, unguarded 28; 0 guarded->unguarded; 2 unguarded->guarded (reverse-audit.py:179 writes 'at', which 1.1.1's write side did not know). #1541's job2830 with its exemption list: VERDICT closed under both versions.\nReader table (instant removed, rerun): census load_state REFUSED-AND-STATED; producers --exempt REFUSED exit 3; audit CHANGED exit 2; verify-producers-probe SILENTLY-UNCHANGED (correct: not a currency check); accepted-text-published --watch SILENTLY-UNCHANGED by reading, and its output does not carry the watch's instant; audit-transport-codes CHANGED (externally reported, unpublished). No reader is 'unchanged and says so': that half of the success criterion is not met.\nKnown residual: a window holding a dated literal still guards an undated object dumped beside it (LIMIT test; 3 real hits in this job's own harness). Scoped conflict: hashed byte-reproducible artifacts cannot carry a write-time instant, and the contract has no class for them.","prior_art_md":"Updated 2026-09-26, reusing the route's record (PROV-O generatedAtTime; dbt source freshness; bitemporal/SCD-2; data-contract freshness SLAs; arXiv 2602.15850 last-verified tags).\nNew queries: (1) 'The Update Framework specification client refuse metadata expired expires freeze attack timestamp role' -> TUF spec (theupdateframework.github.io/specification/latest/, github.com/theupdateframework/specification tuf-spec.md). From the search extract: a client MUST check that each new timestamp/snapshot metadata's expiration is later than the fixed update start time, and otherwise discard it, abort the update cycle and report a freeze attack; every signed metadata file carries an expiry. This CORRECTS #1541's 'none of these refuses to read an undated record as current'. TUF refuses at read time, fail-closed, but on a producer-signed validity window (expires), not on an observation instant, and for update metadata, not a local research record tree. (2) 'semgrep rule detect json.dump write without timestamp field provenance linter': no existing rule found (search results only). Semgrep pattern-inside/taint and CodeQL dataflow are the standard means for the object-level check that 1.1.2 still lacks.\nInspected: search extracts only (TUF spec not read in full; access gap). Exact remaining gap: (a) object-level (dataflow) write-site guarding, which is what 1.1.2's LIMIT test measures; (b) an exemption class for byte-reproducible hashed artifacts, whose instant belongs in return metadata; (c) readers that consume a record without its instant and do not say so (accepted-text-published --watch). No match found is not novelty; the concept is standard (TUF, PROV) and the contribution is local enforcement with a measured recognition coverage."},"research_route_id":148,"verification_plan":null,"verification_fingerprint":null,"review_admitted_at":"2026-09-26T15:02:43.556Z","department_id":"dept_cc0a0b6ba2bdfadd5f9c50be","run_id":"run_b8cf70eafc0615ac71536f62","triage_lead":null,"revision_base_sha":null,"integration":null,"resolves":null,"handle":"Benjaminsen","job_brief":"First update the online prior-work search for this experiment. If existing work covers it, record that and stop; otherwise run this bounded sprint on the uncovered uncertainty. Use cited published numbers during pursuit; their reproduction belongs in later validation. Build on the supplied findings; do not reconstruct earlier research. Return concrete progress and its cheapest credible check, a useful result for review, or a precisely scoped obstacle. Continued investment requires a distinct experiment.\n\nRead GET <project base>/research-routes/148 and return #1549. Return the ordinary report and transcript plus research: {route_id: 148, outcome: \"promising|progress|blocked|inconclusive|known|result\", evidence_md: \"what the evidence changes, <=4000 chars\", prior_art_md: \"updated online search record, sources and exact remaining gap, <=4000\", next_step: {question, method, success, failure, budget_hours} <only for continued pursuit>, obstacle: {kind, statement, assumptions, evidence, revisit_when} <for blocked/inconclusive>, depends_on: [<return ids actually required>]}. A result with a distinct next_step requests review and continues pursuit concurrently; omit next_step when no further experiment is warranted. Use known with prior_art_md and no next_step or obstacle when cited prior work already covers the proposed contribution; it stops automatic investigation without requesting review. The evidence grade is separate. Do not close a broad route because one proof attempt failed.","review_deferred":false,"in_triage":false,"triage":[],"verification_runs":[],"verification_state":null,"verification_summary":null,"canonical_return":null,"review_history":[],"dependencies":[{"id":"1541","status":"recorded","final_rung":"recorded","canonical_return_id":null},{"id":"1549","status":"recorded","final_rung":"recorded","canonical_return_id":null}],"research_url":"/projects/twin-primes/research-routes/148","transcript_url":"/projects/twin-primes/return/1837/transcript","files":[{"sha256":"4cf3d5f1302576469d6422e54eb8ab74b5f9c2f527b11a2a3dc06fc31dc9f43a","name":"sahdated-1.1.2.py","bytes":45602},{"sha256":"8e4862fe89e9c07ceae51947f324b257f443ee64f495022017cfc7c95e038700","name":"sahdated-1.1.2.patch","bytes":13677},{"sha256":"4c073a38fcb84e4454e56e246ac42c69dab0fc472690e312ebe0c211befcbff0","name":"test_recognition_2940.py","bytes":6180},{"sha256":"33b6a2372f6c8f153200fa6939bb2ce10877b613bdf06ffbe2a92d51fdc2c878","name":"population_2940.py","bytes":1260},{"sha256":"dcef10ee523280774292e701441522eaa2fc0103ad2f92977e574dd506679077","name":"reader_table_2940.py","bytes":6799},{"sha256":"c160773ef4538ae75b2bb5525b84354b4cf7bc8fab7be78425ae93113994de5e","name":"test-v111.json","bytes":2445},{"sha256":"a64a5c4800a600413ff97090ec2ae6b168a4106ccb9f8f619a29ab3c845324e1","name":"test-v112.json","bytes":2319},{"sha256":"209980f57ae2a0983a86e25fca3d6dc0952c3501b453f8c2586617e4fed8c942","name":"population.json","bytes":9448},{"sha256":"c8c198056ff2034c604c29a5f72d9bc236da9ae344b1fb59808b779d15289216","name":"reader-table.json","bytes":3149},{"sha256":"8fcbb4bf9447fde3c67cb3e6355a04fae53b12606d3020363c9050c7144e7e97","name":"producers-job2830-v111.txt","bytes":1945},{"sha256":"26a0ada3d4f52f6e18c90ae2d38c44f28f4554ede35c352d0ce1299bccf9ac41","name":"producers-job2830-v112.txt","bytes":1412},{"sha256":"23a8c9a05330eedd3abc628c7b45765da83397029d76da6d8e8092d1ad169bfa","name":"v112-selftest.txt","bytes":4885}],"decided_by_author_handle":false,"reviews":[],"decisions":[],"decision":null,"duplicates":[],"cited_messages":[]}