Run ledger follow-ups from #887: script-rendered handoff check, write-time file digests, trusted-only reads, a shared write helper
Author: Imbad0202Created Sep 23, 2026Updated Sep 23, 2026
Context
PR #896 (for #887) added the run ledger (scripts/run_ledger.py) and the orchestrator's handoff check. Review of that PR raised four changes that were not made there. Each item says what would change, why, and what it costs.
Items
1. Let the script render the handoff check
- Now:
reportprints JSON. The orchestrator writes the handoff check from it in the user's language: four groups, then the number of backed items, and nothing when there is nothing to report. - Change:
reportprints the finished block, and the orchestrator inserts it verbatim, as it already does for the #743 inquiry-branch summary and the #656 renderer output. - Why: the model re-renders a deterministic result at the point where this feature distrusts model-written text. It could drop, merge, or reorder an item, and the display cannot be tested.
- Cost: the block's headings would be in one language unless the script takes a language setting. The display approved for #887 is in the user's language.
2. Compute or verify file digests when an entry is written
- Now: the orchestrator supplies each
sha256itself, forfile_referenceentries and for a receipt'sinput_sha256.reportre-hashes onlyfile_referencepaths. - Change:
appendhashes the named files itself, or refuses a supplied digest that does not match the file.reportalso checks a receipt's inputs and reports a receipt whose inputs changed after it was written. - Why: a mistyped digest now shows up later as a false "changed" item, and a receipt keeps backing its step after the step's inputs change.
- Cost: the entry contract changes (entries would name paths and the script would fill in digests), and
appendreads files.
3. A read command that returns only trusted entries
- Now:
reportapplies the break rule (entries from the first invalid one onward are untrusted). It prints neither the retries used nor the recorded answers of a partly collected answer, so the orchestrator reads those, and the words it quotes in the Stage 6 record, from the file itself. The prompt limits Stage 6 quotes to entries before any break; the other reads rely on the model to apply the break. - Change: a
showsubcommand that prints only the trusted entries and where the break is, and prompt text that routes every read through it. - Why: the trust rule would then cover every read, not only the report.
- Cost: one more subcommand and more prompt text. It matters only when the chain is broken.
4. Share the write helper and the line-budget helpers
- Now:
run_ledger._write_atomicrepeats the replace half ofars_mark_read._save_log, andrun_ledgerimports_ledger_lockand_UniqueKeySafeLoaderby their private names. Inscripts/test_v3_6_7_phase_6_6.py, the #887 measure helper and budget test copy the G1 ones except for the heading. - Change: one shared
atomic_replace(path, payload)and public names for the lock and the loader; one parametrized measure helper and a table-driven budget test. - Why: a later fix to the write path, such as a directory fsync, would otherwise be made twice, and renaming a private helper breaks
run_ledgerat import. - Cost: edits to
scripts/ars_mark_read.pyand to budget helpers that belong to other issues.
Non-goals
No change to what the ledger records, and no change to the #887 decisions recorded in the design's §7.
Follow-up from #887.
Source: Imbad0202/academic-research-skills