@attalabs/vinaya 0.1.1 → 0.1.2
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.
- package/aeg-root/contracts/archivist-tranche-archivist.md +92 -0
- package/aeg-root/contracts/brief-developer.md +140 -0
- package/aeg-root/contracts/developer-reviewer.md +106 -0
- package/aeg-root/contracts/planner-brief.md +130 -0
- package/aeg-root/contracts/reviewer-archivist.md +96 -0
- package/aeg-root/contracts/tranche-archivist-planner.md +116 -0
- package/aeg-root/coordination.md +293 -0
- package/aeg-root/enforcement.md +159 -0
- package/aeg-root/glossary.md +32 -0
- package/aeg-root/process.md +371 -0
- package/aeg-root/roles/archivist.md +167 -0
- package/aeg-root/roles/brief-author.md +108 -0
- package/aeg-root/roles/developer.md +429 -0
- package/aeg-root/roles/planner.md +285 -0
- package/aeg-root/roles/principal.md +107 -0
- package/aeg-root/roles/reviewer.md +130 -0
- package/aeg-root/roles/security.md +121 -0
- package/aeg-root/roles/tranche-archivist.md +257 -0
- package/aeg-root/skills/aeg/SKILL.md +90 -0
- package/aeg-root/skills/aeg-roles/SKILL.md +58 -0
- package/aeg-root/skills/brief-authoring/SKILL.md +497 -0
- package/aeg-root/state-machine.md +642 -0
- package/aeg-root/templates/brief-template.md +103 -0
- package/aeg-root/templates/issue-rationale-template.md +35 -0
- package/aeg-root/templates/pr-report-template.md +68 -0
- package/aeg-root/tranche-model.md +304 -0
- package/dist/checks/bin/check-branch-topology.js +2840 -0
- package/dist/checks/bin/check-brief-shape.js +2775 -0
- package/dist/checks/bin/check-closes-n.js +2824 -0
- package/dist/checks/bin/check-coherence.js +2922 -0
- package/dist/checks/bin/check-dead-branch-push.js +2799 -0
- package/dist/checks/bin/check-dispatch-readiness.js +2923 -0
- package/dist/checks/bin/check-doc-coverage-push.js +2818 -0
- package/dist/checks/bin/check-doc-coverage.js +2816 -0
- package/dist/checks/bin/check-first-push-dispatch.js +2888 -0
- package/dist/checks/bin/check-issue-assignment.js +2863 -0
- package/dist/checks/bin/check-no-disk-state.js +2811 -0
- package/dist/checks/bin/check-reader-resolvable-prose.js +2820 -0
- package/dist/checks/bin/check-registry-gates.js +2923 -0
- package/dist/checks/bin/check-review-gate.js +2826 -0
- package/dist/checks/bin/check-single-plan-pr.js +2810 -0
- package/dist/checks/bin/check-test-plan.js +2775 -0
- package/dist/index.js +110 -94
- package/package.json +4 -2
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_title: Archivist → Tranche Archivist
|
|
3
|
+
title: Archivist → Tranche Archivist
|
|
4
|
+
order: 5
|
|
5
|
+
contract_id: archivist-tranche-archivist
|
|
6
|
+
description: Carries each task’s close-out record up to the tranche close-out, so a phase can only be called finished once its parts genuinely are.
|
|
7
|
+
status: active
|
|
8
|
+
producer: archivist
|
|
9
|
+
consumer: tranche-archivist
|
|
10
|
+
carrier: pr-provenance-comments, tranche-file
|
|
11
|
+
summary: Ever closed out a big project only to find smaller pieces were never really finished?
|
|
12
|
+
---
|
|
13
|
+
# Contract: per-task Archivist → Tranche Archivist
|
|
14
|
+
|
|
15
|
+
## The short version
|
|
16
|
+
|
|
17
|
+
This seam sits between closing out one task and closing out the tranche that contained it. It exists because a tranche's history is only honest if each task's history was completed first.
|
|
18
|
+
|
|
19
|
+
**What crosses** — the set of merged pull requests, each carrying its own provenance record. That record is what proves a task was genuinely closed out rather than merely merged. Alongside it: a note on the standing lessons thread for any serious finding that was raised in review and merged anyway, so a consciously accepted deviation is available as a pattern later; and a follow-up issue for every finding that the product's specification has gone stale, so the gap outlives the task that found it.
|
|
20
|
+
|
|
21
|
+
**The hand-off is malformed when** — a merged pull request carries no provenance record. That means the task's close-out never ran, and the tranche's retrospective would then be assembled from a gap rather than a fact. It is malformed in the same way when an accepted deviation left no note, or when a stale-specification finding left no follow-up: in each case something real happened and nothing durable records it.
|
|
22
|
+
|
|
23
|
+
**What it does not carry** — permission to proceed on partial evidence. A partial close-out is worse than none, because it produces a record that looks complete and is not. It also carries no new judgement: nothing here re-opens, re-reviews or re-decides a merged task; both roles assemble from facts, and neither authors one.
|
|
24
|
+
|
|
25
|
+
**How it physically runs** — the carrier is the merged pull requests themselves, each with its provenance comment, plus the standing lessons thread and any follow-up issues. Tranche close-out reads them and stops if one is missing, flagging exactly which task's record is incomplete rather than working around it. The retrospective it then writes is a structured projection of those facts — assembled from merged work, recorded lessons and the decisions of the period, never generated from memory.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Reference
|
|
31
|
+
|
|
32
|
+
**Status:** active
|
|
33
|
+
**Seam:** the hand-off from the per-task Archivist (producer) to the Tranche Archivist (consumer).
|
|
34
|
+
**Single source of truth for this seam.** The two role docs do **not** redefine what crosses this boundary — they point here. `aeg-root/roles/archivist.md` (producer side) and `aeg-root/roles/tranche-archivist.md` (consumer side) each reference this file; this file is where the field-by-field hand-off lives, once.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Why this file exists
|
|
39
|
+
|
|
40
|
+
The per-task Archivist closes out individual tasks; the Tranche Archivist closes out the whole tranche. The Tranche Archivist's close-out is only honest if every per-task Archivist ran correctly — a missing provenance block means a task's history is incomplete, and an incomplete history means the retrospective is assembled from gaps rather than facts. This contract specifies exactly what the per-task Archivist must produce before the Tranche Archivist is authorized to begin, and exactly what the Tranche Archivist reads from those outputs.
|
|
41
|
+
|
|
42
|
+
The failure mode this prevents: a Tranche Archivist who begins close-out before verifying that every task's per-task Archivist ran, and then assembles a retrospective and tranche provenance block that silently omits a task's history or fabricates fields whose source facts were never produced.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## The hand-off carrier
|
|
47
|
+
|
|
48
|
+
The **set of merged PRs**, each bearing a per-task provenance block comment, plus the **tranche file** at `aeg-root/tranches/<name>.md` which provides the task topology the Tranche Archivist checks against. Every task in the topology must have a merged PR with a provenance block; the absence of either is a gap the Tranche Archivist must flag before proceeding.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## The contract — field-by-field mapping
|
|
53
|
+
|
|
54
|
+
Every output the per-task Archivist produces (left) has exactly one obligation for the Tranche Archivist (right). A task missing any left-column output is a close-out gap — the Tranche Archivist does not proceed with partial evidence.
|
|
55
|
+
|
|
56
|
+
| per-task Archivist produces (per task) | Tranche Archivist consumes at | What the consumption means |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| **Provenance block comment** on each merged PR | Entry gate verification | The Tranche Archivist verifies every task PR has a provenance block comment before starting close-out. A missing provenance block means that task's per-task Archivist close-out was incomplete — stop and flag: *"Task N's PR has no provenance block — per-task Archivist did not run for this task. Flag for Principal before proceeding."* |
|
|
59
|
+
| **Lessons Issue comments** for any `BLOCKER`/`MAJOR` findings that merged | Retrospective assembly | The Tranche Archivist reads the pinned lessons Issue's comments since the tranche started and includes the patterns they identify in the retrospective's "What stalled or caused rework" and "Carry-forward lessons" sections. |
|
|
60
|
+
| **Follow-up Issues** opened for `STALE-SPEC` findings | State doc update | The Tranche Archivist notes open follow-up Issues in the relevant pinned state Issue under "Pending manual operations" (or in the output report as DANGLING items). A `STALE-SPEC` finding with no follow-up Issue is a DANGLING item — flag it for the Principal. (`now.md` is retired.) |
|
|
61
|
+
|
|
62
|
+
**Reading the table:** left is the producer obligation (per-task Archivist role doc and this contract enforce it), right is the consumer obligation (Tranche Archivist role doc and this contract enforce it). The two role docs must not contradict this table.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Producer obligations (the per-task Archivist)
|
|
67
|
+
|
|
68
|
+
- Post a provenance block comment on every merged task PR — no exceptions. This is the single most critical output: without it, the Tranche Archivist's entry gate fails and close-out cannot proceed.
|
|
69
|
+
- Post a new comment on the pinned lessons Issue for every `BLOCKER` or `MAJOR` finding that was present in the Reviewer's verdict and merged anyway (a deviation). A deviation without a lessons entry is a missed learning.
|
|
70
|
+
- Open a follow-up Issue for every `STALE-SPEC` finding identified by the Reviewer. If the Developer already opened one, confirm it exists; do not open a duplicate.
|
|
71
|
+
- Append one row to the tranche's token ledger at close-out.
|
|
72
|
+
|
|
73
|
+
## Consumer obligations (the Tranche Archivist)
|
|
74
|
+
|
|
75
|
+
- Verify every task PR has a provenance block comment before starting. If any is missing, stop and flag — do not proceed with partial close-out. Partial close-out is worse than no close-out: it creates a plausible-looking but incomplete record.
|
|
76
|
+
- Read the pinned lessons Issue's comments since the tranche start date before assembling the retrospective. Carry-forward lessons that appear there but are not reflected in the retrospective are a gap.
|
|
77
|
+
- Note open follow-up Issues in the relevant pinned state Issue (under "Pending manual operations") or in the close-out report as DANGLING items. If a `STALE-SPEC` finding has no follow-up Issue (the per-task Archivist missed it), flag it as DANGLING and open the Issue on behalf of the Principal. (`now.md` is retired.)
|
|
78
|
+
- Do not assemble the tranche retrospective from memory or inference — assemble it from merged PR summaries, the pinned lessons Issue's comments, and the tranche topology file. The retrospective is a structured projection of facts.
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Changing this contract
|
|
83
|
+
|
|
84
|
+
A contract changes **as a unit**. You may not change what the per-task Archivist produces without, in the same change, updating what the Tranche Archivist consumes — because the property that makes the seam sound is that the producer's output side is *identical* to the consumer's input side. Concretely:
|
|
85
|
+
|
|
86
|
+
- A change to this file is a **Tier 3** change: it alters a cross-role contract, so the reasoning belongs in the pull request that makes it, where the reviewer and the close-out both read it.
|
|
87
|
+
- The same PR that edits this contract must verify both `aeg-root/roles/archivist.md` and `aeg-root/roles/tranche-archivist.md` still point here and still match the table.
|
|
88
|
+
- Never edit one side's role doc to add/drop a hand-off field directly. Add/drop it **here**; the role docs inherit it by reference.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
*This contract is the seam. The per-task Archivist fills the left column; the Tranche Archivist drains the right. One source of truth, changed as a unit.*
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_title: Brief Author → Developer
|
|
3
|
+
title: Brief Author → Developer
|
|
4
|
+
order: 2
|
|
5
|
+
contract_id: brief-developer
|
|
6
|
+
description: Carries a brief to the agent that executes it, so nothing the author knew is left implicit.
|
|
7
|
+
status: active
|
|
8
|
+
producer: brief-author
|
|
9
|
+
consumer: developer
|
|
10
|
+
carrier: pr-body
|
|
11
|
+
summary: Ever handed someone a task and they missed something you thought was obvious?
|
|
12
|
+
---
|
|
13
|
+
# Contract: Brief Author → Developer
|
|
14
|
+
|
|
15
|
+
## The short version
|
|
16
|
+
|
|
17
|
+
This seam sits between the brief and the agent that executes it. It exists to close the gap where an author assumes something is obvious and an executor never sees it stated.
|
|
18
|
+
|
|
19
|
+
**What crosses** — one brief, complete. The exact command that creates the isolated working copy and branch, to be run before anything else. The impact tier, which decides how much documentation and record-keeping the work owes. The projects it touches. The context: what the task is not, and the traps already found. What must exist and be merged before it can start. The bounded file surface it may touch. Pinned assertions about the current code, so a brief written yesterday cannot be executed against a surface that has moved. The documents it must update. The checklist it satisfies before opening a pull request. A test plan, each item marked as one an agent can run or one only a person can. The conditions that stop it. The constraints it may not weigh against convenience.
|
|
20
|
+
|
|
21
|
+
**The hand-off is malformed when** — any of those is missing. A brief without stop conditions is not a terse brief; it is one whose executor will invent them. A file surface described as "wherever else turns out to need it" is not bounded. A documentation list assembled from memory rather than reading is not a list. It is equally malformed to skim rather than read it, to treat a stop condition as advice, to execute past the file surface because nothing blocked it, or to paraphrase a verification result instead of pasting what the command printed.
|
|
22
|
+
|
|
23
|
+
**What it does not carry** — status, which is derived from branches and pull requests and never written; the planner's durable reasoning, which crossed the previous seam and lives on the issue; and any authority to amend the brief. The brief is frozen at dispatch; a change to it is an escalation, not an edit.
|
|
24
|
+
|
|
25
|
+
**How it physically runs** — the carrier is the pull-request body, which holds the brief verbatim. That is the brief's permanent home: the executing agent reads it there, the reviewer reads it there to judge intent against outcome, and the close-out reads it there as evidence. It is never committed into the repository and never stored in the issue, which holds task identity only — a brief kept anywhere durable goes stale before the work starts.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Reference
|
|
31
|
+
|
|
32
|
+
**Status:** active
|
|
33
|
+
**Seam:** the hand-off from the Brief Author (producer) to the Developer (consumer).
|
|
34
|
+
**Single source of truth for this seam.** The two role docs do **not** redefine what crosses this boundary — they point here. `aeg-root/skills/brief-authoring/SKILL.md` (producer side) and `aeg-root/roles/developer.md` (consumer side) each reference this file; this file is where the field-by-field hand-off lives, once.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Why this file exists
|
|
39
|
+
|
|
40
|
+
A brief is the executable contract between intent and implementation. When the hand-off from Brief Author to Developer is described separately in each role doc, the descriptions drift: the Brief Author believes the Developer will infer certain things; the Developer misses the fields the Brief Author thought were obvious. This contract removes that drift structurally — there is exactly one description of what a brief must carry and what the Developer must do with each field.
|
|
41
|
+
|
|
42
|
+
The failure mode this prevents: a Developer who starts work without reading the full brief, or who treats stop conditions as suggestions, or who improvises past a surface-map boundary because nothing explicitly blocked them. Every field below is present in every well-formed brief; its absence is a signal the brief is malformed, not that the field is optional.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## The hand-off carrier
|
|
47
|
+
|
|
48
|
+
The **PR body** — which the Developer opens at the start of execution and which carries the full brief verbatim. The brief is not in the Issue (the Issue is task identity + Planner's rationale only). The PR body is the brief's permanent, durable home. The Developer reads the PR body as the brief; the Reviewer and Archivist read it as evidence of intent.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## The contract — field-by-field mapping
|
|
53
|
+
|
|
54
|
+
Every field the Brief Author emits (left) has exactly one named obligation for the Developer (right). A brief missing any left-column field is malformed — the Brief Author refuses to dispatch it. A Developer who drops a right-column obligation is executing incorrectly.
|
|
55
|
+
|
|
56
|
+
| Brief Author emits | Developer consumes at | What the consumption means |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| **Worktree step 0** (verbatim `git worktree add` command) | First action before any other command | The Developer must execute this exact command first. No exceptions. Never assume the right branch exists. Before executing it, the Developer independently re-verifies the branch-name suffix literal-matches the topology's `#` column — the same check the Brief Author already ran before writing the command. |
|
|
59
|
+
| **Tier:** field | PR-open checklist + `vinaya/tier:*` label | The Developer sets the matching `vinaya/tier:*` label on the Issue at PR open. The field is binding; the label is the scannable projection. |
|
|
60
|
+
| **Project:** field | PR description + `verify-docs` | The Developer confirms the project resolves against `.vinaya/projects.md`. |
|
|
61
|
+
| **Context** including boundary + traps | Mental model before any code | The Developer reads the boundary ("what this task is NOT") to know what to refuse to build, and the traps to know what not to do. |
|
|
62
|
+
| **Technical Dependencies** | Verify all depends-on are merged | The Developer confirms every named dependency is on `main` before starting. A depends-on not yet merged is a hard stop. |
|
|
63
|
+
| **Technical Surface Map** | Bounds the diff | The Developer touches only files in the surface map. Files outside it are a stop-and-escalate. |
|
|
64
|
+
| **Premise pins (`Premise:` block, mandatory when the surface map names a real code surface)** | Re-asserted before Step 0, via `verify-dispatch --premise <body-file>`; re-asserted again pre-PR via `verify-task` | A failed premise means the surface moved since the brief was authored — the Developer stops and re-digs rather than executing against a stale mental model. This is a stop condition, not a silent re-guess. `checkPremiseCoverage` (Brief Validation) fails a brief with a real code surface and zero premise coverage. |
|
|
65
|
+
| **Documentation-update list** | Self-check before opening PR + Reviewer doc check | The Developer updates every doc named in the list before claiming done. The list is a DoD obligation, not a recommendation — a named doc not updated is a BLOCKER at review. `verify-docs --pr` gates structural presence; the Reviewer gates content correctness. |
|
|
66
|
+
| **Task Done checklist** | Self-check before opening PR | The Developer runs every item before opening the PR. An unchecked item means the PR is not ready. |
|
|
67
|
+
| **Test Plan** tagged `[agent]` / `[principal]` | Runs `[agent]` items; leaves `[principal]` for Principal | The Developer runs every `[agent]` item and posts evidence. Does not tick `[principal]` boxes. |
|
|
68
|
+
| **Stop conditions** | Halt triggers | The Developer stops and posts a blocker comment on the Issue when any condition is met. Never improvises past a stop condition. |
|
|
69
|
+
| **Constraints** | Hard rules during execution | The Developer treats these as absolute — not "guidelines." A violated constraint is a PR that must not merge. |
|
|
70
|
+
|
|
71
|
+
**Reading the table:** left is the producer obligation (Brief Author enforces it by refusing to dispatch a malformed brief), right is the consumer obligation (Developer role doc and executor protocol enforce it). The two role docs must not contradict this table.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Producer obligations (the Brief Author)
|
|
76
|
+
|
|
77
|
+
- Every field in the left column above must be present. A brief missing any of them is malformed — the Brief Author refuses to dispatch it.
|
|
78
|
+
- The brief is frozen at dispatch; amendments go through escalation (`severity:execution` or `severity:strategy` depending on what changed).
|
|
79
|
+
- The worktree step 0 command must be exact — branch name, base ref (`origin/main`), and destination path must all be present. The branch name's suffix must literal-match the task's row in the tranche topology file's `#` column — character for character, no added prefix, no case change, no truncation.
|
|
80
|
+
- Stop conditions must be explicit, not inferred. Every known failure mode for this task belongs in the brief's stop conditions — the Developer will not invent stop conditions that aren't stated.
|
|
81
|
+
- The surface map must be bounded and named. "Wherever else turns out to need it" is not a surface map.
|
|
82
|
+
- **The documentation-update list must be populated from reading, not memory.** The Brief Author's Dig must identify and read any relevant specs/skills/docs before drafting it. The list for Tier 1+ must be non-empty unless the surface map genuinely touches no documented surface (state "No doc updates required" explicitly in that case). A list populated from the Planner's rationale alone without the Brief Author's own reading is malformed.
|
|
83
|
+
- **A brief with a real code surface must carry a `Premise:` block pinning at least one checkable fact inside that surface.** A Tier 0 brief with zero code/runtime surface has nothing to pin.
|
|
84
|
+
|
|
85
|
+
## Task-status coherence precondition — hard STOP before authoring or executing any task
|
|
86
|
+
|
|
87
|
+
> **SUPERSEDED (2026-07-13).** This precondition (the per-task archival / row-adjacency gate) is no longer a hard-STOP for the Brief Author or the Developer — automated post-merge provenance posting made the drift signal it protected moot. The section below is preserved as historical record — do NOT enforce it.
|
|
88
|
+
|
|
89
|
+
~~The Brief Author MUST verify this precondition before authoring any task brief. The Developer MUST verify it before step 0. **If any predicate fails for any in-scope prior, STOP and report to the Principal what is owed — do NOT author, do NOT begin work, do NOT rationalize past it.**~~
|
|
90
|
+
|
|
91
|
+
**The archival bar.** A prior task is "done" when ALL THREE predicates hold:
|
|
92
|
+
1. Its forge Issue is **closed**
|
|
93
|
+
2. Its PR is **merged to main**
|
|
94
|
+
3. Its **provenance block** comment is present on the merged PR (posted by the Archivist)
|
|
95
|
+
|
|
96
|
+
"PR merged" alone is NOT the bar. A merged PR whose Issue is still open, or whose provenance block is absent, is an incomplete archival — the Archivist has not fully closed out.
|
|
97
|
+
|
|
98
|
+
**Scope of "prior task" — verify all three predicates for each:**
|
|
99
|
+
- **Mid-tranche task:** every earlier task in the same tranche that this task depends on (direct `depends-on` edges).
|
|
100
|
+
- **First task of an vinaya/tranche:** the entire previous tranche of that product must be archived — all Issues closed, all PRs in main, all tasks with provenance blocks, tranche file in `aeg-root/tranches/completed/`.
|
|
101
|
+
- **ALL tasks:** every cross-tranche dependency declared in the topology (e.g. a task in one project that depends on a task in another, from an earlier tranche) must also satisfy all three predicates.
|
|
102
|
+
|
|
103
|
+
**Hard STOP language:** *"Prior task [Y] does not pass the coherence gate: Issue #N is [open/closed], PR #M is [merged/unmerged], provenance block is [present/absent]. The Archivist must fully close out task [Y] before this task can proceed. Here is what is owed: [list]."*
|
|
104
|
+
|
|
105
|
+
**Accepted-backfill never bypasses this gate.** Deferring backfill of historical provenance on **already-closed tranches** is a permitted debt record; proceeding with a new task on an **unarchived active prior** is not. The accepted-gap clause is strictly limited to closed historical tranches; it cannot be cited to bypass the coherence precondition for tasks in an active tranche. An accepted historical backlog is a debt record, not a gate bypass. The coherence precondition applies to active prior tasks; it cannot be waived by citing accepted historical gaps.
|
|
106
|
+
|
|
107
|
+
The Brief Author's enforcement is at Dig stage, item (c) (see `aeg-root/skills/brief-authoring/SKILL.md`). The Developer's enforcement is at entry gate items 3–5 (see `aeg-root/roles/developer.md`). The Brief Author gate fires one stage earlier than the Developer gate — catching the gap before a brief the Developer will immediately refuse is dispatched.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## Consumer obligations (the Developer)
|
|
112
|
+
|
|
113
|
+
- **Honor the documentation-update list.** Every doc named in the list must be updated as part of the task deliverable — not post-merge cleanup, not a follow-up task. A named doc not updated is a BLOCKER at review. If the list names a doc you cannot find or access, stop and report — do not silently skip it.
|
|
114
|
+
- **Row-existence precondition (hard STOP before step 0).** Before executing step 0, `git fetch origin main`, then confirm this task's row exists at all in its tranche topology file (`aeg-root/tranches/<name>.md`) — read from the freshly-fetched `origin/main`, never a stale local checkout or memory. This is distinct from and prior to the Issue-existence precondition below: a missing row means the plan PR that adds this task has not merged yet. STOP: *"Task <id> is not present in `aeg-root/tranches/<name>.md` on a freshly-fetched `origin/main` — the plan PR that adds it has not merged. Not dispatchable until it does."* This gate is enforced in `aeg-root/roles/developer.md` (entry gate, item 7).
|
|
115
|
+
- **Issue-existence precondition (hard STOP before step 0).** Before executing step 0, locate this task in its tranche topology file (`aeg-root/tranches/<name>.md`) and confirm the Issue column carries a real GitHub Issue number — not `#TBD`, not blank. If it is `#TBD` or blank, 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."* This gate is enforced in `aeg-root/roles/developer.md` (entry gate, item 3).
|
|
116
|
+
- ~~**Prior-archival precondition (hard STOP before step 0).**~~ **SUPERSEDED (2026-07-13)** — no longer a Developer obligation. See the notice above the task-status coherence precondition section. Preserved as historical record: ~~Before executing step 0, apply the task-status coherence precondition above to every in-scope prior task. Verify all three predicates (Issue closed, PR in main, provenance block present) for each. If any predicate fails for any in-scope prior, STOP: report to the Principal exactly what is owed and do not begin work. If no prior task exists in scope (first task of a fresh tranche with no prior tranche on this product), this check passes trivially. This gate was enforced in `aeg-root/roles/developer.md` (entry gate, item 4) and the coherence signal it read is defined in `aeg-root/contracts/reviewer-archivist.md`.~~
|
|
117
|
+
- **Branch-ID verification precondition (hard STOP before step 0).** Before executing step 0, read this task's row in the tranche topology file and confirm the Step 0 branch-name suffix literal-matches the `#` column — character for character, no added prefix, no case change, no truncation. If it doesn't, STOP: do not create the worktree/branch, report the mismatch to the Brief Author/Principal rather than silently using either name. This is the same check the Brief Author already ran before writing the command — the Developer re-runs it independently rather than trusting the brief was authored correctly. This gate is enforced in `aeg-root/roles/developer.md` (entry gate, item 6).
|
|
118
|
+
- **Mechanized precondition check.** The three preceding preconditions (row-existence, Issue-existence, and the prior-tranche-archival check in `roles/developer.md` entry gate item 5) are all re-derivable in one command: `bun packages/aeg-core/bin/verify-dispatch.ts <tranche> <n>`. Run it before step 0; a `NOT READY` result names the exact failing precondition and is the same STOP described above. (The prior-archival/row-adjacency precondition previously listed here was removed from this composed check.)
|
|
119
|
+
- **Premise re-check (hard STOP before step 0).** If the brief carries a `Premise:` block, re-assert it before step 0 via `verify-dispatch --premise <body-file>` (the body-file being the dispatched brief text). A failed premise means the surface moved since authoring — STOP and re-dig, do not proceed on a stale mental model.
|
|
120
|
+
- Read the full brief before opening the worktree. Not a skim — every section.
|
|
121
|
+
- Execute step 0 first, always. Never branch from `HEAD` of the current local checkout.
|
|
122
|
+
- Verify all dependencies are merged before the first line of code.
|
|
123
|
+
- Stay within the surface map. Files outside it are a stop-and-escalate, not a judgment call.
|
|
124
|
+
- Run every `[agent]` Test Plan item and post the actual command output as evidence. Do not paraphrase verification results.
|
|
125
|
+
- Stop on any stop condition — post a blocker comment, do not improvise.
|
|
126
|
+
- Append one row to the tranche's token ledger at turn-end (before opening PR, and again on each re-push after `CHANGES_REQUESTED`).
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Changing this contract
|
|
131
|
+
|
|
132
|
+
A contract changes **as a unit**. You may not change what the Brief Author emits without, in the same change, updating what the Developer consumes — because the property that makes the seam sound is that the producer's output side is *identical* to the consumer's input side. Concretely:
|
|
133
|
+
|
|
134
|
+
- A change to this file is a **Tier 3** change: it alters a cross-role contract, so the reasoning belongs in the pull request that makes it, where the reviewer and the close-out both read it.
|
|
135
|
+
- The same PR that edits this contract must verify both `aeg-root/skills/brief-authoring/SKILL.md` and `aeg-root/roles/developer.md` still point here and still match the table.
|
|
136
|
+
- Never edit one side's role doc to add/drop a hand-off field directly. Add/drop it **here**; the role docs inherit it by reference.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
*This contract is the seam. The Brief Author fills the left column; the Developer drains the right. One source of truth, changed as a unit.*
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_title: Developer → Reviewer
|
|
3
|
+
title: Developer → Reviewer
|
|
4
|
+
order: 3
|
|
5
|
+
contract_id: developer-reviewer
|
|
6
|
+
description: Carries finished work to its reviewer already accounted for, so review spends itself on judgement rather than on basics.
|
|
7
|
+
status: active
|
|
8
|
+
producer: developer
|
|
9
|
+
consumer: reviewer
|
|
10
|
+
carrier: pr-diff-and-body
|
|
11
|
+
summary: Ever had a reviewer waste time on basics instead of judging the actual work?
|
|
12
|
+
---
|
|
13
|
+
# Contract: Developer → Reviewer
|
|
14
|
+
|
|
15
|
+
## The short version
|
|
16
|
+
|
|
17
|
+
This seam sits between finished work and the review of it. It exists so that an independent reviewer spends the session judging the work rather than verifying that it was ready to be looked at.
|
|
18
|
+
|
|
19
|
+
**What crosses** — one open pull request, and everything that makes it reviewable. The brief in its body, pasted whole rather than summarised, because it is the statement of intent the diff has to be judged against. The impact tier, which sets how deep the review goes. Green checks: the type checker, the linter, the tests and the documentation gate all passing already, so a failure found in review is the work's, not the environment's. A diff that stayed inside the file surface the brief named. A completed checklist. Every test-plan item an agent can run, actually run, with the real command output posted rather than a claim about it. And every document the brief named, updated in the same change.
|
|
20
|
+
|
|
21
|
+
**The hand-off is malformed when** — the brief is missing, paraphrased or edited; when the checks are red; when the diff reaches outside the named surface; when a checklist item is ticked without evidence; when a test-plan item is claimed rather than shown; or when a promised document did not move. Each of those sends the change back rather than becoming a review finding, because none of them is a judgement call.
|
|
22
|
+
|
|
23
|
+
**What it does not carry** — the authority to fix anything. The reviewer reports and the author repairs; the reviewer never edits the code, never merges, and never writes status. It also does not carry a second opinion on taste: a change is judged against its brief, the product's specification, and safety, not against how the reviewer would have written it.
|
|
24
|
+
|
|
25
|
+
**How it physically runs** — the carrier is the open pull request: the diff, plus the body holding the brief. Coverage of the documents a change must touch is already enforced mechanically before review begins, which is why the reviewer's remaining job is the question no check can answer — whether the update is true, or a no-op edit that silenced the gate without describing the change. The verdict lands as comments on the pull request, with a severity on every finding, and a change cannot merge without a clean one.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Reference
|
|
31
|
+
|
|
32
|
+
**Status:** active
|
|
33
|
+
**Seam:** the hand-off from the Developer (producer) to the Reviewer (consumer).
|
|
34
|
+
**Single source of truth for this seam.** The two role docs do **not** redefine what crosses this boundary — they point here. `aeg-root/roles/developer.md` (producer side) and `aeg-root/roles/reviewer.md` (consumer side) each reference this file; this file is where the field-by-field hand-off lives, once.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Why this file exists
|
|
39
|
+
|
|
40
|
+
A review is only as good as the artifact it reviews. When the Developer hands off an incomplete, CI-failing, or brief-free PR, the Reviewer's independence is wasted — they spend the session verifying basics rather than judging correctness and spec-conformance. This contract removes ambiguity about what "ready for review" means: the Developer cannot open a PR without satisfying the left column; the Reviewer cannot start without verifying the right column.
|
|
41
|
+
|
|
42
|
+
The failure mode this prevents: a Reviewer who begins reviewing a diff without reading the brief (and therefore judges code rather than intent), or who reviews a red-CI PR (and cannot distinguish the Developer's errors from pre-existing failures), or who accepts a PR that touched files outside the brief's surface map without flagging it as a BLOCKER.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## The hand-off carrier
|
|
47
|
+
|
|
48
|
+
The **open PR** — the diff plus the PR body, which carries the brief verbatim. The PR is the Reviewer's primary artifact. The brief (in the PR body) is the intent document; the diff is the execution; the Reviewer's job is to judge whether the execution matched the intent, safely and correctly.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## The contract — field-by-field mapping
|
|
53
|
+
|
|
54
|
+
Every item the Developer produces in the open PR (left) has exactly one obligation for the Reviewer (right). A PR missing any left-column item is not ready for review — the Reviewer refuses to start and sends it back to the Developer.
|
|
55
|
+
|
|
56
|
+
| Developer produces in the PR | Reviewer consumes at | What the consumption means |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| **Brief in PR body** (the frozen brief, pasted verbatim) | Entry — read before looking at the diff | The Reviewer reads the brief first to understand intent, boundary, surface map, and traps. Reviewing a diff without the brief is not a valid review pass. |
|
|
59
|
+
| **Tier:** field in PR body | Determines review depth | Tier 0 → light pass; Tier 1 → standard including spec-conformance; Tier 3 → full including spec and state doc verification. |
|
|
60
|
+
| **CI green** (typecheck, lint, tests, `verify-docs`) | Entry gate | The Reviewer does not start if CI is red. A red CI is a Developer problem, not a Reviewer finding. |
|
|
61
|
+
| **Surface map respected** (diff touches only files named in the brief's surface map) | First diff check | If the diff touches files outside the surface map, that is a BLOCKER finding before reading any logic. |
|
|
62
|
+
| **Task Done checklist ticked** | Confirms Developer self-checked | The Reviewer verifies the checklist is present and ticked. An unticked item that the Reviewer then finds broken is a MAJOR finding. |
|
|
63
|
+
| **`[agent]` Test Plan items run with evidence comment** | Confirms runtime verification | The Reviewer checks that actual command output was posted for every `[agent]` item. Missing evidence = unticked item = MAJOR finding. |
|
|
64
|
+
| **Documentation-update list honored** (every named doc updated in the diff) | Doc coupling check — first diff step after surface-map check | A named doc absent from the diff or present but incorrect is a BLOCKER (it is a DoD obligation, not guidance). `verify-docs` gates structural presence; the Reviewer gates content correctness. |
|
|
65
|
+
| **`.vinaya/doc-owners` coverage (C5) satisfied** — every binding fired by the diff is bound (in-diff doc), URL-acked (`Doc-ack: <pointer> — <note>`), or waived by an actor-verified `vinaya/waiver:docs` label applied by a principal. | Coverage check — *mechanical* via CI; the Reviewer reads it as already-true and moves on. | Coverage presence is mechanical (`verify-docs` C5 fails CI if missing). The Reviewer's job shrinks to **judging correctness of the covered doc**: a passing C5 plus an incorrect / no-op / misleading doc update is still a BLOCKER. A waiver is no longer the author's to grant — it is an actor-verified `vinaya/waiver:docs` label applied by a principal, so there is no deferral line for the Reviewer to judge. The seam is dormant when `.vinaya/doc-owners` is absent or no binding matches; in that case there is nothing for either side to do. |
|
|
66
|
+
|
|
67
|
+
**Reading the table:** left is the producer obligation (Developer role doc and this contract enforce it), right is the consumer obligation (Reviewer role doc and this contract enforce it). The two role docs must not contradict this table.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Producer obligations (the Developer)
|
|
72
|
+
|
|
73
|
+
- ~~**Prior-archival precondition satisfied.**~~ **SUPERSEDED (2026-07-13).** This is no longer a Developer producer obligation — the per-task archival / row-adjacency precondition formerly defined in `aeg-root/contracts/brief-developer.md` is removed as a hard-STOP; automated post-merge provenance posting made the drift signal it protected moot.
|
|
74
|
+
- **Documentation-update list honored.** Every doc named in the list must be updated in the diff before opening the PR. A PR with list items outstanding is not ready for review; do not open it and expect the Reviewer to discover the gap.
|
|
75
|
+
- **`.vinaya/doc-owners` coverage satisfied.** For every binding fired by the diff: update the bound doc in this PR; or, for URL bindings, add `Doc-ack: <pointer> — <note>`; or have a principal apply the actor-verified `vinaya/waiver:docs` label — you cannot self-serve it, and there is no body-field waiver grammar anymore. `verify-docs` C5 enforces this mechanically — if it fails CI, do not request review.
|
|
76
|
+
- CI must be green before requesting review. Do not request review with a red CI and expect the Reviewer to begin.
|
|
77
|
+
- The brief must be in the PR body, unmodified — pasted verbatim, not summarized or paraphrased.
|
|
78
|
+
- The diff must touch only files in the brief's Technical Surface Map. Files outside it are a stop-and-escalate before opening the PR, not a finding for the Reviewer to catch.
|
|
79
|
+
- The Task Done checklist must be ticked — all items, with actual verification evidence for each.
|
|
80
|
+
- Every `[agent]` Test Plan item must have an evidence comment posted on the PR — the actual command output, not a paraphrase.
|
|
81
|
+
- One row appended to the tranche's token ledger before opening the PR.
|
|
82
|
+
|
|
83
|
+
## Consumer obligations (the Reviewer)
|
|
84
|
+
|
|
85
|
+
- Read the brief before the diff. This is not optional — the brief is the intent document; the diff without the brief is just code.
|
|
86
|
+
- Do not start if CI is red. Post a comment: *"CI is red — returning to Developer. Start review once CI is green."*
|
|
87
|
+
- Check surface map compliance as the first diff-inspection step. A surface map violation is a BLOCKER before any logic review.
|
|
88
|
+
- **Verify documentation-update-list compliance as a BLOCKER gate.** For every doc named in the list, confirm it appears in the diff AND is correct (not just present — `verify-docs` already checks presence). A named doc absent from the diff or present but wrong is a BLOCKER finding before reviewing logic. This is a hard gate, not an advisory; the list is a DoD commitment.
|
|
89
|
+
- **Judge correctness of `.vinaya/doc-owners` coverage.** Coverage *presence* is mechanical — `verify-docs` C5 has already enforced it (or the PR would not be green). Your job is to read each in-diff doc update that satisfied a C5 binding and confirm it actually reflects the code change, not a no-op edit or misleading rewrite that silenced the gate. A passing C5 + an incorrect doc update is a BLOCKER. A doc-coverage waiver is no longer a body field you weigh: it exists only as an actor-verified `vinaya/waiver:docs` label applied by a principal, which is a forge-authenticated human act rather than a parseable string.
|
|
90
|
+
- Produce a structured verdict per `roles/reviewer.md` output format — with severity tags on every finding. A verdict without severity tags is malformed.
|
|
91
|
+
- Do not edit the code. Do not expand scope. Do not approve to be agreeable.
|
|
92
|
+
- Append one row to the tranche's token ledger after posting the verdict (and again on each re-review after `CHANGES_REQUESTED`).
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Changing this contract
|
|
97
|
+
|
|
98
|
+
A contract changes **as a unit**. You may not change what the Developer produces without, in the same change, updating what the Reviewer consumes — because the property that makes the seam sound is that the producer's output side is *identical* to the consumer's input side. Concretely:
|
|
99
|
+
|
|
100
|
+
- A change to this file is a **Tier 3** change: it alters a cross-role contract, so the reasoning belongs in the pull request that makes it, where the reviewer and the close-out both read it.
|
|
101
|
+
- The same PR that edits this contract must verify both `aeg-root/roles/developer.md` and `aeg-root/roles/reviewer.md` still point here and still match the table.
|
|
102
|
+
- Never edit one side's role doc to add/drop a hand-off field directly. Add/drop it **here**; the role docs inherit it by reference.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
*This contract is the seam. The Developer fills the left column; the Reviewer drains the right. One source of truth, changed as a unit.*
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_title: Planner → Brief Author
|
|
3
|
+
title: Planner → Brief Author
|
|
4
|
+
order: 1
|
|
5
|
+
contract_id: planner-brief
|
|
6
|
+
description: Carries a tranche’s plan down to a single task’s brief, so a task keeps the reasoning that shaped it.
|
|
7
|
+
status: active
|
|
8
|
+
producer: planner
|
|
9
|
+
consumer: brief-author
|
|
10
|
+
carrier: issue-body
|
|
11
|
+
summary: Ever had a plan's key details get lost the moment someone else picked it up?
|
|
12
|
+
---
|
|
13
|
+
# Contract: Planner → Brief Author
|
|
14
|
+
|
|
15
|
+
## The short version
|
|
16
|
+
|
|
17
|
+
This seam sits between planning a tranche and writing one task's brief. It exists because a role boundary is where work is lost: the planner does a deep technical pass, and without a contract its conclusions quietly fail to arrive.
|
|
18
|
+
|
|
19
|
+
**What crosses** — the planner's rationale for one task, written into that task's issue: what the task is and deliberately is not; why it is one task rather than three; every project and shared-package consumer in its blast radius; why each dependency and conflict edge exists; the traps the dig already found; the class of agent the work needs; when the executing agent must stop rather than improvise; and the documents this work will make incoherent. Each has exactly one named home in the brief that consumes it, so a conclusion cannot arrive without a place to land.
|
|
20
|
+
|
|
21
|
+
**The hand-off is malformed when** — a rationale is missing any of those parts, in which case the planner does not emit it; or when a brief drops one on the floor, in which case the brief is wrong rather than merely thin. It is malformed too when the rationale carries detail that cannot survive the wait — exact signatures, precise file lists — which goes stale between planning and dispatch; re-deriving that fresh is the brief author's half. And when the brief author's own dig contradicts the rationale, that is escalated back, never silently overridden.
|
|
22
|
+
|
|
23
|
+
**What it does not carry** — the brief itself, which is written later and lives elsewhere; any statement of status, which is derived from the forge and never written down; scheduling or estimates, which belong to whatever tool plans the roadmap; and the freshly pinned facts a brief asserts about current code, which belong entirely to the next seam.
|
|
24
|
+
|
|
25
|
+
**How it physically runs** — the carrier is the task's issue body. The planner writes the rationale there in a fixed grammar, readable by a person and checkable by a machine alike; an issue whose body does not carry every part is refused at creation, and the same check re-runs against issues already open. The brief author reads it there and writes the brief, which lands in the pull-request body at dispatch. The issue holds the reasoning; the pull request holds the instruction.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Reference
|
|
31
|
+
|
|
32
|
+
**Status:** active
|
|
33
|
+
**Seam:** the hand-off from the Planner (producer) to the Brief Author (consumer).
|
|
34
|
+
**Single source of truth for this seam.** The two role docs do **not** redefine what crosses this boundary — they point here. `aeg-root/roles/planner.md` (producer side) and `aeg-root/skills/brief-authoring/SKILL.md` (consumer side) each reference this file; this file is where the field-by-field hand-off lives, once.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Why this file exists
|
|
39
|
+
|
|
40
|
+
A role boundary is where work is lost. The Planner does a deep technical pass and produces durable conclusions; the Brief Author must consume *every one* of them or the conclusion is dropped and the executing agent walks into a trap the planner already saw. When the hand-off is described separately in each role doc, the two descriptions drift (they already did once — the brief side was missing "Sizing" and "Dependency rationale" that the planner side required). A **contract** removes the drift structurally: there is exactly one description of the seam, and both roles are bound to it.
|
|
41
|
+
|
|
42
|
+
This is the first of AEG's role-seam contracts. Others (`brief-developer`, `developer-reviewer`, …) follow the same shape as each seam is modeled. A contract is a Class 1 artifact and changes **as a unit** — see "Changing this contract" below.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## The hand-off carrier
|
|
47
|
+
|
|
48
|
+
The Planner's output unit is the **task**, which exists as a forge Issue (identity + metadata + Planner's rationale) and a row in the tranche topology file (Issue link + edges only). The thing that crosses this seam is the **Planner's rationale** block, which the Planner writes into the **Issue body**. The Brief Author reads the rationale from the Issue — the forge artifact — and turns it into the executable brief that lands in the PR body. The tranche file row is a topology pointer (the Issue number); the Issue is the definition.
|
|
49
|
+
|
|
50
|
+
The Planner persists **durable conclusions** (which do not decay). The Brief Author adds **perishable detail** (current signatures, exact files, final model pick) at dispatch. Neither re-does the other's half; the rationale is the carrier between them, and the Issue is its home.
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## The contract — field-by-field mapping
|
|
55
|
+
|
|
56
|
+
Every field the Planner emits in the rationale (left) has exactly one named home in the brief (right). The Planner MUST emit every left-column field; the Brief Author MUST consume every one into the named brief section. A rationale missing a field is malformed (Planner refuses). A brief that drops a field on the floor is malformed (Brief Author error).
|
|
57
|
+
|
|
58
|
+
| Planner emits (rationale field) | Brief Author consumes it in (brief section) | What the consumption means |
|
|
59
|
+
|---|---|---|
|
|
60
|
+
| **Boundary** (what this task is / is not) | Context + Technical Surface Map | The brief's scope and out-of-surface set are the planner's boundary made concrete against current code. |
|
|
61
|
+
| **Sizing** (passed the four "too big?" tests) | Re-confirmation only | The brief assumes the task is one PR. If the Brief Author's own dig finds it no longer fits (code moved), that is **stop-and-escalate**, not a silent re-split. |
|
|
62
|
+
| **Project(s) + blast radius** (every project/consumer touched) | `Project:` field + blast-radius re-verification in the Done checklist | The brief carries the identical `Project(s)`; the Done checklist re-verifies every blast-radius consumer the planner named. |
|
|
63
|
+
| **Dependency rationale** (why each depends-on / conflicts-with edge) | Technical Dependencies | The brief turns the *why* of each edge into the concrete "what must already exist" preconditions (exports, migrations, capabilities, merged dependencies). |
|
|
64
|
+
| **Traps to avoid** (concrete pitfalls the dig surfaced) | Context + Constraints | The trap becomes an explicit "do NOT do X; do Y instead" the executing agent cannot miss. Highest-value field — never drop it. |
|
|
65
|
+
| **Suggested agent-class** (high/mid/fast + one-line reason) | `For:` + `Reason:` header | The Brief Author confirms or deviates (with stated reason) and makes the **final** model pick. Class is the planner's; pick is the brief's. |
|
|
66
|
+
| **Stop-and-escalate** (when the agent must stop, not improvise) | Stop conditions | The planner's stop conditions are copied into the brief's stop-condition list verbatim in substance. |
|
|
67
|
+
| **Docs to keep coherent** (which specs/skills/docs this task will make incoherent) | the documentation-update list | The Brief Author turns the Planner's named list into the explicit doc-update items. Conditional: if the Planner stated "No docs touched," the list is "No doc updates required (Tier 0)." If the Planner named docs, they are all in the list. Presence-**and-correctness** of the list is the Planner's mechanical obligation, not naming docs from memory: the Planner names intended surfaces and the Brief Author derives the floor at brief-authoring time by matching those surfaces against `.vinaya/doc-owners` (`deriveSection7`), then supplements from the read obligation. Any override of the derived floor (added doc, or a derived pointer marked out of scope) must carry a one-line reason in the brief — silent overrides are a regression. |
|
|
68
|
+
|
|
69
|
+
**Reading the table:** left is the producer obligation (Planner role doc enforces it), right is the consumer obligation (brief-authoring skill enforces it). The two role docs must not contradict this table; if either needs to change what it emits or consumes, it changes *here*, and both sides update together.
|
|
70
|
+
|
|
71
|
+
**Premise pinning is deliberately NOT a field in this table.** `verify-dispatch`/`verify-task`'s `Premise:` block is file-content-level, perishable detail — current signatures, current constants — squarely inside the Brief Author's half of the division of labor this contract already describes, not a durable conclusion the Planner should seed as a rationale field. It is governed entirely by the Brief Author → Developer seam (`contracts/brief-developer.md`), not this one.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Rationale grammar
|
|
76
|
+
|
|
77
|
+
The eight left-column fields above are the rationale's **content**; this section defines its **format** — how a field must be written in the Issue body for it to be machine-detectable. Before this grammar existed the rationale was prose with no defined format; a check cannot parse what has no format.
|
|
78
|
+
|
|
79
|
+
Two serializations are accepted, case-insensitive, matched by field name (or an established synonym — e.g. `Depends-on` for **Dependency rationale**):
|
|
80
|
+
|
|
81
|
+
- **Bold-inline:** `**<Field>** — <content>` (e.g. `**Boundary** — …`)
|
|
82
|
+
- **Heading:** `### <Field>` followed by the content on subsequent lines (e.g. `### Traps to avoid`)
|
|
83
|
+
|
|
84
|
+
A ready-to-fill skeleton of the full eight-field rationale lives at `aeg-root/templates/issue-rationale-template.md` — copy it rather than reconstructing the shape from this section's prose; this section remains the grammar's definition.
|
|
85
|
+
|
|
86
|
+
**`Dependency rationale` carries one exception to the two-serialization tolerance above: it must be written `**Dependency rationale** — <content>` exactly** — bold-inline only, with the closing `**` immediately after the label, no colon inside the bold (`**Dependency rationale:**` is rejected) and no heading form. This field alone has a downstream consumer beyond the creation gate: `amendRationaleDeps` (`packages/aeg-forge-state/src/amend-rationale-deps.ts`), the only sanctioned way to edit `Depends-on`/`Conflicts-with` after creation, locates the section by the exact anchor `SECTION_HEADER` (`packages/aeg-forge-state/src/parse-rationale-deps.ts`) and refuses any other form. `checkIssueRationale` imports that same constant rather than a second regex, so a body it accepts is always rewritable by `amend-deps` — the two consumers share one grammar for this field. Found live 2026-08-05 on a real task Issue that used the colon form for all eight fields: it passed creation but could not be amended.
|
|
87
|
+
|
|
88
|
+
A task Issue's body must carry all eight fields in one of these two forms. **Canonical implementation:** `packages/aeg-core/src/issue-validation.ts` (`checkIssueRationale`, `isTaskIssueLabelSet`) — the single grammar/parser, consumed at two enforcement points per `aeg-root/enforcement.md`'s ring model:
|
|
89
|
+
|
|
90
|
+
- **Ring 0 (creation gate):** `packages/aeg-core/bin/open-issue.ts` refuses to create or edit a task Issue (any Issue labeled `vinaya/tranche:<slug>`) whose body fails `checkIssueRationale`. **It also refuses on three content checks, which grade what the fields *say* rather than that they exist:**
|
|
91
|
+
- `checkBlastRadiusScope` — if **Boundary** or **Project(s) + blast radius** names a path under a collision domain in `.aeg/packages` that none of the declared projects owns (ownership resolves against `.vinaya/projects.md`), the Issue must declare a second project or carry a `blast-radius-ack: <why one lens is enough>` line. `Project(s)` drives the review fan-out, so an under-declared blast radius under-governs the change. Dormant when `.aeg/packages` is absent.
|
|
92
|
+
- `checkNoBriefContent` — the body must carry no `## References`, `Technical surface map`, `Premise`, `Step 0`, or `Test Plan` section. Those are Brief-Author artifacts; an Issue is not a brief's home (it would go stale before work starts).
|
|
93
|
+
- `checkRationaleNamesDocs` — **Docs to keep coherent** and/or **Traps to avoid** must name at least one concrete doc path (`aeg-root/…`, `.claude/skills/…`, `.claude/rules/…`, `apps/<x>/CLAUDE.md`, `apps/<x>/specs/…`, a repo-level `*.md`). A genuinely doc-less surface uses the explicit `no-doc-surface` sentinel — the same shape as `Test Plan: unit-tests-only`. This is the only read-obligation signal a forge write leaves: the skill-check hook fires on file edits, and cutting an Issue edits no file.
|
|
94
|
+
|
|
95
|
+
A fourth check, `checkConflictCompleteness`, **warns and never blocks**: two open task Issues naming the same collision domain with no mutual `Conflicts-with` edge. Non-blocking because an Issue declares no precise file surface, so the overlap is a hint, not a fact.
|
|
96
|
+
- **Ring 1/2 (continuous oracle):** `verify-coherence`'s **R1** check re-runs the same function against the live stock of open task Issues, catching bodies edited by ungated writers or predating the gate. Pre-grammar Issues are grandfathered by explicit Issue number (`R1_GRANDFATHERED_ISSUES` in `packages/aeg-core/src/coherence-checks.ts`) — visible as `info`, never blocking.
|
|
97
|
+
|
|
98
|
+
R1 checks **presence/structure only**; whether the content is correct (sizing actually right, traps actually real) stays the Reviewer's judgment, never CI's.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Producer obligations (the Planner)
|
|
103
|
+
|
|
104
|
+
- **Cut a real forge Issue for every task before dispatch.** Before the Brief Author can author a brief, the Planner must have replaced any `#TBD` in the topology table's Issue column with a real GitHub Issue number. A `#TBD` entry means the task has no forge Issue — it is neither briefable nor executable regardless of its derived status. The Brief Author hard-STOPs on `#TBD` during Dig; the Developer hard-STOPs at entry gate item 3. Cutting the Issue makes the task forge-addressable and dispatchable; it is a Planner-only act.
|
|
105
|
+
- Emit a rationale block per task containing **all eight left-column fields**. (Enforced in `planner.md` — a task missing its rationale is refused.) The eighth field, **Docs to keep coherent**, must name every spec/skill/doc this task will make incoherent, or state "No docs touched" explicitly. Omitting it forces the Brief Author to populate the documentation-update list from memory — the exact failure the read obligation exists to close.
|
|
106
|
+
- The rationale holds durable conclusions only — no perishable line-level detail (that's the Brief Author's half).
|
|
107
|
+
- `Project(s)` must include every shared-package consumer in the blast radius (the blast-radius rule in `planner.md`).
|
|
108
|
+
- **Read relevant docs before emitting the "Docs to keep coherent" field.** The read obligation requires the Planner to have identified and read the relevant specs/skills/docs before planning. The "Docs to keep coherent" field is only trustworthy if it was derived from reading, not from memory.
|
|
109
|
+
|
|
110
|
+
## Consumer obligations (the Brief Author)
|
|
111
|
+
|
|
112
|
+
- Read the rationale first; **start from it, never from a blank page**. (Enforced in `brief-authoring`.)
|
|
113
|
+
- Consume **every** right-column mapping — no field dropped.
|
|
114
|
+
- Add the perishable detail the planner deliberately left out (current signatures, exact file list, final model pick).
|
|
115
|
+
- **Read obligation:** During the Dig, identify and read any specs/skills/docs relevant to this task's code surface. Then (a) surface in Context what the Developer must know from those docs, and (b) populate the documentation-update list from this reading — the Planner's "Docs to keep coherent" field is the starting point, but the Brief Author's own reading may surface additional docs the Planner missed.
|
|
116
|
+
- If the Brief Author's own dig **contradicts** the rationale (the boundary moved, sizing no longer holds), that is a `severity:strategy` escalation back toward the Planner — not a silent override.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Changing this contract
|
|
121
|
+
|
|
122
|
+
A contract changes **as a unit**. You may not change what the Planner emits without, in the same change, updating what the Brief Author consumes — because the property that makes the seam sound is that the producer's output side is *identical* to the consumer's input side. Concretely:
|
|
123
|
+
|
|
124
|
+
- A change to this file is a **Tier 3** change: it alters a cross-role contract, so the reasoning belongs in the pull request that makes it, where the reviewer and the close-out both read it.
|
|
125
|
+
- The same PR that edits this contract must verify both `planner.md` and `brief-authoring/SKILL.md` still point here and still match the table (they should need no field-level edits, since the fields live here — but their references must stay valid).
|
|
126
|
+
- Never edit one side's role doc to add/drop a hand-off field directly. Add/drop it **here**; the role docs inherit it by reference.
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
*This contract is the seam. The Planner fills the left column; the Brief Author drains the right. One source of truth, changed as a unit.*
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_title: Reviewer → Archivist
|
|
3
|
+
title: Reviewer → Archivist
|
|
4
|
+
order: 4
|
|
5
|
+
contract_id: reviewer-archivist
|
|
6
|
+
description: Carries a review’s actual findings into the permanent record, so a verdict says what was checked, not just that it passed.
|
|
7
|
+
status: active
|
|
8
|
+
producer: reviewer
|
|
9
|
+
consumer: archivist
|
|
10
|
+
carrier: pr-verdict-comment
|
|
11
|
+
summary: Ever had a vague "looks good" review that told you nothing about what was checked?
|
|
12
|
+
---
|
|
13
|
+
# Contract: Reviewer → per-task Archivist
|
|
14
|
+
|
|
15
|
+
## The short version
|
|
16
|
+
|
|
17
|
+
This seam sits between a review and the permanent record of the work it reviewed. It exists because close-out can only be honest if the verdict it reads says what was actually checked.
|
|
18
|
+
|
|
19
|
+
**What crosses** — the reviewer's verdict, and the merged pull request that carries it. The verdict itself: approved, or changes requested. The findings, each with a severity, so the record can tell a note from a blocker. And the result of the check against the product's own specification — whether the change conforms to it, drifts from it, contradicts it, or reveals that the specification itself is now stale.
|
|
20
|
+
|
|
21
|
+
**The hand-off is malformed when** — the verdict is absent or unclear, when a finding carries no severity, or when the specification check is simply not stated. A verdict comment missing any of the three is not posted; the reviewer revises it first. "Looks good" is the failure this seam was written against: it tells the record nothing about what was examined, and close-out then has the choice of inventing a field or leaving a hole.
|
|
22
|
+
|
|
23
|
+
**What it does not carry** — permission to close out an unmerged change. The verdict is not the authorisation; the merge is. Nor does it carry any obligation to re-review: close-out is bookkeeping, not a second opinion, and a merged change is not reopened because the record-keeper would have judged it differently.
|
|
24
|
+
|
|
25
|
+
**How it physically runs** — the carrier is the verdict comment on the pull request, which becomes a frozen fact once that pull request merges. The verdict line is written bare, on its own line, because it is read by machine as well as by people, and the merge gate requires a clean one. After the merge, close-out reads it from the pull request's own history and copies it into the provenance record. A serious finding that was raised and merged anyway means a deviation was consciously accepted — it is recorded as such, not quietly dropped. A finding that the specification has gone stale becomes a follow-up issue, because it is not a reason to block the merge and must not vanish either.
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Reference
|
|
31
|
+
|
|
32
|
+
**Status:** active
|
|
33
|
+
**Seam:** the hand-off from the Reviewer (producer) to the per-task Archivist (consumer).
|
|
34
|
+
**Single source of truth for this seam.** The two role docs do **not** redefine what crosses this boundary — they point here. `aeg-root/roles/reviewer.md` (producer side) and `aeg-root/roles/archivist.md` (consumer side) each reference this file; this file is where the field-by-field hand-off lives, once.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Why this file exists
|
|
39
|
+
|
|
40
|
+
Close-out is not a mechanical afterthought — it is the step that makes a tranche's history honest. When the Reviewer's verdict is incomplete (no severity tags, no spec-conformance result, no explicit verdict line), the Archivist cannot assemble the provenance block correctly: they cannot distinguish what was reviewed from what was inferred, what was found from what was missed. This contract removes that ambiguity by specifying exactly what the Reviewer's verdict must contain and exactly what the Archivist reads from it.
|
|
41
|
+
|
|
42
|
+
The failure mode this prevents: an Archivist who assembles a provenance block with fabricated or inferred fields because the Reviewer's comment was vague; or a BLOCKER finding that merged silently because the Archivist didn't know it existed; or a STALE-SPEC finding that disappeared without a follow-up Issue because no one tracked it.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## The hand-off carrier
|
|
47
|
+
|
|
48
|
+
The **Reviewer's verdict comment** on the open (then merged) PR, plus the **merged PR itself**. The verdict comment is the producer's output; the merge is the trigger that authorizes the Archivist to begin close-out. The Archivist reads the verdict from the PR's review history — it is a frozen fact on the PR record.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## The contract — field-by-field mapping
|
|
53
|
+
|
|
54
|
+
Every item the Reviewer produces in the verdict (left) has exactly one obligation for the per-task Archivist (right). A verdict missing any left-column item is malformed — the Reviewer refuses to post it in that state.
|
|
55
|
+
|
|
56
|
+
| Reviewer produces | per-task Archivist consumes at | What the consumption means |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| **Verdict** (`APPROVE` or `REQUEST CHANGES`) | Entry gate | The Archivist only runs close-out on `APPROVE` + merged PRs. A `REQUEST CHANGES` verdict means the task is not done — close-out does not run until the Reviewer posts `APPROVE` and the PR is subsequently merged. |
|
|
59
|
+
| **Finding list** with severity tags (`BLOCKER` / `MAJOR` / `MINOR` / `NIT`) | Provenance block assembly | The Archivist includes the verdict and finding count in the provenance block. A `MAJOR` or `BLOCKER` finding that merged despite being raised means a deviation was approved — the Archivist logs it in the provenance block under DANGLING. |
|
|
60
|
+
| **Spec-conformance result** (`CONFORMS` / `DRIFTS` / `CONTRADICTS` / `STALE-SPEC`) | Provenance block + pinned lessons Issue | `CONTRADICTS` that merged is a `severity:strategy` flag in the provenance block. `STALE-SPEC` triggers a follow-up Issue (the Archivist opens it if the Developer did not) — it is not a reason to block merge, but it must not disappear. |
|
|
61
|
+
|
|
62
|
+
**Reading the table:** left is the producer obligation (Reviewer role doc and this contract enforce it), right is the consumer obligation (Archivist role doc and this contract enforce it). The two role docs must not contradict this table.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Producer obligations (the Reviewer)
|
|
67
|
+
|
|
68
|
+
- Every finding must carry a severity tag (`BLOCKER`, `MAJOR`, `MINOR`, or `NIT`). A finding without a tag is malformed — the Reviewer revises the comment before the verdict is considered valid.
|
|
69
|
+
- The verdict line must be the **first line** of the verdict comment, in the exact format specified by `roles/reviewer.md`: `VERDICT: APPROVE | REQUEST CHANGES`.
|
|
70
|
+
- The spec-conformance result must be stated explicitly — `CONFORMS`, `DRIFTS`, `CONTRADICTS`, or `STALE-SPEC`. "Not checked" is not acceptable for Tier 1+ tasks with a named Project.
|
|
71
|
+
- A verdict comment missing any of these three elements is malformed. The Reviewer does not post it.
|
|
72
|
+
- Append one row to the tranche's token ledger after posting the verdict.
|
|
73
|
+
|
|
74
|
+
## Consumer obligations (the per-task Archivist)
|
|
75
|
+
|
|
76
|
+
- Do not run close-out on unmerged PRs. The merge is the authorization signal — confirmed by querying the forge, not by reading a status field.
|
|
77
|
+
- Assemble the provenance block from frozen PR facts (brief in PR body, verdict comment, merge metadata) — never fabricate a field whose source fact is absent. A missing source fact is a DANGLING item, not an opportunity to infer.
|
|
78
|
+
- Post the provenance block as a comment on the merged PR (the PR is a frozen truth domain once merged; the provenance block is its permanent record).
|
|
79
|
+
- **The provenance block comment is the forge-derived coherence signal that downstream roles depend on.** The next Developer to start a task in this tranche checks whether the most-recently-merged task PR carries a provenance block before executing step 0 — its absence is a hard STOP that blocks the next task from starting. Post it completely; a partial or absent block does not satisfy the Developer's entry gate (see `aeg-root/roles/developer.md` and `aeg-root/contracts/brief-developer.md`).
|
|
80
|
+
- A `BLOCKER` or `MAJOR` finding present in the verdict of a merged PR means a deviation was approved. Log it in the provenance block under DANGLING and post a new comment on the pinned lessons Issue.
|
|
81
|
+
- A `STALE-SPEC` finding in a merged PR must produce a follow-up Issue if the Developer did not already open one. This is the Archivist's responsibility to ensure it happens.
|
|
82
|
+
- Append one row to the tranche's token ledger at close-out.
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Changing this contract
|
|
87
|
+
|
|
88
|
+
A contract changes **as a unit**. You may not change what the Reviewer produces without, in the same change, updating what the per-task Archivist consumes — because the property that makes the seam sound is that the producer's output side is *identical* to the consumer's input side. Concretely:
|
|
89
|
+
|
|
90
|
+
- A change to this file is a **Tier 3** change: it alters a cross-role contract, so the reasoning belongs in the pull request that makes it, where the reviewer and the close-out both read it.
|
|
91
|
+
- The same PR that edits this contract must verify both `aeg-root/roles/reviewer.md` and `aeg-root/roles/archivist.md` still point here and still match the table.
|
|
92
|
+
- Never edit one side's role doc to add/drop a hand-off field directly. Add/drop it **here**; the role docs inherit it by reference.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
*This contract is the seam. The Reviewer fills the left column; the per-task Archivist drains the right. One source of truth, changed as a unit.*
|