Build projects the record; plan review runs iff its verdict routes#54
Open
czpython wants to merge 3 commits into
Open
Conversation
czpython
force-pushed
the
commonzenpython/eng-733-sdk-the-run-record-platform-recorded-typed-history-with
branch
2 times, most recently
from
July 22, 2026 06:01
6824c2d to
17f0477
Compare
Base automatically changed from
commonzenpython/eng-733-sdk-the-run-record-platform-recorded-typed-history-with
to
main
July 22, 2026 06:01
czpython
force-pushed
the
commonzenpython/eng-734-build-project-the-record-plan-review-runs-iff-its-verdict
branch
from
July 22, 2026 06:06
0b6a106 to
3de3203
Compare
czpython
marked this pull request as ready for review
July 22, 2026 06:06
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Lands on #53's run record. Two halves, per the ticket.
The journal loses its mutation half.
BuildJournalis now a frozen dataclass overself.record— pure typed projections, nothing stored, nothing to rebuild:plan= latestPlanData,implementations=list(ImplementationOutput, status="success")(a bailed delivery stays on the record but never counts),evaluations, and the assignee scan over recorded plans.PlanRecord, everyadd_*, the_reviews_at_planwindowing, andreviewer_requirements()are gone; body call sites read as plain agent awaits.HumanFeedbackdied with it: it was a composed bag duplicatingTriageOutputfields (body stored twice) with a status field that never left"pending". The journal now pairs eachrequest_changesreply with the triage that digested it, positionally into plain dicts (zip strict=False— the newest reply is undigested while its own triage agent renders the projection).ReviewWorkmoved tocontracts.pyso the journal can select by its type without a cycle;on_waitis unchanged.Plan review runs iff its verdict routes.
_plan_phasecomputesplan_approval_gate(auto_dispatch_on_plan_approval)once. Gate mode isgenerate → park— the operator is the reviewer and theirrequest_changesnote is the critique channel; the machine reviewer never runs. Auto mode:generate → review → APPROVE → implement, orREQUEST_CHANGES →exactly one redraft (reviewer_notes=grade.body; the bound is a flag, so an empty critique can't loop)→ re-review →park on the second rejection. The operator taking over resets the notes and re-arms a single fresh redraft. Questions always park, in either mode.ReviewOutputis binary (APPROVE | REQUEST_CHANGES+ body), AWRC is deleted from the enum, andassignee_github_loginmoved to the planner's contract (PlanOutput→PlanData; revisions carry None and the journal scan falls through) — the resolution prompt section moved from review_plan.md to generate_plan.md with it.How the critique reaches the operator at the fallback park (the ticket left this open): as ask context.
review()gains an optionalcontext=that lands in the parkedinput_request;get_askalready spreads gate-declared fields, so the plan stays the ask's resolved document and the build page renders the critique beside it.ReviewOutputdeliberately records no artifact — an artifact would displace the plan as the latest and hide the very thing the operator must judge.Templates: generate_plan.md gains the top-level
reviewer_notesblock (StrictUndefined — the one call site always passes it, empty on plain paths); review_plan.md is rewritten for the binary verdict and the fold-once loop ("the plan will NOT be re-generated" is gone); the "Reviewer requirements (active)" section is deleted from _header.md; implement.md, evaluate_implementation.md (six sweeps now, plan-arrives-complete framing), and review_code.md drop every requirements mention.grep -ri "reviewer.requirement|APPROVE_WITH|AWRC"over templates/prompts is zero-hit.Tests: the plan-phase suite drives both modes (reviewer-never-runs, fold-once, exhaustion + re-arm with the context assertion, questions-park, cancel); new
test_build_journal.pycovers the projections and the pairing; the durable stub now returns real contracts so the record's typed projections are exercised end-to-end, and the recovery test crashes twice — once at the plan park, once at the work park with an implementation on the record — asserting zero agent re-invocations across both replays; prompts tests cover the critique block and the assignee-section move.Deploy note: this changes workflow structure. In-flight build runs parked at a question-free plan review recorded
review_planbefore their park; the new body skips it in gate mode, so those runs (and runs whose replay passes through that path) will not replay cleanly under the new image. Same treatment as the extension-identity deploy: drain or cancel in-flight build runs in the window.codex-reviewed: the adversarial pass caught the artifact-displacement problem at the fallback park (fixed with the ask-context channel above), flagged the deployment cutover (the drain note), and called the durable stub's lookalikes too weak to catch a lost-projection regression (now real contracts + the second crash leg).
ENG-734