@attalabs/vinaya 0.24.1 → 0.26.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +26 -3
  2. package/aeg-root/contracts/architect-planner.md +5 -5
  3. package/aeg-root/contracts/developer-reviewer.md +10 -7
  4. package/aeg-root/contracts/planner-developer.md +142 -0
  5. package/aeg-root/contracts/reviewer-archivist.md +2 -2
  6. package/aeg-root/contracts/tranche-archivist-planner.md +12 -11
  7. package/aeg-root/enforcement.md +25 -11
  8. package/aeg-root/process.md +53 -75
  9. package/aeg-root/roles/archivist.md +3 -3
  10. package/aeg-root/roles/developer.md +30 -24
  11. package/aeg-root/roles/planner.md +100 -21
  12. package/aeg-root/roles/principal.md +14 -11
  13. package/aeg-root/roles/reviewer.md +33 -17
  14. package/aeg-root/roles/security.md +28 -13
  15. package/aeg-root/roles/tranche-archivist.md +2 -2
  16. package/aeg-root/skills/aeg/SKILL.md +5 -5
  17. package/aeg-root/skills/aeg-roles/SKILL.md +7 -7
  18. package/aeg-root/state-machine.md +36 -35
  19. package/aeg-root/task-model.md +3 -3
  20. package/aeg-root/templates/brief-template.md +22 -6
  21. package/aeg-root/templates/issue-rationale-template.md +35 -2
  22. package/aeg-root/templates/pr-report-template.md +5 -13
  23. package/aeg-root/tranche-model.md +21 -21
  24. package/dist/checks/bin/check-body-bare-digits.js +684 -142
  25. package/dist/checks/bin/check-branch-topology.js +741 -88
  26. package/dist/checks/bin/check-brief-shape.js +708 -83
  27. package/dist/checks/bin/check-changeset-coverage.js +1445 -149
  28. package/dist/checks/bin/check-closes-n.js +741 -88
  29. package/dist/checks/bin/check-coherence.js +808 -149
  30. package/dist/checks/bin/check-dead-branch-push.js +617 -81
  31. package/dist/checks/bin/check-dispatch-readiness.js +811 -152
  32. package/dist/checks/bin/check-doc-coverage-push.js +1445 -149
  33. package/dist/checks/bin/check-doc-coverage.js +1447 -151
  34. package/dist/checks/bin/check-doctrine-no-procedures.js +684 -142
  35. package/dist/checks/bin/check-doctrine-portability.js +1445 -149
  36. package/dist/checks/bin/check-evidence-fresh.js +684 -142
  37. package/dist/checks/bin/check-exec-bits.js +1445 -149
  38. package/dist/checks/bin/check-first-push-dispatch.js +808 -149
  39. package/dist/checks/bin/check-issue-assignment.js +741 -88
  40. package/dist/checks/bin/check-main-branch-refusal.js +618 -82
  41. package/dist/checks/bin/check-no-disk-state.js +617 -81
  42. package/dist/checks/bin/check-pr-premise-reassert.js +5401 -0
  43. package/dist/checks/bin/check-pr-report-density.js +617 -81
  44. package/dist/checks/bin/check-quoted-command.js +1443 -147
  45. package/dist/checks/bin/check-reader-resolvable-prose.js +1481 -153
  46. package/dist/checks/bin/check-registry-gates.js +659 -85
  47. package/dist/checks/bin/check-retired-vocabulary.js +1443 -147
  48. package/dist/checks/bin/check-review-gate.js +758 -145
  49. package/dist/checks/bin/check-single-plan-pr.js +617 -81
  50. package/dist/checks/bin/check-surface-scope.js +5722 -0
  51. package/dist/checks/bin/check-test-plan.js +617 -81
  52. package/dist/checks/bin/check-token-collection-wired.js +617 -81
  53. package/dist/checks/bin/check-token-report.js +629 -88
  54. package/dist/checks/bin/check-workspace-escape.js +1443 -147
  55. package/dist/index.js +8548 -4335
  56. package/package.json +1 -1
  57. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/brief-render.ts +2 -2
  58. package/studio-standalone/_node_modules/@attalabs/aeg-core/src/main-branch-refusal.ts +26 -1
  59. package/studio-standalone/apps/vinaya-studio/web/.next/BUILD_ID +1 -1
  60. package/studio-standalone/apps/vinaya-studio/web/.next/build-manifest.json +3 -3
  61. package/studio-standalone/apps/vinaya-studio/web/.next/prerender-manifest.json +3 -3
  62. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.html +1 -1
  63. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.rsc +1 -1
  64. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  65. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  66. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  67. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  68. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  69. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page/server-reference-manifest.json +2 -2
  70. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  71. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  72. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/api/coherence/route.js.nft.json +1 -1
  73. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page/server-reference-manifest.json +2 -2
  74. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js.nft.json +1 -1
  75. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page_client-reference-manifest.js +1 -1
  76. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page/server-reference-manifest.json +2 -2
  77. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js.nft.json +1 -1
  78. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page_client-reference-manifest.js +1 -1
  79. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page/server-reference-manifest.json +2 -2
  80. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js.nft.json +1 -1
  81. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page_client-reference-manifest.js +1 -1
  82. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page/server-reference-manifest.json +2 -2
  83. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js.nft.json +1 -1
  84. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page_client-reference-manifest.js +1 -1
  85. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page/server-reference-manifest.json +2 -2
  86. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js.nft.json +1 -1
  87. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page_client-reference-manifest.js +1 -1
  88. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page/server-reference-manifest.json +2 -2
  89. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js.nft.json +1 -1
  90. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page_client-reference-manifest.js +1 -1
  91. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page/server-reference-manifest.json +2 -2
  92. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js.nft.json +1 -1
  93. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page_client-reference-manifest.js +1 -1
  94. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page/server-reference-manifest.json +2 -2
  95. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js.nft.json +1 -1
  96. package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page_client-reference-manifest.js +1 -1
  97. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/1q96_modules_@clerk_nextjs_dist_esm_app-router_client_keyless-creator-reader_0lom2js.js +1 -1
  98. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0053k9k._.js +1 -1
  99. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0112h-k._.js +1 -1
  100. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0o771t1._.js +1 -1
  101. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__1pndh3_._.js → [root-of-the-server]__0p8q38b._.js} +1 -1
  102. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0puovz5._.js +1 -1
  103. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1hs0dcu._.js +1 -1
  104. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1wc4-ip._.js +1 -1
  105. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_03x_w6q._.js +1 -1
  106. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0gvm3og._.js +1 -1
  107. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0lwxg63._.js +1 -1
  108. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0wxycau._.js +1 -1
  109. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1n0cnq-._.js +1 -1
  110. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1vo08dj._.js +2 -2
  111. package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/packages_ui_topbar_index_tsx_1h1gs1y._.js +1 -1
  112. package/studio-standalone/apps/vinaya-studio/web/.next/server/middleware-build-manifest.js +3 -3
  113. package/studio-standalone/apps/vinaya-studio/web/.next/server/pages/500.html +1 -1
  114. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.js +1 -1
  115. package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.json +3 -3
  116. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3m1kgax7j2vgs.js → 0bn8c8v5q429o.js} +1 -1
  117. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0doqwpd81sjzn.js → 0keji7wvbe1d1.js} +1 -1
  118. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/1maoxbrl3pv5d.css +1 -0
  119. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{1uogpj5w2n5ju.js → 3-6a3tinbdb-7.js} +1 -1
  120. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0zebsmmk1bvnb.js → 3_9xytdmiv1xi.js} +4 -4
  121. package/studio-standalone/apps/vinaya-studio/web/package.json +2 -2
  122. package/aeg-root/contracts/brief-developer.md +0 -141
  123. package/aeg-root/contracts/planner-brief.md +0 -130
  124. package/aeg-root/roles/brief-author.md +0 -114
  125. package/aeg-root/skills/brief-authoring/SKILL.md +0 -509
  126. package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/3qc67qhcvbg0o.css +0 -1
  127. /package/studio-standalone/_node_modules/@attalabs/vinaya/studio-standalone/_node_modules/@attalabs/vinaya/studio-standalone/_node_modules/@attalabs/vinaya/studio-standalone/_node_modules/@attalabs/{aeg-core → vinaya/studio-standalone/_node_modules/@attalabs/aeg-core}/bin/verify-coherence.ts +0 -0
  128. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{QY2GhiI47-765D9DHGy1I → DMofV2-9FrHE7100GfrpI}/_buildManifest.js +0 -0
  129. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{QY2GhiI47-765D9DHGy1I → DMofV2-9FrHE7100GfrpI}/_clientMiddlewareManifest.js +0 -0
  130. /package/studio-standalone/apps/vinaya-studio/web/.next/static/{QY2GhiI47-765D9DHGy1I → DMofV2-9FrHE7100GfrpI}/_ssgManifest.js +0 -0
@@ -5,30 +5,28 @@ sidebar_title: Process
5
5
 
6
6
  This document describes how work flows through the AEG operational model — from the moment the Principal has an idea to the moment that work merges to `main` with all specs and skills updated.
7
7
 
8
- It is the canonical "how do we actually work?" document. Every other PM doc (`state-machine.md`, `tranche-model.md`, role docs, `brief-authoring` skill) describes a slice of this process. This document stitches them together into a single readable walkthrough.
8
+ It is the canonical "how do we actually work?" document. Every other PM doc (`state-machine.md`, `tranche-model.md`, role docs) describes a slice of this process. This document stitches them together into a single readable walkthrough.
9
9
 
10
- If you are starting a new session and need to understand the workflow, read this first. Then the `aeg` skill's session-start forge queries for orientation, then the role doc that applies to you, then any project-specific specs.
10
+ If you are starting a new session and need to understand the workflow, read this first. Then the `aeg` skill's session-start forge queries for orientation, then the role doc that applies to you, then any project-specific specs. Coined vocabulary used below (Dispatch, Impact tier, Ratification, …) is defined in the glossary at aeg-root/glossary.md.
11
11
 
12
12
  ---
13
13
 
14
14
  ## Where tasks come from: the tranche
15
15
 
16
- The thirteen phases below are the **per-task** flow. Tasks do not appear from nowhere — they are produced by the **Planner** (a Planner / Brief Author mode) when a tranche is planned: the Planner turns an intent plus a slice of tickets into a set of **forge Issues** (one per task) plus a thin topology file declaring their `depends-on` / `conflicts-with` edges (`tranche-model.md`, `roles/planner.md`). Each Issue that enters the flow below is a task the Planner already shaped.
16
+ The phases below are the **per-task** flow. Tasks do not appear from nowhere — they are produced by the **Planner**'s plan act when a tranche is planned: the Planner turns an intent plus a slice of tickets into a set of **forge Issues** (one per task) plus a thin topology file declaring their `depends-on` / `conflicts-with` edges (`tranche-model.md`, `roles/planner.md`). Each Issue that enters the flow below is a task the Planner already shaped — its rationale and judgment sections already written onto the Issue at plan time.
17
17
 
18
18
  **Status is never stored.** Throughout every phase, a task's status is *derived* from the forge — Issue open/assigned, branch existence, PR open, review decision, merge — never written to a label or a file. When a phase below says a task "becomes in-review," it means *a PR was opened*, not that anyone set a status field.
19
19
 
20
20
  ---
21
21
 
22
- ## The thirteen phases
22
+ ## The phases
23
23
 
24
- Every piece of work moves through some subset of these. Trivial work (Tier 0) skips most; complex work (Tier 3) hits all and may loop back from review.
24
+ Every piece of work moves through some subset of these. Trivial work (Tier 0) skips most; complex work (Tier 3) hits all and may loop back from review. Numbered 1–13 for historical continuity with every cross-reference below and across `aeg-root/**`, but **not thirteen distinct phases any more**: the former Phases 3–5 (brief authoring, brief validation, dispatch) collapsed into one Planner phase, still numbered 3, performed by one command (`vinaya task dispatch`) — see Phase 3 below for why the numbers 4 and 5 are retired rather than reused. Every phase from 6 onward keeps its original number unchanged, so no downstream cross-reference in the doctrine tree needed to move.
25
25
 
26
26
  ```
27
27
  1. Idea origination
28
28
  2. Pressure-testing (optional; high-stakes only)
29
- 3. Brief authoring (just-in-time)
30
- 4. Brief validation
31
- 5. Dispatch
29
+ 3. Dispatch (brief authoring + validation + dispatch, one Planner phase — 4 and 5 retired into this one)
32
30
  6. Execution
33
31
  7. Escalation (optional; only when Developer blocks)
34
32
  8. Task Done verification
@@ -49,11 +47,11 @@ After merge, the **Archivist** runs close-out (`roles/archivist.md`). That's the
49
47
 
50
48
  **Who:** Principal and Planner.
51
49
 
52
- The Principal brings an idea. The Brief Author pressure-tests, pushes back, surfaces related decisions, checks whether it's already specced. The Brief Author's job is **not** to immediately agree and plan — it's to:
50
+ The Principal brings an idea. The Planner pressure-tests, pushes back, surfaces related decisions, checks whether it's already specced. The Planner's job here is **not** to immediately agree and plan — it's to:
53
51
  - Read the relevant specs to confirm the idea isn't already settled
54
52
  - Push back if it's wrong, premature, or duplicative
55
53
  - Identify the impact tier (0 / 1 / 3) — this drives everything downstream
56
- - Identify the Type 1 (irreversible — Principal ratifies) vs Type 2 (reversible — Brief Author ratifies) profile
54
+ - Identify the Type 1 (irreversible — Principal ratifies) vs Type 2 (reversible — Planner ratifies) profile
57
55
 
58
56
  If already locked or specced, the conversation ends here. If genuinely new, it produces a shared understanding of what the work is, why now, its tier, and its decision profile — which the Planner then turns into Issues (the tranche).
59
57
 
@@ -65,76 +63,56 @@ If already locked or specced, the conversation ends here. If genuinely new, it p
65
63
 
66
64
  ## Phase 2: Pressure-testing (optional)
67
65
 
68
- **When:** high-stakes only — architectural locks, project-direction shifts, decisions blocking weeks of downstream work, or when the Principal's instinct and the Brief Author's read disagree. **Not** for tactical decisions, naming, or style. The Principal may waive it and ratify in-session (the pull request notes the skip, for audit honesty).
66
+ **When:** high-stakes only — architectural locks, project-direction shifts, decisions blocking weeks of downstream work, or when the Principal's instinct and the Planner's read disagree. **Not** for tactical decisions, naming, or style. The Principal may waive it and ratify in-session (the pull request notes the skip, for audit honesty).
69
67
 
70
- **Who:** Brief Author orchestrates; external AI reviewers (vendor-diverse — independently hosted, each from a provider other than the one authoring the brief) participate via pasted briefs.
68
+ **Who:** Planner orchestrates; external AI reviewers (vendor-diverse — independently hosted, each from a provider other than the one drafting the brainstorming brief) participate via pasted briefs.
71
69
 
72
- The Brief Author writes a brainstorming brief (idea, sketch, alternatives, what to pushback on), pairs it with `reviewer-prompt.md`, and pastes to each reviewer. The Brief Author synthesizes. Converge on a flaw → back to Phase 1. Validate → proceed. **Max two rounds** — if two don't converge, the issue is framing, not a third round.
70
+ The Planner writes a brainstorming brief (idea, sketch, alternatives, what to pushback on), pairs it with `reviewer-prompt.md`, and pastes to each reviewer. The Planner synthesizes. Converge on a flaw → back to Phase 1. Validate → proceed. **Max two rounds** — if two don't converge, the issue is framing, not a third round.
73
71
 
74
72
  This phase pressure-tests an *idea*; Phase 10 reviews *shipped code*. Different things.
75
73
 
76
- **Exit:** Brief Author and Principal agree the direction holds.
74
+ **Exit:** Planner and Principal agree the direction holds.
77
75
 
78
76
  ---
79
77
 
80
- ## Phase 3: Brief authoring (just-in-time)
78
+ ## Phase 3: Dispatch (brief authoring + validation + dispatch)
81
79
 
82
- **Who:** Planner / Brief Author in Brief Author mode.
80
+ **Who:** Planner, in its dispatch act (`roles/planner.md` § The dispatch act).
83
81
 
84
- When a task is picked up for execution, the Brief Author writes its brief **just-in-time, not at plan time** following the `brief-authoring` skill. The brief MUST include:
85
- - Impact tier (0 / 1 / 3)
86
- - Type 1 / Type 2 declaration if architectural decisions are expected
82
+ **Formerly three phases (brief authoring, brief validation, dispatch); now one.** The brief is no longer hand-authored just-in-time by a separate Brief Author role its judgment content (the eight-field rationale, `## Objectives`, and the four judgment sections `## Surface`/`## Parts`/`## Test plan`/`## Stop conditions`) was already written onto the task Issue at plan time (Phase 1), and validated then, by the same ring-0 creation gate and R1 continuous check that grade every open task Issue (`roles/planner.md` § Rationale grammar). What used to be three sequential human/CI steps is now one mechanical render plus one gate check, both performed by a single command.
83
+
84
+ Before dispatching a task, the Planner checks four gates (`roles/planner.md` § The dispatch act):
85
+ 1. **Issue exists** — a real forge Issue number, not `#TBD`, not blank.
86
+ 2. **Dependencies merged** — every `depends-on` task's PR is on `main`.
87
+ 3. **No open conflicting sibling** — no `conflicts-with` task has an open PR.
88
+ 4. **Render complete** — the brief render can derive every mechanical section from the Issue and the tree with no gap.
89
+
90
+ `vinaya check dispatch-readiness`, run against the task, re-derives gates 1–3 mechanically in one command.
91
+
92
+ **Running the dispatch:** `vinaya task dispatch <tranche> <n> [--agent claude | codex | gemini]` performs the whole phase once the gates pass: it renders the brief (the same render `brief render` uses, from `aeg-root/templates/brief-template.md` and every derivable fact), posts it once, frozen, as the task Issue's own `aeg:brief:v1` comment, then — with `--agent` — starts the Developer through `dispatchRole`. Without `--agent` it prints the rendered brief and the manual dispatch instruction and exits `0`, so a human can paste it instead. The brief MUST include (all mechanically derived or refused on):
93
+ - Impact tier (0 / 1 / 3), rendered from the Issue's tier declaration
94
+ - Type 1 / Type 2 declaration if architectural decisions are expected, gated at dispatch (a PENDING Type 1 decision blocks dispatch)
87
95
  - `principal_delegate:` if the work runs while the Principal is offline
88
96
  - Spike flag (`spike: true`) if exploratory
89
- - The mandatory worktree-first Step 0 (`git worktree add .worktrees/task/<tranche>/<n> -b task/<tranche>/<n> origin/main` — no exceptions)
90
- - An explicit documentation-update list tied to the tier
97
+ - The mandatory worktree-first Step 0 (`git worktree add .worktrees/task/<tranche>/<n> -b task/<tranche>/<n> --no-track origin/main` — no exceptions), rendered from the task's forge-derived branch id
98
+ - An explicit documentation-update list tied to the tier, mechanically derived against `.vinaya/doc-owners`
91
99
  - Optional `Ticket:` (reference-only provenance) and, in a multi-project repo, `Project:` (resolves against `projects.md`)
92
100
  - Clear scope, stop conditions, Task Done checklist
93
101
  - A deliverable section stating "done" means "passed Phase 11 verification," not "PR opened"
94
102
 
95
- A brief is self-contained and executable without further conversation. If it needs clarifying questions, it's incomplete.
103
+ A brief with any `[NEEDS CLARIFICATION: …]` marker left in it is not dispatched — the Planner resolves the ambiguity on the Issue's rationale (or puts it to the Principal) and re-renders. A brief is self-contained and executable without further conversation.
96
104
 
97
- **Where the brief lives:** it is pasted to the Developer and will land in the **PR body** at Phase 9. It is **not** committed and **not** put in the Issue body — the Issue (created by the Planner) holds task identity + metadata only. A brief in the Issue would age before work starts.
105
+ **Where the brief lives:** the task Issue's own `aeg:brief:v1` comment, posted once, frozen, before the Developer starts never in the PR body, which carries only the Developer's report. It is **not** committed and **not** put in the Issue's own body — the Issue body (written by the Planner at plan time) holds task identity + metadata + the rationale + judgment sections; the brief is a rendered comment on it, not a field of it.
98
106
 
99
107
  **Artifacts:** the brief (a markdown block, not a committed file). The task's Issue already exists from tranche planning.
100
108
 
101
- Before dispatch, a fresh-context Reviewer runs **Brief review mode** (`roles/reviewer.md`) on the brief itself — a separate, time-boxed pass from the post-dispatch code review, under five minutes, returning one line, `BRIEF: READY` or `BRIEF: NOT READY`, with findings limited to two classes: a contradiction between two of the brief's own sentences, or a design the brief specifies that the party it constrains can defeat or that fails on an input the brief never named. `BRIEF: NOT READY` returns the brief to its author rather than letting it reach dispatch.
102
-
103
- **Exit:** the brief is well-formed, has passed Brief review mode, and is ready to dispatch.
104
-
105
- ---
106
-
107
- ## Phase 4: Brief validation
108
-
109
- **Who:** Archivist gate (automated) + the Developer's own entry gate.
110
-
111
- Before work begins, the brief is checked for well-formedness:
112
- - `tier:` present and valid; brief structure follows the skill (scope, stop conditions, deliverable)
113
- - `principal_delegate:` valid if declared
114
- - `Project:` (if present) resolves against the registry
115
- - No obvious contradiction with the ratified specs (string-match heuristic)
116
- - The task's Issue carries only execution metadata — **no** planning fields (priority/estimates/points), which the required Issue template + a CI check reject
117
-
118
- If it fails, it's not dispatchable until fixed. The Developer also re-checks well-formedness as its entry gate (`roles/developer.md`) — a malformed brief is refused, not guessed at. (Brief Validation is a real blocking gate — the `Brief Validation` step (9/9) of the `aeg-gate-suite` job; see `state-machine.md` for mechanically-enforced vs trusted.)
119
-
120
- **Exit:** the brief is well-formed and dispatchable.
121
-
122
- ---
123
-
124
- ## Phase 5: Dispatch
125
-
126
- **Who:** Principal (or delegated Brief Author within ratification-window scope), by hand or via an automation layer.
127
-
128
- Dispatch starts the task. There are two equivalent routes:
129
-
130
- - **Manual:** the Principal pastes the brief into the coding agent. The brief's worktree-first Step 0 makes the Developer create its own worktree (`.worktrees/task/<tranche>/<n>/`, branch `task/<tranche>/<n>`, from `origin/main`) as its first action.
131
- - **Automated:** an automation layer creates the worktree, generates the agent's config, spawns the Developer in it, and streams progress. This is a convenience; the semantics are identical to manual.
109
+ Before dispatch, a fresh-context Reviewer runs **Brief review mode** (`roles/reviewer.md`) on the rendered brief — a separate, time-boxed pass from the post-dispatch code review, under five minutes, returning one line, `BRIEF: READY` or `BRIEF: NOT READY`, with findings limited to two classes: a contradiction between two of the brief's own sentences, or a design the brief specifies that the party it constrains can defeat or that fails on an input the brief never named. `BRIEF: NOT READY` returns the rationale to the Planner rather than letting the render reach dispatch.
132
110
 
133
- Either way: **before starting, the Developer checks the dispatch gates against the forge** — every `depends-on` task's PR merged, no `conflicts-with` sibling's PR open. If a gate isn't satisfied, it does not start (the task serializes). Opening the branch *is* the `todo → in-flight` transition; nobody writes a status label.
111
+ Once dispatched: **before starting, the Developer independently re-checks the same dispatch gates against the forge** (`roles/developer.md` entry gate) — every `depends-on` task's PR merged, no `conflicts-with` sibling's PR open, the branch-name suffix literal-matching the forge-derived id. If a gate isn't satisfied, it does not start (the task serializes). Opening the branch *is* the `todo → in-flight` transition; nobody writes a status label.
134
112
 
135
113
  The branch name `task/<tranche>/<n>` is the convention that links the task to its branch and PR, so any role can derive its live status with one forge query.
136
114
 
137
- **Exit:** the Developer is working in its worktree.
115
+ **Exit:** the brief is rendered, has passed Brief review mode, is posted frozen on the Issue, and the Developer is working in its worktree.
138
116
 
139
117
  ---
140
118
 
@@ -158,15 +136,15 @@ The Developer cannot author its own briefs, expand scope without escalation, mod
158
136
 
159
137
  The Developer escalates through the escalation mechanism — a manual escalation note, or, if dispatched by an automation layer, its request-input mechanism — tagged with a `severity` that routes it:
160
138
 
161
- - `severity: execution` → Brief Author. Most common: a deprecated dependency, an unanticipated flag, a "null or throw?" call.
162
- - `severity: strategy` → Brief Author. Less common: the brief's approach has a structural problem; the work touches an undiscussed area.
139
+ - `severity: execution` → Planner. Most common: a deprecated dependency, an unanticipated flag, a "null or throw?" call.
140
+ - `severity: strategy` → Planner. Less common: the brief's approach has a structural problem; the work touches an undiscussed area.
163
141
  - `severity: product` → Principal. Rare: user-visible behavior the brief didn't address; a Type 1 decision is required.
164
142
 
165
143
  The task is marked `blocked` (an `aeg:blocked` label — the one status with no native forge fact) until a reply arrives. The responder (Planner or Principal) formulates a reply and the Developer resumes.
166
144
 
167
145
  **Type 1 during execution:** if the question needs an irreversible decision and the Principal isn't available, the Issue/PR stays labeled `needs:principal-input`; the next window resolves it. The Developer may terminate and resume via a follow-up dispatch after the window.
168
146
 
169
- **Brief amendment:** if the brief itself is wrong in a way that blocks all paths, the Brief Author issues an amendment (logged as a separate event, not a brief edit — briefs are frozen after dispatch) or kills the task.
147
+ **Brief amendment:** if the brief itself is wrong in a way that blocks all paths, the Planner issues an amendment (logged as a separate event, not a brief edit — briefs are frozen after dispatch) or kills the task.
170
148
 
171
149
  **Exit:** the Developer is unblocked and resumes.
172
150
 
@@ -193,7 +171,7 @@ Before opening the PR, the Developer runs the tier-appropriate Task Done checkli
193
171
 
194
172
  The Developer opens a PR with:
195
173
  - Title in commitlint format (`Type: Subject`)
196
- - **The brief pasted into the body** — its permanent home, read by the Reviewer and Archivist
174
+ - **No brief in the body at all** — its permanent home is the task Issue's frozen `aeg:brief:v1` comment (posted at Phase 3, before the Developer ever started), which is where the Reviewer and Archivist read it
197
175
  - A `Tier:` declaration (`Tier: 0|1|3`) so verify-docs reads the correct tier
198
176
  - `Closes #N` linking the task's Issue (so the merge auto-closes it)
199
177
  - Body following the PR template (what shipped, validated mechanism, what's not in scope, next steps)
@@ -208,20 +186,20 @@ CI runs typecheck, lint, tests, `verify-docs` (the load-bearing doc gate — fai
208
186
 
209
187
  ## Phase 10: Review
210
188
 
211
- Two stages: independent **agent passes** (fresh-context), then **human reviews** (Principal + Brief Author). Agent passes run first and feed the human reviews — they do not replace them.
189
+ Two stages: independent **agent passes** (fresh-context), then **human reviews** (Principal + Planner). Agent passes run first and feed the human reviews — they do not replace them.
212
190
 
213
191
  ```
214
- code-reviewer pass → security pass → Principal code review → Brief Author spec review → merge
192
+ code-reviewer pass → security pass → Principal code review → Planner spec review → merge
215
193
  ```
216
194
 
217
195
  ### Stage A — Agent review passes
218
196
 
219
- Each pass is a **separate fresh-context invocation** with no memory of writing the code (the independence rule). Manual: the Principal pastes the review prompt. Automated: the automation layer dispatches the `code-reviewer` and `security-reviewer` passes. The agent reads its role doc + the PR diff + **the brief in the PR body**, and emits a structured verdict. Review agents do not edit code, do not merge, and do not write status.
197
+ Each pass is a **separate fresh-context invocation** with no memory of writing the code (the independence rule). Manual: the Principal pastes the review prompt. Automated: the automation layer dispatches the `code-reviewer` and `security-reviewer` passes. The agent reads its role doc + the PR diff + **the brief, read from the task Issue's frozen `aeg:brief:v1` comment**, and emits a structured verdict. Review agents do not edit code, do not merge, and do not write status.
220
198
 
221
199
  1. **Code-reviewer pass** — `roles/reviewer.md`. Brief conformance, scope violations, test honesty, code quality, doc coupling, lock awareness, multi-project reach. Emits `VERDICT: APPROVE | REQUEST CHANGES` (BLOCKER / MAJOR / MINOR).
222
200
  2. **Security pass** — `roles/security.md`. Secret leakage, BYOK/crypto, auth/permissions, MCP/agent-tooling exposure, injection surfaces, dependency risk. Runs a config-security scan over the agent/MCP/hook config when that config is touched. Emits `VERDICT: PASS | FAIL` (CRITICAL / HIGH / MEDIUM / LOW).
223
201
 
224
- A BLOCKER (code) or CRITICAL/HIGH (security) returns the PR to the Developer, who fixes on the **same branch**; the pass re-runs. (Pushing fixes returns the PR's review decision to open — the `changes-requested → in-review` transition, derived.) A verdict binds to the head it judged; a push landing after the newest verdict's judged head voids it and is named as such: `vinaya review status` prints `push after verdict — re-review required`, and merge waits on a fresh review round. An escalation (`--escalate authority | strategy | product`) is its own review outcome, never a finding — it routes to Brief Author (`strategy`) or Principal (`authority`/`product`).
202
+ A BLOCKER (code) or CRITICAL/HIGH (security) returns the PR to the Developer, who fixes on the **same branch**; the pass re-runs. (Pushing fixes returns the PR's review decision to open — the `changes-requested → in-review` transition, derived.) A verdict binds to the head it judged and the objectives list it judged against; a push or an objectives edit including a mid-PR scope change made through `vinaya issue objectives edit` — voids the verdict, and a body edit alone changes nothing the gate reads. A voided verdict is named as such: `vinaya review status` prints `push after verdict — re-review required` for the head case, `objectives moved — re-review required` for the objectives case, and merge waits on a fresh review round either way. An escalation (`--escalate authority | strategy | product`) is its own review outcome, never a finding — it routes to Planner (`strategy`) or Principal (`authority`/`product`).
225
203
 
226
204
  **A fix commit adds no mechanism beyond what the finding names.** The finding bounds the fix: a flag, a gate, a window, a config knob or a second code path that the finding did not ask for is new design, arriving inside a round that exists to close a defect and reviewed by nobody as design. A finding that genuinely cannot be answered without new mechanism is not a fix at all — it is escalated (`--escalate strategy`) and waits, and the mechanism it needs enters the work the way every other design does: as a constraint amended into the next brief. This is the round-count rule's twin. Rounds multiply when each one both closes something and opens something; a round that only closes is a round the loop can converge out of.
227
205
 
@@ -229,7 +207,7 @@ A BLOCKER (code) or CRITICAL/HIGH (security) returns the PR to the Developer, wh
229
207
 
230
208
  **Code review (Principal).** The Principal reviews the diff — does it match the brief, scope violations, honest tests, spot-check quality. The agent verdict is an input, not a substitute; the Principal can overrule either way.
231
209
 
232
- **Spec review (Brief Author).** Do the specs describe what was built? Is the pull request's stated reasoning honest about what changed? Coherence, not technical correctness (that's the Principal's code review).
210
+ **Spec review (Planner).** Do the specs describe what was built? Is the pull request's stated reasoning honest about what changed? Coherence, not technical correctness (that's the Principal's code review).
233
211
 
234
212
  If both pass (and agent verdicts are APPROVE and PASS, and surfaced findings have been shown to the Principal at the go) → merge. If issues are found → back to the Developer with specific feedback. The loop ends by finding identity, never by round count — per the Review Cycle specification, round two judges only the lines changed since the previously judged head, for every non-blocking severity: a finding outside that delta is surfaced for the Principal's go rather than driving the verdict. A BLOCKER, CRITICAL or HIGH outside the delta still drives the verdict on any round; only MAJOR, MINOR, MEDIUM and LOW outside the delta are surfaced for the Principal's go. After round two the Principal decides, and there is no round three unless the Principal orders it. The loop pauses when a resolved finding reappears, when two consecutive rounds resolve no prior finding, or when one finding stays open three consecutive rounds while others resolve — every trigger is measured from the finding id sets, never from anyone's narrative of progress, and round five is a backstop, not a trigger. On a pause the Principal applies the `vinaya/needs:principal-input` label and works the stall menu cheapest first: a different role in the seat, resume with the trigger overridden, reseed the developer, abandon — a ruling re-enters the work as a constraint amended into the brief.
235
213
 
@@ -243,7 +221,7 @@ If both pass (and agent verdicts are APPROVE and PASS, and surfaced findings hav
243
221
 
244
222
  **Who:** the Developer-agent (for `[agent]` items) and the Principal (for `[principal]` items). Verification is a *phase*, not a new actor — see `roles/developer.md` § Verification.
245
223
 
246
- A PR that has passed code review and security review still has not been run. The reviews read the diff; the static gates of Phase 8 prove the code compiles and types and tests; CI does not boot the app. Phase 11 boots it, executes the brief's **Test Plan** (a required brief field, `brief-authoring/SKILL.md` §9), and posts the results onto the PR. Doctrine: **CI green ≠ app boots ≠ feature works** — runtime verification is its own gate.
224
+ A PR that has passed code review and security review still has not been run. The reviews read the diff; the static gates of Phase 8 prove the code compiles and types and tests; CI does not boot the app. Phase 11 boots it, executes the brief's **Test Plan** (a required brief field, rendered from the Issue's `## Test plan` section — see `roles/planner.md` § The Planner's rationale), and posts the results onto the PR. Doctrine: **CI green ≠ app boots ≠ feature works** — runtime verification is its own gate.
247
225
 
248
226
  The test plan is split by who can structurally execute each item:
249
227
 
@@ -262,7 +240,7 @@ The test plan is split by who can structurally execute each item:
262
240
 
263
241
  ## Phase 12: Merge
264
242
 
265
- **Who:** Principal (or Brief Author if explicit per-PR delegation was set in the brief).
243
+ **Who:** Principal (or the Planner if explicit per-PR delegation was set in the brief's `principal_delegate:` field).
266
244
 
267
245
  The Principal merges. Tier 3 work merges during a ratification window (`roles/principal.md`); Tier 0/1 anytime. The merge **auto-closes the linked Issue** (via `Closes #N`) — and the merge *is* the `merged` status; nobody writes a label. An automation layer may surface a completion notification.
268
246
 
@@ -284,7 +262,7 @@ When the last task of a tranche has merged, the Principal declares it done and d
284
262
 
285
263
  2. **Write the retrospective** — append a new section to `aeg-project/lessons.md` with observations on what went well, what stalled, carry-forward lessons, decisions made, and unbuilt tasks. Assembled from merged PR summaries and topology — not invented.
286
264
 
287
- 3. **Archive the tranche** — set `Lifecycle: complete` as the first line after the tranche file's heading, move the file from `aeg-root/tranches/` to `aeg-root/tranches/completed/` (one commit: `git mv`). This signals to the AEG Studio and any reader that the tranche is no longer active.
265
+ 3. **Archive the tranche** — close the tranche's Milestone. That closed Milestone is the current signal to the Planner's readiness gate (`contracts/tranche-archivist-planner.md`) and to any reader that the tranche is no longer active. **Legacy exception:** for a tranche still carrying a pre-cutover topology file, also set `Lifecycle: complete` as the first line after the file's heading and move it from `aeg-root/tranches/` to `aeg-root/tranches/completed/` (one commit: `git mv`) kept for tranches created before the forge-native cutover; a forge-native tranche carries no such file to move.
288
266
 
289
267
  4. **Update state docs** — refresh `aeg-project/state.md` (last-updated date, current focus pointer, recently shipped section, clear any resolved pending-manual-ops). Active-work state is derived from the forge — no `now.md`.
290
268
 
@@ -312,7 +290,7 @@ The Principal eventually removes the worktree (`git worktree remove …`) — de
312
290
  `spike: true` → reduced Task Done (typecheck + lint, with what was tried and learned recorded in the pull request). Spike code does not merge — it rebases away or converts to a full Tier 1+ task in a separate brief.
313
291
 
314
292
  ### Tier 0 work (trivial)
315
- Skips Phase 2; short brief; minimal checklist; light Phase 10 (a code-reviewer pass is cheap insurance, but the security pass and Brief Author spec review can be skipped when there's no config/auth surface and no spec change). Declare `Tier: 0` in the PR body so verify-docs doesn't require doc updates.
293
+ Skips Phase 2; short brief; minimal checklist; light Phase 10 (a code-reviewer pass is cheap insurance, but the security pass and Planner spec review can be skipped when there's no config/auth surface and no spec change). Declare `Tier: 0` in the PR body so verify-docs doesn't require doc updates.
316
294
 
317
295
  ### Multi-developer parallel work
318
296
  Each Developer gets its own worktree, branched from `origin/main`. Parallel safety is the dispatch gates: a task does not start while a `conflicts-with` sibling's PR is open, or before a `depends-on`'s PR merges (`tranche-model.md` §8). Conflicts are declared at planning time as package-level collision domains — the coordination lives in the tranche's edges, not in ad-hoc scope-checking. When unsure two tasks collide, the Planner declares the conflict and serializes.
@@ -327,17 +305,17 @@ A rollback is its own task with its own brief. The decision to roll back is a Ty
327
305
 
328
306
  ## Anti-patterns
329
307
 
330
- - **Going straight to brief authoring without Phase 1** — produces briefs that solve the wrong problem.
331
- - **Dispatching an unvalidated or malformed brief** — the Developer's entry gate refuses it; bypassing the gate manually defeats the model.
308
+ - **Going straight to dispatch without Phase 1** — a rationale written on top of an unexamined idea produces briefs that solve the wrong problem.
309
+ - **Dispatching a task whose gates aren't met, or forcing a render past a gap it flagged** — the Developer's own entry gate refuses it anyway; bypassing the gate manually just moves the failure one stage later.
332
310
  - **Letting the Developer review its own work** — the Phase 10 agent passes are separate fresh-context invocations for a reason.
333
311
  - **Writing status anywhere** — status is derived from the forge. Setting a label or editing the tranche file to record state recreates the racing status model the design eliminated.
334
- - **Putting the brief in the Issue** — it lives in the PR body, just-in-time. The Issue is task identity only.
312
+ - **Hand-writing brief content into the Issue's own body** — the Issue body is task identity + metadata + the Planner's rationale + judgment sections only; the brief itself is a mechanically rendered comment on it, posted by `vinaya task dispatch`, never typed by hand into either the Issue or the PR body.
335
313
  - **Developer scope creep** — "while I'm here…" is a new task and a new brief.
336
- - **Brief Author self-ratifying Type 1 decisions in solo sessions** — they queue as PENDING for a ratification window.
314
+ - **Planner self-ratifying Type 1 decisions in solo sessions** — they queue as PENDING for a ratification window.
337
315
  - **Skipping the Task Done checklist under deadline pressure** — it's the load-bearing discipline; skipping it is how the BYOK gap happened.
338
316
  - **Treating "PR opened" as "done"** — done is "passed Phase 11 verification" (which requires Phase 10 review to have already passed).
339
317
  - **Treating "review passed" as "ready to merge"** — review reads the diff; verification runs the booted app. CI green ≠ app boots ≠ feature works. An unticked Test Plan box is the merge gate even when the reviews are clean.
340
- - **Inventing a Test Plan at verification time when the brief omitted one** — that is the Brief Author's job by design; verification *executes* the plan, it does not author it. A missing Test Plan is a brief-validation failure (`needs:brief-correction`).
318
+ - **Inventing a Test Plan at verification time when the Issue's rationale omitted one** — the Test Plan is written onto the Issue at plan time and rendered mechanically at dispatch; verification *executes* the plan, it does not author it. A missing Test Plan is a rationale defect, caught by the ring-0 creation gate or the render's own refusal, not something verification improvises around.
341
319
  - **Mis-tagging a `[principal]` Test Plan item as `[agent]`** to make the agent half look complete — the asymmetry is structural (the agent surface lacks auth/keys/eyes); reclassifying loses the point of the split.
342
320
  - **Building a dynamic conflict scanner** to catch what the Planner missed — declare conflicts conservatively and serialize instead (`tranche-model.md` §9).
343
321
 
@@ -345,7 +323,7 @@ A rollback is its own task with its own brief. The decision to roll back is a Ty
345
323
 
346
324
  ## How this process maps to file artifacts
347
325
 
348
- For which files get mutated in which phase by which actor, see `state-machine.md` (the artifact + mutation matrix). For the roles, see `roles/principal.md`, `roles/planner.md`, `roles/brief-author.md`, `developer.md`, `reviewer.md`, `security.md`, `archivist.md`. For the tranche/task model, see `tranche-model.md` and `roles/planner.md`. For brief authoring, see the `brief-authoring` skill.
326
+ For which files get mutated in which phase by which actor, see `state-machine.md` (the artifact + mutation matrix). For the roles, see `roles/principal.md`, `roles/planner.md`, `developer.md`, `reviewer.md`, `security.md`, `archivist.md`. For the tranche/task model, see `tranche-model.md` and `roles/planner.md`. For dispatching a task, see `roles/planner.md` § The dispatch act.
349
327
 
350
328
  ---
351
329
 
@@ -100,7 +100,7 @@ Work through this checklist for the merged task. Confirm each against reality
100
100
 
101
101
  At close-out you assemble one **provenance record** for the task and post it as a comment on the merged PR (the PR is a frozen truth domain once merged; the comment is append-only). This is the audit-by-construction output — the thing a reviewer, an auditor, or a future maintainer reads to know *what shipped, from what intent, checked by whom*.
102
102
 
103
- **The cardinal constraint: you ASSEMBLE, you do not author.** Every field is **copied from a fact the merge already froze** — the brief (in the PR body), the PR's reviews, the forge's own merge metadata. You compute nothing new and you store no new state. The provenance block is a **projection of frozen facts**, exactly like derived status is a projection of forge state — which is why it does **not** violate the anti-regression rule against storing execution metadata: it lives on the merged PR, not in the tranche file or the Issue, and it is written once, never updated.
103
+ **The cardinal constraint: you ASSEMBLE, you do not author.** Every field is **copied from a fact the merge already froze** — the brief (frozen on the task Issue's `aeg:brief:v1` comment), the PR's reviews, the forge's own merge metadata. You compute nothing new and you store no new state. The provenance block is a **projection of frozen facts**, exactly like derived status is a projection of forge state — which is why it does **not** violate the anti-regression rule against storing execution metadata: it lives on the merged PR, not in the tranche file or the Issue, and it is written once, never updated.
104
104
 
105
105
  Fields (omit any whose source fact is genuinely absent; never invent one):
106
106
 
@@ -108,7 +108,7 @@ Fields (omit any whose source fact is genuinely absent; never invent one):
108
108
  ### AEG provenance — task <n> (tranche <name>)
109
109
  - Issue: #N (closed by merge)
110
110
  - Tier: 0|1|3
111
- - Brief: in this PR body (the frozen intent)
111
+ - Brief: frozen on the task Issue's `aeg:brief:v1` comment
112
112
  - Project(s): <from the brief's Project: field, resolved via projects.md>
113
113
  - Model/agent: <from the brief's `For:` line — AEG forbids commit-trailer attribution, so this is the source>
114
114
  - Code review: APPROVE | REQUEST CHANGES→resolved (PR review by <reviewer>)
@@ -159,7 +159,7 @@ If required docs didn't move, or a required provenance source fact is absent, th
159
159
 
160
160
  ## Where you sit in the process
161
161
 
162
- You are the last step of the flow (`process.md`) — the close-out that sits under **Phase 12 (Merge)**, not the review phase: code-reviewer pass → security pass → Principal code review → Brief Author spec review → merge → **close-out (you)**. After you, the task is done, durable, and provenanced.
162
+ You are the last step of the flow (`process.md`) — the close-out that sits under **Phase 12 (Merge)**, not the review phase: code-reviewer pass → security pass → Principal code review → Planner spec review → merge → **close-out (you)**. After you, the task is done, durable, and provenanced.
163
163
 
164
164
  ## Turn-end: record the ledger rows for every role that turned on this task
165
165
 
@@ -28,13 +28,13 @@ summary: Ever had someone review their own work?
28
28
 
29
29
  You execute **one** brief, on **one** branch, and answer for it. You are the only role that writes code.
30
30
 
31
- **You own** — the code, the tests, and the documentation the brief names; a clean typecheck, lint, test and production build; the worktree; and the pull request, carrying the report and the brief (posted as its own comment), its impact tier, the issue it closes, and your own exact token figures.
31
+ **You own** — the code, the tests, and the documentation the brief names; a clean typecheck, lint, test and production build; the worktree; and the pull request, carrying the report, its impact tier, the issue it closes, and your own exact token figures. The brief itself lives elsewhere: dispatch tooling posts it once, frozen, as a comment on the task's own tracking issue, before you ever start — you never author or post it yourself.
32
32
 
33
33
  **You refuse** — to start, when the input is not a well-formed brief, when a task you depend on has not merged, when a conflicting task is still open, when the task has no issue yet, when the previous tranche of a product you touch was never closed out, or when the branch name you were handed does not match the task; and to continue, when a pre-flight check fails, when the brief contradicts the code irreconcilably, when a test still fails after repeated genuine diagnosis, when you are about to touch a file outside the brief's surface, or when an action would be destructive and the brief never authorized it. Refusing is reporting what blocks you, not improvising past it.
34
34
 
35
35
  **You never** author your own brief, write status anywhere, review or approve your own work, merge, settle a contested architectural question, skip a verification hook to get a commit through, or commit a new file whose only purpose is to hold a report.
36
36
 
37
- **How it physically runs** — you work in a git worktree of your own, at `.worktrees/task/<tranche>/<n>`, on a branch named `task/<tranche>/<n>`, cut from the tip of the main branch rather than from whatever your local checkout happens to be. Creating it is the first thing you do, before reading a line of code. That branch name is the entire addressing scheme: every other role finds this task's branch, its pull request, and therefore its state from that one string, which is why it must match the task exactly. Commits are small and frequent — one per Part, pushed once. When the work is done the brief is posted as its own pull-request comment — its permanent home, and where the reviewer reads it — while the pull-request description itself carries the report: the impact tier and the issue the merge closes. No file records progress: the branch existing, the pull request opening, and the merge landing **are** the status.
37
+ **How it physically runs** — you work in a git worktree of your own, at `.worktrees/task/<tranche>/<n>`, on a branch named `task/<tranche>/<n>`, cut from the tip of the main branch rather than from whatever your local checkout happens to be. Creating it is the first thing you do, before reading a line of code. That branch name is the entire addressing scheme: every other role finds this task's branch, its pull request, and therefore its state from that one string, which is why it must match the task exactly. Commits are small and frequent — one per Part, pushed once. The brief itself was already posted, frozen, on the tracking issue before you started — its permanent home, and where the reviewer reads it — while the pull-request description carries the report: the impact tier and the issue the merge closes. No file records progress: the branch existing, the pull request opening, and the merge landing **are** the status.
38
38
 
39
39
 
40
40
  ---
@@ -45,6 +45,10 @@ You execute **one** brief, on **one** branch, and answer for it. You are the onl
45
45
 
46
46
  You are the Developer when you are running in a coding-agent surface, a task brief has been dispatched to you (pasted in chat, or by an automation layer), and the brief tells you to execute specific work. You are executing — not planning, not strategizing, not authoring briefs.
47
47
 
48
+ <!-- AEG:CLAIM: apps/cli/src/lib/dispatch.ts contains:VINAYA_ROLE: role, -->
49
+ <!-- AEG:CLAIM: packages/aeg-core/src/log/envelope.ts contains:isRole(input.env.role) ? input.env.role : 'unattributed' -->
50
+ A turn started via `vinaya dispatch developer --agent <vendor>` carries its role and task in every `vinaya` call it makes; one started by hand in a terminal reads `unattributed` in the Vinaya Log, which is the truth about it.
51
+
48
52
  > **Toolchain is per-repo.** This role names obligations (tests pass, typecheck passes, lint passes, production build passes), not specific commands. Each repo declares its own commands — the exact `typecheck` / `lint` / `test` / `build` invocations live in the repo's config (e.g. `package.json` scripts, a Makefile, the brief's verification section). Where this doc shows commands, they are **this repo's** instances (a Bun/JS toolchain) — substitute your repo's equivalents.
49
53
 
50
54
  ---
@@ -55,7 +59,7 @@ You are the Developer when you are running in a coding-agent surface, a task bri
55
59
  - A task brief has been pasted, or dispatched by an automation layer
56
60
  - The brief says to build, fix, refactor, document, or validate something specific
57
61
 
58
- You are NOT the Developer if you are in a chat/planning surface talking with the Principal about strategy or planning. That's the Planner or Brief Author role. You are NOT the Reviewer — that's a separate fresh-context invocation that reviews your PR after you open it (`roles/reviewer.md`, `roles/security.md`). Environment determines role.
62
+ You are NOT the Developer if you are in a chat/planning surface talking with the Principal about strategy or planning. That's the Planner role. You are NOT the Reviewer — that's a separate fresh-context invocation that reviews your PR after you open it (`roles/reviewer.md`, `roles/security.md`). Environment determines role.
59
63
 
60
64
  ---
61
65
 
@@ -63,11 +67,11 @@ You are NOT the Developer if you are in a chat/planning surface talking with the
63
67
 
64
68
  Before writing any code, validate the following — and refuse if any fails:
65
69
 
66
- 1. **Is my input a well-formed brief?** It must carry tier, scope, stop conditions, and a deliverable. If you were handed a loose prompt instead → *"This isn't a brief — it's missing tier / scope / stop-conditions. Get one from the Brief Author; I don't infer scope from a prompt."* If a multi-project repo and `Project:` doesn't resolve against `.vinaya/projects.md` → *"Project 'x' isn't registered."*
70
+ 1. **Is my input a well-formed brief?** It must carry tier, scope, stop conditions, and a deliverable. If you were handed a loose prompt instead → *"This isn't a brief — it's missing tier / scope / stop-conditions. Get one dispatched from the Planner; I don't infer scope from a prompt."* If a multi-project repo and `Project:` doesn't resolve against `.vinaya/projects.md` → *"Project 'x' isn't registered."*
67
71
  2. **Are my dispatch gates satisfied?** Check the forge (not a status file — status is derived):
68
72
  - Every `depends-on` task's **PR is merged**. If not → *"Task N depends on <dep>, whose PR isn't merged yet. Not starting — it serializes behind it."*
69
73
  - No `conflicts-with` sibling has an **open PR** (or is otherwise in-flight). If one does → *"Task N conflicts with <sibling>, whose PR is open. Not starting until it merges."*
70
- 3. **Issue-existence precondition (hard STOP before step 0).** Before executing step 0, confirm via the forge (`vinaya/tranche:<slug>`-labeled Issue titled `[<slug>] <n> — …`, and its Milestone) — not `aeg-root/tranches/<name>.md` — that this task has a real GitHub Issue number, not `#TBD`, not blank. If no such Issue exists, the task has no forge Issue and is not dispatchable. STOP: *"Task <id> in tranche `<name>` has no Issue (#TBD) — it is not dispatchable. The Planner must cut the Issue before this task can start."* Do not begin work. The Issue number is what makes the task forge-addressable and is required for `Closes #N` in the PR body. See `aeg-root/contracts/brief-developer.md`.
74
+ 3. **Issue-existence precondition (hard STOP before step 0).** Before executing step 0, confirm via the forge (`vinaya/tranche:<slug>`-labeled Issue titled `[<slug>] <n> — …`, and its Milestone) — not `aeg-root/tranches/<name>.md` — that this task has a real GitHub Issue number, not `#TBD`, not blank. If no such Issue exists, the task has no forge Issue and is not dispatchable. STOP: *"Task <id> in tranche `<name>` has no Issue (#TBD) — it is not dispatchable. The Planner must cut the Issue before this task can start."* Do not begin work. The Issue number is what makes the task forge-addressable and is required for `Closes #N` in the PR body. See `aeg-root/contracts/planner-developer.md`.
71
75
  4. ~~**Prior-archival precondition (hard STOP before step 0).**~~ **SUPERSEDED (2026-07-13) — no longer a live obligation.** The per-task archival / row-adjacency precondition this item once mechanized is removed as a hard-STOP: automated post-merge provenance posting made the drift signal this item existed to protect moot. Preserved below as historical record only — do NOT enforce this item:
72
76
 
73
77
  ~~Before executing step 0, query this tranche's most-recently-merged task PR:~~
@@ -81,13 +85,13 @@ Before writing any code, validate the following — and refuse if any fails:
81
85
  | jq '.comments[].body | select(test("AEG.*provenance|provenance.*task"; "i"))'
82
86
  ```
83
87
  ~~If the result is empty, the per-task Archivist was skipped. STOP: *"Prior task PR #N in tranche `<name>` has no provenance block — the per-task Archivist must run before this task proceeds. Dispatch the per-task Archivist for #N first."* Do not begin work. If no prior merged task PR exists in the tranche (this is the first task), this check passes trivially. The contract governing this signal is `aeg-root/contracts/reviewer-archivist.md`; the full obligation is in `aeg-root/contracts/brief-developer.md`.~~
84
- 5. **Prior-tranche-archival precondition.** Before opening a PR against any product, confirm each product named in the brief's `Project:` field has its previous tranche archived. For each product, check whether a prior tranche for that product exists in `aeg-root/tranches/` but NOT in `aeg-root/tranches/completed/`. If any such unarchived tranche exists and all its task PRs are merged, the Tranche Archivist has not run. STOP: *"Product `<X>`'s previous tranche `<name>` is complete but not archived — the Tranche Archivist must run before new work on this product. Dispatch it first."* If there is no prior tranche on a product, this gate passes trivially. The contract governing this gate is `aeg-root/contracts/tranche-archivist-planner.md`.
85
- 6. **Branch-ID verification (hard STOP before step 0).** Before executing step 0, confirm via the forge (`vinaya/tranche:<slug>`-labeled Issue titled `[<slug>] <n> — …`, and its Milestone) — not `aeg-root/tranches/<name>.md` — that the branch-name suffix in the Step 0 command you were just handed literal-matches this task's forge-derived id `<n>` — character for character: no added prefix, no case change, no truncation. If it doesn't: *"The Step 0 branch name `task/<tranche>/<X>` doesn't match this task's topology ID `<Y>` — STOP, do not create the worktree/branch; report the mismatch to the Brief Author/Principal rather than silently using either name."* Do not begin work.
88
+ 5. **Prior-tranche-archival precondition.** Before opening a PR against any product, confirm each product named in the brief's `Project:` field has its previous tranche archived. For each product, check whether a prior tranche for that product has an open Milestone (forge-native) — or, for a tranche still carrying a pre-cutover topology file, exists in `aeg-root/tranches/` but NOT in `aeg-root/tranches/completed/` (legacy exception; a forge-native tranche carries no such file to check). If any such unarchived tranche exists and all its task PRs are merged, the Tranche Archivist has not run. STOP: *"Product `<X>`'s previous tranche `<name>` is complete but not archived — the Tranche Archivist must run before new work on this product. Dispatch it first."* If there is no prior tranche on a product, this gate passes trivially. The contract governing this gate is `aeg-root/contracts/tranche-archivist-planner.md`.
89
+ 6. **Branch-ID verification (hard STOP before step 0).** Before executing step 0, confirm via the forge (`vinaya/tranche:<slug>`-labeled Issue titled `[<slug>] <n> — …`, and its Milestone) — not `aeg-root/tranches/<name>.md` — that the branch-name suffix in the Step 0 command you were just handed literal-matches this task's forge-derived id `<n>` — character for character: no added prefix, no case change, no truncation. If it doesn't: *"The Step 0 branch name `task/<tranche>/<X>` doesn't match this task's topology ID `<Y>` — STOP, do not create the worktree/branch; report the mismatch to the Planner/Principal rather than silently using either name."* Do not begin work.
86
90
  7. **Row-existence precondition (hard STOP before step 0).** Before executing step 0, confirm via the forge (`vinaya/tranche:<slug>`-labeled Issue titled `[<slug>] <n> — …`, and its Milestone) — not `aeg-root/tranches/<name>.md` — that this task's row exists **at all**. This is distinct from and prior to item 3's `#TBD`/blank check: a missing row means the plan/Issue for this task has not merged/opened yet, and there is nothing to inspect — no Issue, no dependencies, no `Project(s)` value. If the row is absent: STOP: *"Task <id> is not present in tranche `<name>`'s forge-derived task list (no `vinaya/tranche:<name>`-labeled Issue with this task id yet) — the plan/Issue for this task hasn't merged/opened. Not dispatchable until it does."* Do not begin work.
87
91
 
88
92
  **Mechanized version of items 3, 5, and 7.** Items 3, 5, and 7 above (Issue-existence, prior-tranche-archival, row-existence) are all re-derivable in one run: `vinaya check dispatch-readiness`, run from the task branch against a freshly-fetched `origin/main` and the live forge, before step 0. A `NOT READY` result names the exact failing predicate and is the same STOP each item above describes — read the printed blocker rather than re-deriving the fact by hand. **Known gap:** the shipped check's prior-tranche-archival predicate always reports empty (a narrower parity gap than the full derivation below) — do not treat its pass as covering item 5; confirm item 5 yourself. The prose above remains the *why* (what each precondition means, and the manual `gh`/`jq` fallback if the tool is ever unavailable); item 6 (branch-ID verification) is a static check against the brief's own Step 0 text, not a mechanized command, and stays manual. Item 4 is superseded and no longer part of this composed check. **This gate now also runs mechanically** (task 25) — the `first-push-dispatch` check, wired into every adopter's generated CI and managed `.git/hooks/pre-push`, invokes the same derivation on a task branch's first push, before its PR exists — but running it yourself before step 0 remains the cheaper, earlier catch: the hook fires only at push time, after you've already done the work. **On this repo's toolchain**, the underlying, unabridged derivation (including the real prior-tranche-archival predicate) is `bun packages/aeg-core/bin/verify-dispatch.ts <tranche> <n>` — prefer it here over the shipped check's narrower parity.
89
93
 
90
- If the brief carries a `Premise:` block, also re-assert it before step 0: confirm by hand that the brief's stated facts still hold against the live forge/codebase (a stale premise means the surface moved since the brief was authored — STOP and re-dig; see `aeg-root/contracts/brief-developer.md`). **On this repo's toolchain**, `bun packages/aeg-core/bin/verify-dispatch.ts <tranche> <n> --premise <body-file>` (the body-file being the dispatched brief text) automates that re-assertion.
94
+ If the brief carries a `Premise:` block, also re-assert it before step 0: confirm by hand that the brief's stated facts still hold against the live forge/codebase (a stale premise means the surface moved since the brief was rendered — STOP and re-dig; see `aeg-root/contracts/planner-developer.md`). **On this repo's toolchain**, `bun packages/aeg-core/bin/verify-dispatch.ts <tranche> <n> --premise <body-file>` (the body-file being the dispatched brief text) automates that re-assertion.
91
95
 
92
96
  Items 3, 5, and 7 read live forge state. Item 6 checks the brief's own Step 0 text against that same forge-derived id. You never write status anywhere — opening your branch and PR *is* the status.
93
97
 
@@ -103,9 +107,9 @@ Items 3, 5, and 7 read live forge state. Item 6 checks the brief's own Step 0 te
103
107
 
104
108
  **Worktree discipline.** Your brief's first pre-flight step (Step 0) is creating a worktree — do it before anything else. If dispatched by an automation layer, you work in the worktree it created at `.worktrees/task/<tranche>/<n>/`. If working manually, the brief's Step 0 gives you the `git worktree add … origin/main` command — run it and `cd` in. Never branch from a local checkout that may be behind.
105
109
 
106
- **Commit per Part, push once.** Commit after each numbered Part in the brief — small, one logical change per commit, so the history reads as a narrative of how you approached the problem. Push exactly once, immediately before `pr create` — not after every commit. The pre-push hook itself runs the affected test suite (`bunx turbo test --affected`) on that one push and refuses it on failure; you do not additionally run it yourself per Part. A regeneration or evidence run (`vinaya pr report --write`/`--push`) passes `--force` to its own test invocation. A verdict binds to the head it judged; a push landing after the newest verdict's judged head voids it and is named as such: `vinaya review status` prints `push after verdict — re-review required`, and merge waits on a fresh review round.
110
+ **Commit per Part, push once.** Commit after each numbered Part in the brief — small, one logical change per commit, so the history reads as a narrative of how you approached the problem. Push exactly once, immediately before `pr create` — not after every commit. The pre-push hook itself runs the affected test suite (`bunx turbo test --affected`) on that one push and refuses it on failure; you do not additionally run it yourself per Part. The affected suite covers only the packages `turbo`'s own dependency graph marks affected by this diff — a rule about one package's files that lives in another package's test never runs on a push that only touches the first package (found live: a CLI-only diff never marked `aeg-core` affected, so a rule about CLI files, asserted only in an `aeg-core` test, never ran at the push hook at all). A rule meant to bind a package's own files belongs in a `vinaya check`, not in a sibling package's test suite. A regeneration or evidence run (`vinaya pr report --write`/`--push`) passes `--force` to its own test invocation. A verdict binds to the head it judged; a push landing after the newest verdict's judged head voids it and is named as such: `vinaya review status` prints `push after verdict — re-review required`, and merge waits on a fresh review round.
107
111
 
108
- **Opening the PR with a complete description.** The PR description must (1) **carry the report only** — `pr create` posts the brief as its own comment marked `aeg:brief`, once; that comment is the brief's permanent, durable home, and the Reviewer and Archivist read it there; (2) follow the canonical form in [§ PR body — canonical form](#pr-body--canonical-form) below — that section holds the verbatim copy-pasteable template, including the **exact `Tier:` field syntax** the `verify-docs` gate requires; (3) reference the task's Issue (`Closes #N`) so the merge auto-closes it. The description is not optional — the reviews depend on it. Opening the PR is itself the `in-flight → in-review` transition; you write no status field. **The body is authored once, at open.** After the PR is open, you never hand-edit it again — not to append a response to a review round, not to record a decision, not for any reason. Two writes are sanctioned after open, both machine-regenerated, never typed: the Evidence block, and one appended row in the Token report for a re-entry turn (see [§ Evidence is emitted, never typed](#evidence-is-emitted-never-typed)). Everything else a review round produces — your response to findings, re-run `[agent]` evidence, any disclosure the brief didn't anticipate — is a PR comment.
112
+ **Opening the PR with a complete description.** The PR description must (1) **carry the report only** — the brief itself never rides in this body at all; it is already posted, frozen, as the task Issue's `aeg:brief:v1` comment by `vinaya task dispatch`, before your worktree even exists, and that comment is the brief's permanent, durable home the Reviewer and Archivist read it there; (2) follow the canonical form in [§ PR body — canonical form](#pr-body--canonical-form) below — that section holds the verbatim copy-pasteable template, including the **exact `Tier:` field syntax** the `verify-docs` gate requires; (3) reference the task's Issue (`Closes #N`) so the merge auto-closes it. The description is not optional — the reviews depend on it. Opening the PR is itself the `in-flight → in-review` transition; you write no status field. **The body is authored once, at open.** After the PR is open, you never hand-edit it again — not to append a response to a review round, not to record a decision, not for any reason. Two writes are sanctioned after open, both machine-regenerated, never typed: the Evidence block, and one appended row in the Token report for a re-entry turn (see [§ Evidence is emitted, never typed](#evidence-is-emitted-never-typed)). Everything else a review round produces — your response to findings, re-run `[agent]` evidence, any disclosure the brief didn't anticipate — is a PR comment.
109
113
 
110
114
  **Reporting exact tokens in the PR body at turn-end.** You do not append your own row to `aeg-root/tranches/<name>.tokens.md` — no role writes its own ledger row on a task branch, and parallel Developer sessions on different tasks have collided appending to the same shared file. Instead, before opening the PR (and again before each `changes-requested → in-review` re-push), report your exact tokens in the PR body under a **"Token report"** heading: `Phase | Role | Agent/Model | Tokens in | Tokens out | Cost | Date` with `Phase: <task-id>: develop` and `Role: Developer`. **That destination and that grammar are the requirement, and they are the same on every agent host.**
111
115
 
@@ -125,15 +129,17 @@ This is the verbatim PR-body template every Developer pastes when opening a PR.
125
129
 
126
130
  This form is **forge-agnostic.** It depends on no GitHub feature, no `.github/PULL_REQUEST_TEMPLATE.md`, no agent-specific skill. It is the source of truth that travels with the methodology.
127
131
 
128
- **Start from the template file:** copy `aeg-root/templates/pr-report-template.md` and fill its placeholders — it packages this canonical form as a literal skeleton, with each gate-read field (`Closes #N`, `Project:`, `Tier:`, the Test Plan section) wrapped in its AEG anchor pair (an HTML comment pair, invisible on the rendered PR) so a pasted reference brief or quoted example can never be mistaken for the real field. Anchors are optional — prose-only bodies keep parsing exactly as before (`aeg-root/enforcement.md`) — but the template seeds them by default; keep them. Paste the brief into the template's `## Reference` section as before; it never reaches the forge as body text`vinaya pr create` splits that section out and posts it as a separate PR comment marked `<!-- aeg:brief -->`, once, at open.
132
+ **Start from the template file:** copy `aeg-root/templates/pr-report-template.md` and fill its placeholders — it packages this canonical form as a literal skeleton, with each gate-read field (`Closes #N`, `Project:`, `Tier:`, the Test Plan section) wrapped in its AEG anchor pair (an HTML comment pair, invisible on the rendered PR) so a pasted reference brief or quoted example can never be mistaken for the real field. Anchors are optional — prose-only bodies keep parsing exactly as before (`aeg-root/enforcement.md`) — but the template seeds them by default; keep them. There is no `## Reference` section to fill: the brief never rides in this body at all it is already posted, frozen, on the task Issue — and `pr create` refuses a body still carrying either legacy `aeg:brief:start`/`aeg:brief:end` marker.
129
133
 
130
134
  ```markdown
131
- ## Summary
135
+ ## Decisions
132
136
 
133
- <one paragraph: what shipped and the durable why. Links to `Closes #<N>` go
134
- here. No verification claims no "typecheck passes", no diff stats, no
135
- test counts. Those are the Evidence block below, and it is the ONLY sanctioned
136
- home for them: emitted by `vinaya pr report --write`, never hand-typed.>
137
+ <one line per choice the brief left open, e.g. `- <choice>: <what you picked
138
+ and why>` the alternatives you considered and why you picked yours, so the
139
+ Principal can reverse a wrong call. Never restate what the diff does. No
140
+ verification claims no "typecheck passes", no diff stats, no test counts.
141
+ Those are the Evidence block below, and it is the ONLY sanctioned home for
142
+ them: emitted by `vinaya pr report --write`, never hand-typed.>
137
143
 
138
144
  ## Test plan
139
145
 
@@ -176,9 +182,9 @@ field on its own line:>
176
182
 
177
183
  | Field | Requirement |
178
184
  |------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
179
- | Summary | One paragraph. Closes the Issue with `Closes #<N>` somewhere in the body. No verification claims (typecheck/lint/test/diff-stat output, pass counts) — those belong exclusively in Evidence, below. |
185
+ | Decisions | One line per choice the brief left open the alternatives considered and why yours won. Never a restatement of what the diff does. No verification claims (typecheck/lint/test/diff-stat output, pass counts) — those belong exclusively in Evidence, below. "No open choices" is a valid value, stated explicitly, same as `Test Plan: unit-tests-only`'s sentinel pattern — never left blank with no words. |
180
186
  | **Bare digits (whole body)** | `body-bare-digits` (CI) refuses any bare digit outside a fenced/indented/inline code span or `Closes`/`Project`/`Tier`/`Evidence`'s own anchor, correctly placed under its own documented section — nowhere else. `Premise`/`Test plan` get no anchor exemption at all (their real content is unbounded free text, so it's scanned like ordinary prose — a Test Plan item's own pass count or exit code needs backticks too). An Issue/PR ref, a date, a version, a path, a section number all now need their own backticks (`` `#N` ``); a countable claim ("138 passed", a duration, a percentage) belongs in a fenced block or doesn't get written. |
181
- | Test plan | Every runtime-observable check. The brief-authoring skill makes this a **required** field — empty plans use `Test Plan: unit-tests-only` as the sentinel. |
187
+ | Test plan | Every runtime-observable check. The Issue's `## Test plan` section makes this a **required** field, rendered mechanically into the brief — empty plans use `Test Plan: unit-tests-only` as the sentinel. |
182
188
  | `[agent]` fenced list | A fenced block, one command per line, each with `→ <expected observable>`. `vinaya pr report` runs every line from the PR head and writes the command plus its actual output into `AEG:EVIDENCE` — never a checkbox, never a hand-pasted comment. (This is the `[agent]` half of the Verification phase, see `state-machine.md` § Verification.) |
183
189
  | `[principal]` items | Checkbox items only the Principal can run (auth-gated, vendor-key-dependent, visual). The agent **does not tick these** — the Principal does, after running in a real browser. |
184
190
  | Evidence | The `AEG:EVIDENCE` block — emitted by `vinaya pr report --write`, never hand-typed. See [§ Evidence is emitted, never typed](#evidence-is-emitted-never-typed). `check-evidence-fresh` refuses a body whose block doesn't match the head it's attached to. |
@@ -193,7 +199,7 @@ field on its own line:>
193
199
 
194
200
  The `AEG:EVIDENCE` block is populated by running `vinaya pr report --write <body-file>` — never by hand-typing a diff stat, a test count, or a gate's pass/fail line into the PR body. Regenerate it after your final commit, before opening or editing the PR: `vinaya pr report --write` both runs the real gates (Group B) and recomputes the diff stat (Group A), so its own exit code doubles as the pre-open verification run — a red gate still writes the block (recording the failure honestly) but exits non-zero, so a scripted `--write && open-pr` never carries a failing suite onto the forge.
195
201
 
196
- `check-evidence-fresh` (CI) refuses a body whose block doesn't match the head it's attached to — recomputing Group A exactly and checking Group B for staleness. This closes fabrication for **Group A only** (a hand-typed diff stat cannot survive a byte-compare); Group B is checked for freshness, not re-run, so a stale-but-not-fabricated Group B slips past unless the block is also out of date. Do not claim in this PR's own Evidence section, or anywhere else, that this closes fabrication generally — it closes it for the two facts a checker can cheaply recompute, never for the Summary paragraph's prose.
202
+ `check-evidence-fresh` (CI) refuses a body whose block doesn't match the head it's attached to — recomputing Group A exactly and checking Group B for staleness. This closes fabrication for **Group A only** (a hand-typed diff stat cannot survive a byte-compare); Group B is checked for freshness, not re-run, so a stale-but-not-fabricated Group B slips past unless the block is also out of date. Do not claim in this PR's own Evidence section, or anywhere else, that this closes fabrication generally — it closes it for the two facts a checker can cheaply recompute, never for the Decisions section's prose.
197
203
 
198
204
  **Regeneration is one command, run last, after every other change.** The Developer never hand-edits the live PR body after open — there is no local body file to keep in sync with the forge. When a push forces the Evidence block to go stale — or a re-entry turn needs its one appended Token report row — run, from the repo root, after every commit for that round is already pushed:
199
205
 
@@ -222,7 +228,7 @@ All of the following must pass before the PR is opened:
222
228
  - [ ] Code passes typecheck (this repo: `bun run typecheck`)
223
229
  - [ ] Code passes lint/format (this repo: `bun run format-and-lint`)
224
230
  - [ ] Tests pass if applicable (this repo: `bun test`)
225
- - [ ] PR description follows the template, carries the brief, and declares `Tier: 0`
231
+ - [ ] PR description follows the template, carries the report, and declares `Tier: 0`
226
232
  - [ ] "Token report" section in the PR body carrying your turn's real token figures, collected by whatever means your host offers (see the token-reporting section above; on this repo's shipped reference host, `vinaya tokens`) — and, on each re-push after `CHANGES_REQUESTED`, one appended row inside the `AEG:TOKENS` anchor, written in the same `pr edit` that regenerates the Evidence block (see [§ Evidence is emitted, never typed](#evidence-is-emitted-never-typed)); the Archivist appends the ledger row post-merge, you do not
227
233
 
228
234
  ### Tier 1 checklist
@@ -277,12 +283,12 @@ Then stop. Review is a separate invocation.
277
283
  The work now enters Phase 10 review (`process.md`):
278
284
 
279
285
  ```
280
- code-reviewer pass → security pass → Principal code review → Brief Author spec review → merge
286
+ code-reviewer pass → security pass → Principal code review → Planner spec review → merge
281
287
  ```
282
288
 
283
289
  The code-reviewer and security passes are **separate, fresh-context invocations** — not you. You do not review your own work; the independence is the point. What you do:
284
290
 
285
- - **Address REQUEST CHANGES / FAIL findings.** A code-review BLOCKER or a security CRITICAL/HIGH comes back to you. Fix it on the **same branch** with new commits; the relevant pass re-runs. Do not open a new PR. (Pushing fixes returns the PR's review state to open, which is the `changes-requested → in-review` transition — again, derived, not written.) Your response to the round is one PR comment, never a body edit: the PR body is frozen at open (see [§ Opening the PR with a complete description](#what-the-developer-owns)), so no `## Review response`, `## Review round`, or `## Findings addressed` section may exist anywhere in it.
291
+ - **Address REQUEST CHANGES / FAIL findings.** A code-review BLOCKER or a security CRITICAL/HIGH comes back to you. Fix it on the **same branch** with new commits; the relevant pass re-runs. Do not open a new PR. (Pushing fixes returns the PR's review state to open, which is the `changes-requested → in-review` transition — again, derived, not written.) Your response to the round is one PR comment, never a body edit: the PR body is frozen at open (see [§ Opening the PR with a complete description](#what-the-developer-owns)), so no `## Review response`, `## Review round`, or `## Findings addressed` section may exist anywhere in it. A `doc-correctness` finding carries a `Search:` pattern — a repo-wide `git grep -n -iE` pattern, with no path filter — and is resolved only when every hit it returns at the new head is a true statement. So fix every copy, not only the anchored line: re-run that pattern yourself, correct every hit, and paste the command and its output at the fixed head into your round response. A response that fixes only the anchored line, or omits the pasted search output, is malformed and the finding stays open. Where the corrected sentence states what code does, bind it with an `AEG:CLAIM` marker so `verify-docs` C8 keeps it honest.
286
292
  - **Do not argue findings into submission.** If a finding is wrong, say why, concisely, in a PR reply — but the Reviewer's independence means the default is to fix, not to debate.
287
293
  - **Do not act on an escalation yourself.** An escalation is its own review outcome, never a finding — it routes to the Planner (`strategy`) or Principal (`authority`/`product`). Wait for direction.
288
294
  - **Do not merge.** Only the Principal merges.
@@ -339,7 +345,7 @@ Every brief includes stop conditions. Honor them unconditionally. Common reasons
339
345
  When dispatched by an automation layer, you work in the worktree it created at `.worktrees/task/<tranche>/<n>/` on branch `task/<tranche>/<n>` — your isolated workspace, branched from `origin/main`.
340
346
 
341
347
  When working manually, the brief's pre-flight Step 0 gives you the worktree command. Run it first:
342
- - `git worktree add .worktrees/task/<tranche>/<n> -b task/<tranche>/<n> origin/main && cd .worktrees/task/<tranche>/<n>`
348
+ - `git worktree add .worktrees/task/<tranche>/<n> -b task/<tranche>/<n> --no-track origin/main && cd .worktrees/task/<tranche>/<n> && git config push.autoSetupRemote true`
343
349
  - Then `git worktree list` to confirm you're not accidentally working in another task's worktree
344
350
  - Branch from `origin/main`, never from `HEAD` of the current local checkout (which may be behind)
345
351
  - Confirm the branch was created correctly: `git log --oneline -3` should show the expected parent
@@ -412,7 +418,7 @@ The checks above are **static**: they prove the change compiles, lints, types an
412
418
  ### Refuse if it isn't your turn
413
419
 
414
420
  - **No open PR** — nothing to verify; come back when one is open.
415
- - **No `aeg:brief` comment on the PR** — without a Test Plan there is no definition of "verified"; post the brief comment first.
421
+ - **No `aeg:brief:v1` comment on the task Issue** — without a Test Plan there is no definition of "verified"; `vinaya task dispatch` must post the frozen brief comment first.
416
422
  - **No Test Plan section in the brief** — the brief is malformed; flag it for correction and stop rather than inventing a plan at verification time.
417
423
  - **The plan declares `unit-tests-only` but the diff touches a runtime surface** (a route, a page, a server action) — the brief was mis-declared; flag it for correction. This is the failsafe against quietly downgrading verification.
418
424