An executable plan for P2B-01..03, grounded in measurement of what phase 2a
actually left behind rather than in restating the contracts.
The design turns on one question: who writes the completion manifest. If the
watcher computes the hash itself, the manifest only attests that the watcher saw
a stable file, which is the self-certification Codex rejected as R1 last round.
So the side that knows it finished declares it, and the watcher re-derives the
hash rather than trusting the declaration.
That choice makes P2B-03's "preserve the explicit path completely" fall out for
free instead of needing a branch: an agent that declares nothing leaves no
manifest, and a missing manifest already holds today. Verified against the
current policy.
Four measurements shaped the rest. Nothing in the tree writes or reads a
manifest, so the protocol is new in full. Records carry iteration but never
attempt_id, and the engine silently substitutes one for the other -- they agree
today only by coincidence of the wrapper's flow, and the auto-completion gate
hangs off that value, so the plan asks for an explicit decision and reviewer
sign-off before any code is written. The pending-notification contract forbids a
separate outbox, so the intent rides in the record the transaction already
writes. And only three backends have observed evidence of a quiescent state, so
the allowlist has a factual basis instead of an optimistic one.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UrDNJkHmm18uu7n7JwV5Qd
An executable plan for P2A-01..04, grounded in live measurement rather than
restating the phase-0 contracts.
Four measurements shaped the design:
* The job record has no attempt_id, agent_session_uuid or
pane_process_generation, so the four-fold attribution contract has nowhere
to live in it. Phase 1 froze the record schema and P2A-03 forbids registry
writes outright, so attribution goes in a shadow-owned store and the record
schema question is deferred to 2b.
* Every status write is already inside python: the shell side only reads. A
single boundary can therefore cover all writers.
* update_job_status merges fields unconditionally, and pick_pending is a
second path around it. pick_pending is not wrong -- it filters on pending
under the lock, so it is already a correct swap -- it is a duplicate. That
is the O-1 shape from phase 1, where the copy that drifts is the one that
breaks. So P2A-01 generalises the swap that exists rather than inventing one.
* herdr's wait timeout is milliseconds. Phase 0 recorded it correctly; the
plan names the parameter timeout_ms so the unit cannot be misread.
Two invariants are made structural rather than promised. The shadow runner is
never given a reference to the engine, so it cannot write; and the gate hashes
the whole registry directory before and after a full run, which is a stronger
claim than "status was not changed". Lock discipline follows a pattern already
in the tree: pick_pending finishes its record write under the lock and mirrors
to the audit log after releasing it.
Carries the three phase-1 handoffs forward with explicit gates: no daemon spawn
in 2a so preexec_fn stays unreachable, no frozen-helper calls so the interpreter
resolution gap stays dormant, and a coverage assertion for the connection
fingerprint's field list.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UrDNJkHmm18uu7n7JwV5Qd