Repository navigation
Description
[loop-v2-hardening-v1] 4 — Each Developer launch's output schema lists the finding ids of the handoff that turn answers
Tier: 1
Project: cli, vinaya
Type: fix
Objectives
O1. The output schema an Engine Developer launch is given lists, as the finding ids addressedFindingIds may name, exactly the ids of the revision handoff that turn answers: round 2's ids for the turn answering round 2, round 3's for the turn answering round 3; a test drives three review rounds with distinct finding ids through the Engine's actions and asserts the schema built at each Developer launch names that round's ids and no earlier round's.
O2. A Developer turn that answers no review handoff (a CI, conflict, ready-push or gate send-back) is launched with a schema that admits no finding id, the same set its validation accepts; a test asserts the schema and the validation agree for such a turn.
Documentation
processes/vinaya/executing/actions.ts—handedOverIds,validateDeveloperOutputand thevinaya.build-revision-handoffaction, which together decide the ids a turn may name (O1, O2)apps/cli/src/lib/developer-turn-result.ts—developerTurnResultJsonSchema, which turns the ids into an enum bounded by their count (O1, O2)
Planner's rationale
Boundary — The Engine rebuilds the Developer's output schema at every launch from task.developerContext (withTurnSchema in the runner), but developerContext.knownFindingIds is written only inside validateDeveloperOutput, after a turn ends, from that turn's handoff. The launch answering round N's findings therefore gets round N−1's ids in its schema, while its validation reads round N's (handedOverIds); a provider that enforces the schema cannot name a new finding, which is what one run hit in round 3. This task sets the ids from the handoff the next turn will answer, before that turn launches. Pinned files: processes/vinaya/executing/actions.ts, processes/vinaya/tests/round-decisions.test.ts, processes/vinaya/process.yaml, .changeset/developer-schema-current-findings.md. Out: the schema builder in apps/cli, which is correct and stays unchanged; the runner's withTurnSchema; the standalone loop's dispatch, which builds its schema per turn from its own handoff; every importer of a pinned file, which calls it unchanged and is in the Surface only because the importer gate requires it.
Sizing — One verification story: the schema at launch and the validation after the turn accept the same ids. Four pinned files; one failure mode. Size S.
Project(s) + blast radius — Project: cli, vinaya. processes/vinaya/executing/actions.ts runs both Engine Flows, which are re-verified by the test; apps/cli owns the schema builder and the tests that read it, re-verification only.
Dependency rationale — Conflicts-with: #1711 — the harness-kernel move also pins processes/vinaya/executing/actions.ts, processes/vinaya/tests/round-decisions.test.ts and processes/vinaya/process.yaml; three shared files, so they run one after the other. The other tasks of this tranche share only processes/vinaya/process.yaml with this one. No Depends-on: everything this task changes is on the default branch.
Traps to avoid — Do NOT widen the schema to any string to make the ids fit; the enum is what lets the provider refuse an invented id. Do NOT read the ids from the round number; read them from the handoff the turn answers, as validation does. A correction turn keeps the ids of the turn it corrects, as today. Bump the patch version in processes/vinaya/process.yaml. Keep new comments free of Issue and pull-request numbers and tranche slugs.
Suggested agent-class — mid: one state write moved earlier in the Engine's actions, with a multi-round fake test.
Stop-and-escalate — Stop if the ids of the handoff a turn answers cannot be known before that turn launches without a new Flow step; name the step.
Docs to keep coherent — no-doc-surface — the loop specification already says the provider's reply must match the schema it was given and that the controller accepts only the handoff's ids; this task makes the code match that text and adds none.
Check decisions
atta-labs/process-version-bump: bump the patch version inprocesses/vinaya/process.yaml.changeset-coverage: add the pinned changeset.reader-resolvable-prose: new comments carry no Issue or pull-request numbers and no tranche slugs.
Premises
processes/vinaya/executing/actions.tscontainstask.developerContext = { ...task.developerContext, knownFindingIds }processes/vinaya/executing/actions.tscontainsconst stdout = stdoutOf(results['build-revision-handoff'])processes/vinaya/bin/run-engine.tscontainsdeveloperTurnResultJsonSchema(options.taskInput.developerContext)apps/cli/src/lib/developer-turn-result.tscontains.max(context.knownFindingIds.length)
Surface
in: processes/vinaya/executing, processes/vinaya/tests, processes/vinaya/bin, processes/vinaya/loops/dev-review/v2, processes/vinaya, apps/cli/src/lib, apps/cli/tests, .changeset
out: harness, aeg-root, .github, apps/log-server, apps/vinaya-portal
Parts
Part 1 (O1) — The Engine's actions set the Developer context's finding ids from the revision handoff before the turn that answers it launches.
Part 2 (O2) — A send-back that is not a review handoff launches with no finding ids, matching its validation.
Test plan
cd processes/vinaya && bun test tests/round-decisions.test.ts → 0 fail; each launch's schema names the ids of the handoff it answers; a non-review send-back admits none
Stop conditions
- The ids of the handoff a turn answers cannot be known before that turn launches without a new Flow step.
Origin
Principal-directed, 2026-10-29: on the first night of version-2 Engine loops, a round-3 Developer turn could not name a round-2 finding because its schema still listed round 1's ids.
Activity
daniboomerang commentedon Oct 29, 2026
Brief hash: 855383a67623db8f369a7701c052ae51a56fc2e2bd326e63584d20c36ae82e90
For: [model] (coding-agent CLI on a dev machine, dispatched locally, unattended)
Reason: Suggested agent-class — mid: one state write moved earlier in the Engine's actions, with a multi-round fake test.
Owner: the Principal
Goal: Each Developer launch's schema lists the finding ids of the handoff that turn answers
Project: cli, vinaya
Tier: 1
Closes #1740
You are the AEG Developer. Run
bun apps/cli/src/index.ts doctrine --role developer --printand read its output first. Mandatory.Objectives
O1. The output schema an Engine Developer launch is given lists, as the finding ids
addressedFindingIdsmay name, exactly the ids of the revision handoff that turn answers: round 2's ids for the turn answering round 2, round 3's for the turn answering round 3; a test drives three review rounds with distinct finding ids through the Engine's actions and asserts the schema built at each Developer launch names that round's ids and no earlier round's.O2. A Developer turn that answers no review handoff (a CI, conflict, ready-push or gate send-back) is launched with a schema that admits no finding id, the same set its validation accepts; a test asserts the schema and the validation agree for such a turn.
Documentation
processes/vinaya/executing/actions.ts—handedOverIds,validateDeveloperOutputand thevinaya.build-revision-handoffaction, which together decide the ids a turn may name (O1, O2)apps/cli/src/lib/developer-turn-result.ts—developerTurnResultJsonSchema, which turns the ids into an enum bounded by their count (O1, O2)Premises
Checked against the code when this task Issue was cut, and again against the default branch at dispatch — facts, not claims.
processes/vinaya/executing/actions.tscontainstask.developerContext = { ...task.developerContext, knownFindingIds }processes/vinaya/executing/actions.tscontainsconst stdout = stdoutOf(results['build-revision-handoff'])processes/vinaya/bin/run-engine.tscontainsdeveloperTurnResultJsonSchema(options.taskInput.developerContext)apps/cli/src/lib/developer-turn-result.tscontains.max(context.knownFindingIds.length)2. Context — read before doing anything
loop-v2-hardening-v1, task 4, Issue [loop-v2-hardening-v1] 4 — Each Developer launch's schema lists the finding ids of the handoff that turn answers #1740. Branchtask/loop-v2-hardening-v1/4.Depends-on: —,Conflicts-with: #1711.ca981c2858bd54f2f6136ef5cc11ee05532089fd— the checkout's HEAD equaled the remote default branch, and no pinned file below carried an uncommitted change, when these facts were read.task.developerContext(withTurnSchemain the runner), butdeveloperContext.knownFindingIdsis written only insidevalidateDeveloperOutput, after a turn ends, from that turn's handoff. The launch answering round N's findings therefore gets round N−1's ids in its schema, while its validation reads round N's (handedOverIds); a provider that enforces the schema cannot name a new finding, which is what one run hit in round 3. This task sets the ids from the handoff the next turn will answer, before that turn launches. Pinned files:processes/vinaya/executing/actions.ts,processes/vinaya/tests/round-decisions.test.ts,processes/vinaya/process.yaml,.changeset/developer-schema-current-findings.md. Out: the schema builder inapps/cli, which is correct and stays unchanged; the runner'swithTurnSchema; the standalone loop's dispatch, which builds its schema per turn from its own handoff; every importer of a pinned file, which calls it unchanged and is in the Surface only because the importer gate requires it.processes/vinaya/process.yaml. Keep new comments free of Issue and pull-request numbers and tranche slugs.3. Technical dependencies
Dependency rationale —
Conflicts-with: #1711— the harness-kernel move also pinsprocesses/vinaya/executing/actions.ts,processes/vinaya/tests/round-decisions.test.tsandprocesses/vinaya/process.yaml; three shared files, so they run one after the other. The other tasks of this tranche share onlyprocesses/vinaya/process.yamlwith this one. No Depends-on: everything this task changes is on the default branch.4. Technical surface map
Create:
Modify:
Out of surface: harness, aeg-root, .github, apps/log-server, apps/vinaya-portal — a change there, or to any path no Surface
in:glob covers, is still published: the review-loop driver records each such path in the pull request body's beyond-Surface block, and the reviewers judge it like any change.Premise pins
Premise:
5. Pre-flight checks
Step 0 (mandatory, verbatim):
origin/main; branch suffix literal-matches the task id.bun apps/cli/src/index.ts task run), the driver has already run the dispatch-readiness gate plus, on this repository toolchain, its own fuller derivation from its own unsandboxed process before dispatching you (re-derived at render time: it was ready), and dispatches you only when that verdict is READY — a NOT READY verdict refuses the turn before it starts, so being dispatched is the verdict: look for no file and run neither script, whose ownghcall fails inside your sandbox. Working manually, with no driver behind you, fall back toroles/developer.md's own items 3/5/7 prose — each a complete, hand-run forge check in its own right.On any failure: STOP and report.
6. Numbered parts — publish once with
publish_changeswhen every Part is done, thenopen_pull_requestPart 1 (O1): The Engine's actions set the Developer context's finding ids from the revision handoff before the turn that answers it launches.
Files (touches the repo root):
The pre-push hook runs the affected suite on your one push and refuses it on failure — do not run it yourself per Part.
Part 2 (O2): A send-back that is not a review handoff launches with no finding ids, matching its validation.
7. Documentation-update list
.vinaya/doc-ownersderivation matched zero bindings against this task's surface — no mechanically-derived doc updates. Confirm no additional doc artifact applies before treating this list as final.8. Verification before claiming done
run_checksand CI provide the authoritative results. Do not hand-run or paste static-gate commands. Working manually, run this repository's declared typecheck, lint/format, build, and documentation-gate commands yourself.bun apps/cli/src/index.ts doctrine --role developer --printgenuinely satisfied; use the controller'srun_checksresult, hooks, and CI as gate evidence.9. Test Plan
10. Stop conditions
Stop-and-escalate — Stop if the ids of the handoff a turn answers cannot be known before that turn launches without a new Flow step; name the step.
11. Constraints
12. Deliverable
[loop-v2-hardening-v1] 4 — Each Developer launch's schema lists the finding ids of the handoff that turn answersopen_pull_requesttool (title and body); publish your commits withpublish_changesand update the body withupdate_pull_request_body/refresh_evidence— you hold nogh/git pushcredential.publish_changes, when every Part is done; then open the pull request withopen_pull_request. Publish again only to answer review findings or a red gate — a refused hook, a failing check, a merge conflict.bun apps/cli/src/index.ts doctrine --template pr-report --print), withCloses #1740at the top of the header block. This brief stays frozen on the task Issue and never rides in the body.run_checksand CI run it.git diff origin/main...HEAD --statas context only; Surface is judged by the driver'ssurface-scopecheck, never by this hand-run diff. Token use needs no report — the Vinaya log records it.daniboomerang commentedon Oct 29, 2026
The dev-review-loop paused: escalation — the Developer reported the task blocked (preflight_failed): The brief names .changeset/developer-schema-current-findings.md as an existing pinned file, but reading it failed with “No such file or directory”. — Stopped before implementation because a pinned reference file is missing..
No pull request exists yet for this task, so the pause is recorded on this Issue instead.
A Principal ruling is needed before this can continue. Post it as a comment on this Issue whose FIRST line is exactly this marker — the second number is the ordinal, and it must exceed the one this pause recorded:
Then continue with:
The Operator's own
task_resumeclears this pause too, reading that same ruling from this Issue;task_cancelends it instead.daniboomerang commentedon Oct 29, 2026
Decision: proceed as briefed.
Pinned files list every file the task touches, including files it creates.
.changeset/developer-schema-current-findings.mddoes not exist yet because this task adds it: create it with the changeset this change needs. No objective, Surface or scope change.daniboomerang commentedon Oct 29, 2026
The dev-review-loop paused: infrastructure — an uncaught error ended round 1's own processing: ready gate storage cleanup failed: [{"dir":"~/.vinaya/test-tmp/ready-gates/4691b771-1353-4c07-a792-8678ea2cefaa","error":"ownership marker missing; refusing removal"}].
No pull request exists yet for this task, so the pause is recorded on this Issue instead.
A Principal ruling is needed before this can continue. Post it as a comment on this Issue whose FIRST line is exactly this marker — the second number is the ordinal, and it must exceed the one this pause recorded:
Then continue with:
The Operator's own
task_resumeclears this pause too, reading that same ruling from this Issue;task_cancelends it instead.daniboomerang commentedon Oct 29, 2026
Decision: proceed as briefed.
The pause was infrastructure: the ready push's temporary storage lost its ownership marker while other test runs on the same machine swept abandoned fixture folders, so its cleanup refused. Continue the run; the ready push's failing test files are the send-back to answer. No objective, Surface or scope change.