Skip to content

Run state: state_version, and manifest meta passed through to run and task state - #151

Open
boydwold wants to merge 3 commits into
NateBJones-Projects:mainfrom
boydwold:referee/state-version-meta
Open

boydwold wants to merge 3 commits into
NateBJones-Projects:mainfrom
boydwold:referee/state-version-meta

Conversation

@boydwold

@boydwold boydwold commented Oct 9, 2026

Copy link
Copy Markdown

Tools outside Ringer that read ~/.ringer/runs/<run_id>.json have two gaps today:

  • They cannot tell which version of the run state format they are reading. A reader that misreads a changed field could show a run as passed when it failed, which breaks "displayed data must be true".
  • They cannot link a work order back to where it came from. I run Ringer under an orchestrator that plans work in OpenSpec, and a local review app (Referee) reads Ringer's run state to show which task and scenario each work order proves. Run names and task keys cannot carry that link.

This PR adds two small, opt-in parts of one contract for readers of the run state:

  • state_version in the run state (now 1). A reader can refuse a version it does not know. The constant's comment says to bump it whenever a field that readers use changes meaning or shape.
  • meta in the manifest, at run level and per task: an optional JSON object that Ringer copies into the run state untouched (meta on the run and on each task). Ringer never reads it. Each is capped at 16 KB, so a manifest cannot bloat the state file. A non-object or an oversized meta is a manifest error with a clear message.

Backward compatible: meta is optional and shows as null when absent, and manifests without it run as before.

Proof: tests/test_state_meta.py (13 tests) covers parsing, the size cap, the copy, Manifest.from_path, the snapshot, and the written file. The full suite passes locally on Linux, except test_hud_single_tab.test_dead_then_alive_opens_once_after_spawn, which also fails on current main without this change. The README manifest table documents both fields, and the Contributors section has the credit line that test_contributors requires.

Happy to split this into two PRs (state_version, then meta) if you prefer.

boydwold and others added 2 commits October 8, 2026 18:02
…nd task level

meta is an opaque JSON object (at most 16 KB each) that Ringer copies into the
run state untouched, so outside tools such as Referee can link a work order to
the OpenSpec change, task, and scenarios it came from. state_version lets those
readers refuse a format they do not know.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@boydwold
boydwold force-pushed the referee/state-version-meta branch from 0912cb6 to 9c4b324 Compare October 9, 2026 00:04
with_max_parallel built a new Manifest field by field and left out meta, so
ringer.py run --max-parallel N lost the run-level meta. It now uses
dataclasses.replace, which keeps every field. Found by a plan review.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@boydwold

boydwold commented Oct 9, 2026

Copy link
Copy Markdown
Author

I added a fix that a review found. ringer.py run --max-parallel N lost the run-level meta, because with_max_parallel rebuilt the manifest field by field and left meta out. It now uses dataclasses.replace, which keeps every field.

The new test test_max_parallel_keeps_run_meta fails before the fix and passes after it. The rest of the suite is unchanged. The only failure is the existing test_hud_single_tab one, which also fails on main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant