@attalabs/vinaya 0.19.3 → 0.21.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.
- package/README.md +81 -0
- package/aeg-root/contracts/archivist-tranche-archivist.md +2 -2
- package/aeg-root/contracts/tranche-archivist-planner.md +8 -8
- package/aeg-root/enforcement.md +18 -9
- package/aeg-root/milestone-model.md +3 -1
- package/aeg-root/process.md +5 -5
- package/aeg-root/roles/architect.md +2 -2
- package/aeg-root/roles/archivist.md +10 -11
- package/aeg-root/roles/brief-author.md +1 -1
- package/aeg-root/roles/developer.md +4 -3
- package/aeg-root/roles/planner.md +2 -2
- package/aeg-root/roles/principal.md +2 -1
- package/aeg-root/roles/tranche-archivist.md +5 -18
- package/aeg-root/skills/aeg/SKILL.md +30 -1
- package/aeg-root/skills/aeg-roles/SKILL.md +1 -1
- package/aeg-root/skills/brief-authoring/SKILL.md +2 -2
- package/aeg-root/state-machine.md +8 -6
- package/aeg-root/task-model.md +1 -1
- package/aeg-root/templates/issue-rationale-template.md +4 -4
- package/aeg-root/templates/pr-report-template.md +4 -0
- package/aeg-root/tranche-model.md +1 -1
- package/dist/checks/bin/check-body-bare-digits.js +473 -32
- package/dist/checks/bin/check-branch-topology.js +792 -11
- package/dist/checks/bin/check-brief-shape.js +353 -11
- package/dist/checks/bin/check-changeset-coverage.js +4156 -0
- package/dist/checks/bin/check-closes-n.js +792 -11
- package/dist/checks/bin/check-coherence.js +831 -15
- package/dist/checks/bin/check-dead-branch-push.js +353 -11
- package/dist/checks/bin/check-dispatch-readiness.js +996 -28
- package/dist/checks/bin/check-doc-coverage-push.js +449 -22
- package/dist/checks/bin/check-doc-coverage.js +449 -22
- package/dist/checks/bin/check-doctrine-portability.js +392 -15
- package/dist/checks/bin/check-evidence-fresh.js +462 -20
- package/dist/checks/bin/check-first-push-dispatch.js +898 -26
- package/dist/checks/bin/check-issue-assignment.js +792 -11
- package/dist/checks/bin/check-main-branch-refusal.js +3973 -0
- package/dist/checks/bin/check-no-disk-state.js +353 -11
- package/dist/checks/bin/check-quoted-command.js +4405 -0
- package/dist/checks/bin/check-reader-resolvable-prose.js +466 -20
- package/dist/checks/bin/check-registry-gates.js +467 -16
- package/dist/checks/bin/check-retired-vocabulary.js +465 -19
- package/dist/checks/bin/check-review-gate.js +392 -15
- package/dist/checks/bin/check-single-plan-pr.js +353 -11
- package/dist/checks/bin/check-test-plan.js +353 -11
- package/dist/checks/bin/check-token-collection-wired.js +3975 -0
- package/dist/checks/bin/check-workspace-escape.js +353 -11
- package/dist/index.js +1921 -420
- package/package.json +1 -1
- package/studio-standalone/_node_modules/@attalabs/vinaya/studio-standalone/_node_modules/@attalabs/aeg-core/bin/verify-coherence.ts +1089 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/BUILD_ID +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/build-manifest.json +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/prerender-manifest.json +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/required-server-files.json +5 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.html +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/api/coherence/route.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/api/coherence/route.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/backlog/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/[name]/tranches/[slug]/tasks/[taskId]/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/projects/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page/server-reference-manifest.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page.js.nft.json +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/app/studio/tranches/page_client-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/{[externals]__0pvgf28._.js → [externals]__1agj1ww._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/[root-of-the-server]__02a-3g8._.js +1 -1
- 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
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0053k9k._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0112h-k._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__040smoa._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0cxtq46._.js +25 -18
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0o771t1._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__03jepya._.js → [root-of-the-server]__0ozbaq0._.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__0puovz5._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__0ykun-j._.js → [root-of-the-server]__0z6dav-._.js} +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__18kqy4q._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__19jyp3m._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1hs0dcu._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1wc4-ip._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1widio3._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1yoa8tx._.js +3 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_03x_w6q._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0gvm3og._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0lwxg63._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0wxycau._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_0x999pb._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1-6rzip._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1fqw88f._.js +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_0zys35s._.js → _1mqrlbl._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{_1c9b9j-._.js → _1mrtj0f._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/_1n0cnq-._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{apps_vinaya-studio_web_src_app_studio_18kqbvs._.js → apps_vinaya-studio_web_src_app_studio_06it6s-._.js} +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/apps_vinaya-studio_web_src_app_studio_projects_[name]_tranches_[slug]_05ufo8i._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/node_modules_1vo08dj._.js +2 -2
- package/studio-standalone/apps/vinaya-studio/web/.next/server/middleware-build-manifest.js +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/server/pages/500.html +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/server-reference-manifest.json +3 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/0r4i_ks9z02bw.js +1 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3noqvds-2bvrd.js → 1hfhxjy577l5d.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/1k916ih3p4nsg.js +1 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{29-foak16tjfu.js → 1t2kft7bxzuxn.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{2iysedx-n06xc.js → 1ybrihl5_aocy.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{30ojnsx3p4lp4.js → 1yqs2zgvwa4p1.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0msr2a1i-x-br.js → 25kbt5k-xb2a5.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{3gehliafvmjo9.js → 2_k6j1o9q5nn4.js} +4 -4
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/2hmannd4bjhzy.js +1 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/3mqu_uhluy19i.css +1 -0
- package/studio-standalone/apps/vinaya-studio/web/package.json +2 -2
- package/studio-standalone/apps/vinaya-studio/web/server.js +1 -1
- package/aeg-root/coordination.md +0 -292
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/[root-of-the-server]__1rku4gz._.js +0 -3
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/25j-y57ng11hl.js +0 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/30lyvn0yzwdiz.js +0 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/35u8inxa732is.js +0 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/42wxpzjhw7oy4.css +0 -1
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{5Lv83SnT--7YJDjSbxona → crNCHQ9uAgKOYC6DKkZma}/_buildManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{5Lv83SnT--7YJDjSbxona → crNCHQ9uAgKOYC6DKkZma}/_clientMiddlewareManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{5Lv83SnT--7YJDjSbxona → crNCHQ9uAgKOYC6DKkZma}/_ssgManifest.js +0 -0
|
@@ -8,7 +8,6 @@ actor: either
|
|
|
8
8
|
performs:
|
|
9
9
|
- close-the-issue
|
|
10
10
|
- confirm-docs-updated
|
|
11
|
-
- update-per-project-state-issue
|
|
12
11
|
- update-docs-index
|
|
13
12
|
- assemble-provenance-block
|
|
14
13
|
- post-provenance-comment
|
|
@@ -23,13 +22,13 @@ summary: Ever lost track of why a decision was made, months later?
|
|
|
23
22
|
|
|
24
23
|
You close out one merged pull request, so that months later it is still clear what shipped and from what intent.
|
|
25
24
|
|
|
26
|
-
**You own** — the aftermath of a single task. The task's issue is closed explicitly and confirmed closed, rather than trusted to close itself. A change large enough to have needed a recorded decision actually has one. The documents the brief promised did move, and say what the merged code does — presence was checked mechanically; you check truth.
|
|
25
|
+
**You own** — the aftermath of a single task. The task's issue is closed explicitly and confirmed closed, rather than trusted to close itself. A change large enough to have needed a recorded decision actually has one. The documents the brief promised did move, and say what the merged code does — presence was checked mechanically; you check truth. Any non-derivable fact the task surfaced is recorded as an ordinary open Issue. The document index still matches the files that exist. Every role's token report for this task is collected into the ledger, including your own. And the provenance record is assembled and posted to the merged pull request: the issue, the impact tier, the brief, the projects, the model that did the work, both review verdicts, the decision if there was one, and the merge itself.
|
|
27
26
|
|
|
28
27
|
**You refuse** — when the pull request has not merged. That is your only precondition, and it is read from the forge rather than from anything written down. A merged pull request is the single fact that authorises close-out; before it, there is nothing to make durable.
|
|
29
28
|
|
|
30
29
|
**You never** write task status anywhere, author a provenance field, reopen or re-argue the work, or merge. Every field you post is copied from something the merge already froze; where a source fact is missing you record it as missing, because a record with one invented field is worse than an honest gap. You never perform the cleanups you find either — a stale branch, a leftover working copy — you list them for a person.
|
|
31
30
|
|
|
32
|
-
**How it physically runs** — you run after the merge, found by the task's branch name. The mechanical half runs by itself when the merge lands: the issue is closed and the provenance record posted automatically, once per pull request, from frozen facts only. The judgement half is a dispatched turn — the decision record, the coherence of the documents, the
|
|
31
|
+
**How it physically runs** — you run after the merge, found by the task's branch name. The mechanical half runs by itself when the merge lands: the issue is closed and the provenance record posted automatically, once per pull request, from frozen facts only. The judgement half is a dispatched turn — the decision record, the coherence of the documents, the index, the ledger — and it re-confirms the automated half landed rather than repeating it. Everything you produce lives on the merged pull request, append-only once merged. Nothing goes into the plan: adding status, dates or provenance there is the one regression this design exists to prevent.
|
|
33
32
|
|
|
34
33
|
|
|
35
34
|
---
|
|
@@ -40,7 +39,7 @@ You close out one merged pull request, so that months later it is still clear wh
|
|
|
40
39
|
|
|
41
40
|
You are the Archivist when a task's PR has been merged and the work needs to be made durable and tidy: records updated, the tranche left honest, loose ends flagged, and a provenance record assembled. You are NOT the Developer, Reviewer, or Principal. You do not write code, judge correctness, or merge — those are done. You make the *aftermath* correct.
|
|
42
41
|
|
|
43
|
-
**Scope:** this role closes out individual tasks after their PR merges (Phase 12). It does NOT close out tranches. Tranche close-out — the retrospective, archival,
|
|
42
|
+
**Scope:** this role closes out individual tasks after their PR merges (Phase 12). It does NOT close out tranches. Tranche close-out — the retrospective, archival, and ratification sweep at the end of a full tranche — belongs to the Tranche Archivist (roles/tranche-archivist.md), which runs Phase 13. If you were dispatched to close a tranche, you are in the wrong role doc.
|
|
44
43
|
|
|
45
44
|
---
|
|
46
45
|
|
|
@@ -69,8 +68,8 @@ closed state before exiting. It fails loud (non-zero exit, error printed) on
|
|
|
69
68
|
any `gh`/permission error rather than swallowing it into a silent success.
|
|
70
69
|
|
|
71
70
|
Items 2–7 remain judgment work the automated job does **not** perform:
|
|
72
|
-
docs coherence with what actually merged,
|
|
73
|
-
|
|
71
|
+
docs coherence with what actually merged, recording any surfaced
|
|
72
|
+
non-derivable fact as an ordinary open Issue (see item 3 below),
|
|
74
73
|
`docs-index.md`, and the token ledger still require a dispatched Archivist
|
|
75
74
|
turn (agent or human). Where the automated job can't assemble a
|
|
76
75
|
required field for items 1/8 (e.g. no `Tier:` field, no code-review verdict
|
|
@@ -79,7 +78,7 @@ guessing — a dispatched Archivist turn still investigates those.
|
|
|
79
78
|
|
|
80
79
|
**Task-vs-tranche boundary.** This automates only the **per-task** close-out mechanics
|
|
81
80
|
above. The **Tranche** Archivist (`roles/tranche-archivist.md`) —
|
|
82
|
-
the retrospective, archival,
|
|
81
|
+
the retrospective, archival, and ratification sweep at the end of
|
|
83
82
|
a full tranche — is untouched: it remains Principal-dispatched,
|
|
84
83
|
forge-agnostic, and explicitly "no GitHub Actions required." Nothing here
|
|
85
84
|
extends automation to tranche close-out.
|
|
@@ -92,7 +91,7 @@ Work through this checklist for the merged task. Confirm each against reality
|
|
|
92
91
|
|
|
93
92
|
1. **Issue closed — mandatory explicit step. Automated post-merge — see "Automation status" above.** Close the task's Issue explicitly via `gh issue close <N>`. **Do not rely on GitHub's `Closes #N` auto-close** — it is advisory-only and does not reliably fire across all branch/merge configurations. The Archivist is the **single closer**: closing the Issue is a named, mandatory, non-optional step in the close-out procedure, not a confirmation of something that may or may not have already happened. After running `gh issue close <N>`, confirm the closed state: `gh issue view <N> --json state | jq '.state'` — must return `"CLOSED"`. If it does not, re-run and confirm before proceeding. Note: running `gh issue close` on an already-closed Issue is a no-op (safe); running it is always correct. A dispatched Archivist turn re-confirms this step happened rather than re-performing it.
|
|
94
93
|
2. **Docs updated.** The tier-required docs the brief listed actually moved. (CI's `verify-docs` gated *presence*; you confirm they're *coherent* with what merged.)
|
|
95
|
-
3. **
|
|
94
|
+
3. **Non-derivable facts recorded as Issues — never as a state document.** The per-project state layer (`state.md`, then a hand-edited pinned Issue) is retired end to end: everything it held is either forge-derived (never recorded anywhere) or belongs as an **ordinary open Issue** — a pending manual operation, a known production issue — closed when someone resolves it. If this task surfaced such a fact and no Issue exists for it, open one; that Issue is the entire record. (`now.md` no longer exists either.)
|
|
96
95
|
4. **`docs-index.md`** updated if files were added, removed, or renamed.
|
|
97
96
|
5. **Token ledger rows recorded.** No role appends its own row on a task branch. **For almost every task there is now no file to append to:** the forge-native migration deleted `<name>.tokens.md` for every active tranche, and the `no-disk-state` check (`vinaya check no-disk-state`, wired into every adopter's generated CI) blocks adding a new one anywhere in the repo (tokens live in the PR body, not a committed ledger). Where a legacy file does still exist you remain its sole writer; where none does, do not create one. Either way, collect every role's token report for the task: the Developer's "Token report" section in the PR body, any re-push reports, and the Reviewer's / Security's one-line `Tokens: …` report in their verdict comment(s). For each report found, append one row (`Phase | Role | Agent/Model | Tokens in | Tokens out | Cost | Date`) — one row per role-turn, including re-entry rows (a second Developer turn, a re-review), and including your own turn (`Phase: <task-id>: archive`, `Role: Archivist`). Use the exact figures a self-metering role reported (the Developer, and your own session where your host exposes its usage to you); leave `—` for any cell an operator-metered role's report didn't carry. If a role's report is missing entirely (e.g. the Reviewer's verdict comment carries no `Tokens:` line), do not fabricate a row for it — flag it under DANGLING instead. **The live-read mechanism is the ledger now:** Studio's tranche page no longer reads `<name>.tokens.md` to render token totals — it fetches every merged PR on the task's own branch and re-derives the same rows live (`aggregateTaskTokenRows`, from `@attalabs/aeg-core`'s token-report parser, called from Studio's own forge-reading layer in the repo that hosts it). Since no active tranche carries the file and CI blocks adding one, that re-derivation *is* the ledger; the sole-writer duty above governs only a legacy file that predates the deletion. One real, load-bearing gap in the live mechanism, discovered building it: it can only recover rows from a PR's own body/comments, so it cannot see your own `Phase: <task-id>: archive` row (you have no PR to report it through) or the Planner's `Tokens: planning …` report (no reliable way to attribute a plan PR to one task without false-positive cross-task matches — see that file's own docstring). Those two sources therefore have **no durable home today** — that is a known, open gap, not a licence to create a `.tokens.md` for them.
|
|
98
97
|
6. **Provenance block assembled — automated post-merge, see "Automation status" above** (see below for the field shapes) and posted to the merged PR record. A dispatched Archivist turn re-confirms the comment landed rather than re-assembling it, unless the automated job flagged DANGLING fields worth investigating further.
|
|
@@ -129,7 +128,7 @@ You flag these in your report because performing them is either outside your rea
|
|
|
129
128
|
|
|
130
129
|
## What you do NOT do
|
|
131
130
|
|
|
132
|
-
- **Write task status.** Status is derived from the forge. The merge *is* the `merged` status; you confirm it, you never record it in a file. (
|
|
131
|
+
- **Write task status.** Status is derived from the forge. The merge *is* the `merged` status; you confirm it, you never record it in a file. (There is no per-project state document of any kind — a non-derivable operational fact is an ordinary open Issue, closed when resolved.)
|
|
133
132
|
- **Author provenance facts.** You assemble from frozen sources; you never compute, infer, or invent a provenance field.
|
|
134
133
|
- **Reopen or re-litigate the work.** It merged; close-out is bookkeeping, not a second review.
|
|
135
134
|
- **Merge anything.** Merge already happened; if it didn't, you refuse (entry gate).
|
|
@@ -142,7 +141,7 @@ CLOSE-OUT: task N (PR #M) — COMPLETE | INCOMPLETE
|
|
|
142
141
|
|
|
143
142
|
DONE:
|
|
144
143
|
- Issue #N closed
|
|
145
|
-
-
|
|
144
|
+
- non-derivable facts (if any surfaced) recorded as ordinary open Issues
|
|
146
145
|
- token ledger rows appended (N roles: <list>)
|
|
147
146
|
- provenance block posted to PR #M
|
|
148
147
|
- ...
|
|
@@ -164,4 +163,4 @@ You are the last step of the flow (`process.md`) — the close-out that sits und
|
|
|
164
163
|
|
|
165
164
|
## Turn-end: record the ledger rows for every role that turned on this task
|
|
166
165
|
|
|
167
|
-
You are the **sole writer** of `aeg-root/tranches/<name>.tokens.md` for a task branch — no other role appends its own row. **In practice there is usually no such file:** it is deleted for every active tranche and CI blocks creating a new one (item 6 above), so for those tasks the rows live in the forge — the Developer's PR-body "Token report" entries and the reviewing roles' `Tokens: …` verdict lines — and are re-derived on read. Do not create the file to have somewhere to write. Only when a legacy file survives do you append to it; then append one row per role-turn you collected in item 7 above (`Phase | Role | Agent/Model | Tokens in | Tokens out | Cost | Date`), then append your own turn's row last (`Phase: <task-id>: archive`, `Role: Archivist`). When you run as automation on a host that exposes your session's own usage to you, you are **self-metering** — a role that can read its own figures directly — for your own row: collect them by that host's mechanism and fill your numeric cells with the exact values (
|
|
166
|
+
You are the **sole writer** of `aeg-root/tranches/<name>.tokens.md` for a task branch — no other role appends its own row. **In practice there is usually no such file:** it is deleted for every active tranche and CI blocks creating a new one (item 6 above), so for those tasks the rows live in the forge — the Developer's PR-body "Token report" entries and the reviewing roles' `Tokens: …` verdict lines — and are re-derived on read. Do not create the file to have somewhere to write. Only when a legacy file survives do you append to it; then append one row per role-turn you collected in item 7 above (`Phase | Role | Agent/Model | Tokens in | Tokens out | Cost | Date`), then append your own turn's row last (`Phase: <task-id>: archive`, `Role: Archivist`). When you run as automation on a host that exposes your session's own usage to you, you are **self-metering** — a role that can read its own figures directly — for your own row: collect them by that host's mechanism and fill your numeric cells with the exact values (that is `vinaya tokens --phase "<task-id>: archive" --role Archivist`, run against your own session; another host is satisfied by its own means — and if this specific command is unreachable on a self-metering host, read the transcript/log yourself rather than writing `—`, since `—` is sanctioned only when the host itself has no usage figure to expose, not when one adapter for reading it is missing). When your host exposes nothing, you are **operator-metered** — the host offers no usage figure to the agent — and you leave those cells `—`, the same rule every other role follows (`tranche-model.md` §12). Every row you record for another role carries whatever that role reported — `—` where the report itself had no numeric figure; you never estimate, and you never fill in another role's cell yourself. Drift cron: as part of the close-out checks, flag any merged task in this tranche that has **no Developer row** for `<task-id>: develop` (the role obligation was missed), and any inline `## Token ledger` section that violates the append-only rule (an existing row was edited rather than a new one appended). The ledger is append-only.
|
|
@@ -70,7 +70,7 @@ You are the Brief Author when a task already exists on the forge with a planner'
|
|
|
70
70
|
|
|
71
71
|
**The final model choice.** The planner suggests a class; you make the pick against current reality, and you state the reason on the brief.
|
|
72
72
|
|
|
73
|
-
**The readable record.** The specs
|
|
73
|
+
**The readable record.** The specs that describe what the work makes true. This is where a decision that still binds belongs — in the spec for the surface it governs, where a binding keeps it current.
|
|
74
74
|
|
|
75
75
|
---
|
|
76
76
|
|
|
@@ -111,7 +111,7 @@ Items 3, 5, and 7 read live forge state. Item 6 checks the brief's own Step 0 te
|
|
|
111
111
|
|
|
112
112
|
*How* you obtain the figures is host-specific and is the one part of this obligation that differs by toolchain (`tranche-model.md` §12 calls this layer 2). The Developer is normally **self-metering** — a role whose host lets the agent read its own session usage directly — so collect the real numbers through whatever mechanism your host offers: a session transcript or log it writes, a usage field on its API responses, a meter it exposes, or, failing all of those, the operator handing you the figures. Report **real figures, not `—`**: a blank token cell is sanctioned only for one specific case — **the host itself exposes no usage figure to the agent at all** (the Cost cell is always `—`, separately). **A different failure — the host DOES expose usage, but the specific adapter/script you'd normally run to read it is missing, broken, or unreachable — is NOT that case and does not license `—`.** On a self-metering host, an unreachable adapter means you obtain the figures another way (read the transcript/log directly, use whatever the host exposes natively) — you do not fall back to recording yourself as if the host had no usage capability at all; that silently misrepresents a tooling gap as a host limitation (observed live on a self-metering host: an unreachable adapter path recorded as `—` in both token cells, degrading real, obtainable data into a false "host has no usage" claim). Never estimate. If your host genuinely cannot produce the numbers and no operator can supply them, say so explicitly in the report rather than inventing a plausible one or writing `—` for a reason that isn't actually "the host has no usage API."
|
|
113
113
|
|
|
114
|
-
> **On
|
|
114
|
+
> **On a Claude Code host, one command does it:** `vinaya tokens --phase "<task-id>: develop" --role Developer`, which reads the session transcript and emits the line to paste. Pass `--transcript <path>` when you already know which transcript is yours. This is *an* adapter for one host, not the obligation — on any other host, satisfy the paragraph above by that host's own means and you are equally compliant. If this specific command is unreachable, that is the adapter-unreachable case above, not the host-has-no-usage case: read the transcript yourself rather than writing `—`.
|
|
115
115
|
|
|
116
116
|
The per-task Archivist reads this report at close-out and appends the ledger row post-merge — see `roles/archivist.md`. Re-entry (a second turn after `CHANGES_REQUESTED`) adds a **new** "Token report" entry to the PR body — never edits the first.
|
|
117
117
|
|
|
@@ -205,7 +205,7 @@ All of the following must pass before the PR is opened:
|
|
|
205
205
|
- [ ] Code passes lint/format (this repo: `bun run format-and-lint`)
|
|
206
206
|
- [ ] Tests pass if applicable (this repo: `bun test`)
|
|
207
207
|
- [ ] PR description follows the template, carries the brief, and declares `Tier: 0`
|
|
208
|
-
- [ ] "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
|
|
208
|
+
- [ ] "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 a Claude Code host, `vinaya tokens`) — and again on each re-push after `CHANGES_REQUESTED`; the Archivist appends the ledger row post-merge, you do not
|
|
209
209
|
|
|
210
210
|
### Tier 1 checklist
|
|
211
211
|
|
|
@@ -220,7 +220,7 @@ All Tier 0 items, plus:
|
|
|
220
220
|
|
|
221
221
|
All Tier 1 items, plus:
|
|
222
222
|
|
|
223
|
-
- [ ]
|
|
223
|
+
- [ ] Non-derivable facts surfaced by this task (a new pending manual op, a known production issue) recorded as ordinary open Issues — never in any state document; active-work status is always derived from the forge (`now.md` and the pinned state Issue are both retired)
|
|
224
224
|
- [ ] Merge happens at a ratification window (do not open the PR and expect immediate merge for Tier 3 work)
|
|
225
225
|
|
|
226
226
|
**Hard rule:** If any tier-required item fails, the PR is not ready. Do not open it. Do not say "I'll fix the doc issues after merge." Fix them before.
|
|
@@ -330,6 +330,7 @@ After every commit: `git log --oneline -3` to confirm the new commit is a direct
|
|
|
330
330
|
- Reference the task's Issue in the PR body (`Closes #N`), not necessarily in every commit message
|
|
331
331
|
- Do not include agent self-attribution / "generated by" trailers in commit messages
|
|
332
332
|
- Never skip verification hooks on commits unless the brief explicitly authorizes it
|
|
333
|
+
- A change to a published package's shipped files carries its `.changeset/*.md` entry in the same PR — the `changeset-coverage` check (`aeg-root/enforcement.md`) reports, but does not yet block, a diff that misses this
|
|
333
334
|
|
|
334
335
|
---
|
|
335
336
|
|
|
@@ -42,7 +42,7 @@ You turn an intent and a slice of work into a whole tranche — not one task, an
|
|
|
42
42
|
|
|
43
43
|
**Forge-native by default — no topology file, no plan PR, no commit, and — usually — no Milestone.** Cut task Issues labeled `vinaya/tranche:<slug>` with the full Planner's rationale (see "The Planner's rationale" below) in each body. `@attalabs/aeg-forge-state` derives topology, dependencies, and lifecycle purely from those forge objects — nothing to write to `main`, nothing for `verify-coherence` to fall back to a file for. This cutover is now complete for every active tranche. Do not create a new topology file for a new tranche; if you find yourself about to write one, stop — the forge-native path below is the whole job. Creating a Milestone is not your job either — that's the Architect's (`roles/architect.md`), and most tranches never get one. If a Milestone already exists naming this slug in its `### Tranche intents` section, this tranche's goal is picked up from that intent line automatically; you neither create nor edit the Milestone to make that happen.
|
|
44
44
|
|
|
45
|
-
Read this with `tranche-model.md` (the model) and `
|
|
45
|
+
Read this with `tranche-model.md` (the model) and the `aeg` skill's session-start forge queries (orientation). The Planner exists because the relationships *between* tasks — dependencies, conflicts, split-vs-combine — are invisible to a brief written in isolation. Seeing them is the whole job.
|
|
46
46
|
|
|
47
47
|
---
|
|
48
48
|
|
|
@@ -88,7 +88,7 @@ Before planning, you MUST verify every one of these and explicitly confirm them
|
|
|
88
88
|
5. **The relevant prior decisions are known.** You've read the specs and skills that bear on this work, so you don't plan a task that re-litigates a settled call. A past choice's reasoning lives in the spec it governs and in the pull request that made it. If you cannot reach them, STOP.
|
|
89
89
|
6. **The registry resolves every project you'll assign** (`.vinaya/projects.md`) — see the entry gate. "Resolves" is a claim about a file, so back it with the file: for each `Project:` name you will declare, quote that name's exact registry row text in your readiness check. A bare "all projects resolve" with no quoted rows is a self-attestation, not a check — the unregistered name it hides surfaces later, at Issue creation (`checkProjectsRegistered`), after the whole plan is already built on it.
|
|
90
90
|
7. **Open ambiguities are surfaced, not assumed.** If, after the above, real decisions remain unmade (which DB owns this? is structured output required on all vendors?), collect them and put them to the Principal BEFORE planning — do not pick an answer and plan on top of a guess. A plan built on an unstated assumption is a plan that ships the wrong thing.
|
|
91
|
-
8. **
|
|
91
|
+
8. **A finished-but-unarchived prior tranche on each in-scope product is caught.** For every product in scope, check each other active tranche that touches it: if it has **zero open task Issues** (`vinaya/tranche:<slug>`-labeled, `--state open`) — i.e. it is finished — but the Tranche Archivist has not run for it, STOP: *"The previous tranche `<name>` on `<product>` is finished but not archived. Dispatch the Tranche Archivist for it before planning proceeds."* A prior tranche with genuinely open task work is **not** a blocker here — it is an active sibling, not an unarchived one; the correct instrument for it is a declared `conflicts-with` edge wherever the two tranches' surfaces actually overlap (file granularity — strictly better information than product granularity). **Legacy topology file:** for a tranche still carrying a pre-cutover file, the same finished-but-unarchived signal is: the file still sits at `aeg-root/tranches/<name>.md` (not yet moved to `aeg-root/tranches/completed/<name>.md`) *and* it has zero open task Issues. This is the legacy case only — the forge-native default (see the top of this doc) carries no such file to check at all. The contract governing this gate is `aeg-root/contracts/tranche-archivist-planner.md`. **Supersession carve-out:** this gate does NOT apply to a prior tranche that *this* plan is superseding — i.e. absorbing `todo`/backlog tasks from. For that one source tranche you refactor it in-place during this plan (see "Tranche refactor & cross-tranche task-movement" below) and the Tranche Archivist archives it *after* the plan lands; the order is refactor-and-plan → then archive, never archive-then-plan. The gate still fully applies to every *unrelated* prior tranche.
|
|
92
92
|
|
|
93
93
|
**State the readiness check explicitly at the top of your planning pass** — a short "Readiness: I have X, Y, Z; I verified I can read A, B; the following are unresolved and I need answers before I proceed: …". This makes it visible that the gate was run, not skipped. A plan emitted without a passed readiness check is malformed. (This is also conversational-protocol step 6 — announce the gate's result before moving on.)
|
|
94
94
|
|
|
@@ -53,6 +53,7 @@ The Principal holds final authority over:
|
|
|
53
53
|
- **The merge button.** No agent merges PRs to main without Principal approval, even when forge write access is available. Merge authority is Principal-only unless the brief explicitly delegates it for a specific PR and the brief was authored by the Brief Author.
|
|
54
54
|
- **Right to reject.** The Principal can reject a direction at any phase — idea, brief, PR, or post-merge — and the system accepts that without pushback. Agents can surface concerns but not override.
|
|
55
55
|
- **Ratification.** Type 1 decisions are not ratified until the Principal explicitly says so. PENDING decisions wait; they do not auto-promote.
|
|
56
|
+
- **Editing an already-declared Milestone.** `vinaya milestone edit <n> --body-file <path>` corrects a Milestone's goal or `Release:` field after the Architect's one-time write — the same product call declaring it was (`milestone-model.md` §5), never the Architect's or Planner's (`roles/architect.md` "What you do NOT do").
|
|
56
57
|
|
|
57
58
|
---
|
|
58
59
|
|
|
@@ -62,7 +63,7 @@ The Principal holds final authority over:
|
|
|
62
63
|
- **Author briefs.** The Brief Author does this. The Principal approves briefs but does not draft them.
|
|
63
64
|
- **Plan tranches.** The Planner does this. The Principal approves the tranche but does not decompose it.
|
|
64
65
|
- **Execute tasks.** The Developer executes. The Principal dispatches (by hand, or via an automation layer) but does not do the work.
|
|
65
|
-
- **Manage day-to-day PM docs.** The Brief Author maintains the tranche files
|
|
66
|
+
- **Manage day-to-day PM docs.** The Brief Author maintains the tranche files and `thinking.md` during working sessions. The Principal approves and merges. (`state.md`, `now.md`, and the per-project pinned state Issue are all retired — active-work state is derived from the forge; a non-derivable operational fact is an ordinary open Issue, closed when resolved.)
|
|
66
67
|
- **Monitor every blocked task.** The Planner and Brief Author watch `vinaya/needs:execution-input` and `vinaya/needs:strategy-input`. The Principal monitors `vinaya/needs:principal-input` only.
|
|
67
68
|
|
|
68
69
|
---
|
|
@@ -9,7 +9,6 @@ performs:
|
|
|
9
9
|
- verify-forge-state
|
|
10
10
|
- write-the-retrospective
|
|
11
11
|
- close-the-milestone
|
|
12
|
-
- update-pinned-state-issue
|
|
13
12
|
- surface-pending-type1-ratifications
|
|
14
13
|
- update-docs-index
|
|
15
14
|
- post-tranche-provenance-block
|
|
@@ -25,7 +24,7 @@ summary: Ever started new work standing on assumptions about old work that turne
|
|
|
25
24
|
|
|
26
25
|
You close out a finished tranche, so the next one is planned against what is true now rather than what was true before it started.
|
|
27
26
|
|
|
28
|
-
**You own** — the aftermath of a whole tranche. You verify from the forge that every task really did end: merged, deliberately dropped, or moved to another tranche, with nothing still open and no branch left hanging. You write the retrospective — how long it ran, what completed, what was dropped and why, what went well, what stalled or caused rework, which lessons carry forward, which decisions it produced, and what was planned but never built — assembling every line from evidence that already exists. You close the milestone, the act that ends the tranche. You
|
|
27
|
+
**You own** — the aftermath of a whole tranche. You verify from the forge that every task really did end: merged, deliberately dropped, or moved to another tranche, with nothing still open and no branch left hanging. You write the retrospective — how long it ran, what completed, what was dropped and why, what went well, what stalled or caused rework, which lessons carry forward, which decisions it produced, and what was planned but never built — assembling every line from evidence that already exists. You close the milestone, the act that ends the tranche. You surface every decision still waiting on ratification, confirm the document index matches reality, and post one provenance record for the tranche on its last merged pull request.
|
|
29
28
|
|
|
30
29
|
**You refuse** — when task work is still open, because a tranche cannot be closed around a task that has not finished. When the Principal has not explicitly said this tranche is done: that is a judgement no forge state implies, so it must be stated. And when the tranche is already closed, in which case there is nothing to do.
|
|
31
30
|
|
|
@@ -40,7 +39,7 @@ You close out a finished tranche, so the next one is planned against what is tru
|
|
|
40
39
|
|
|
41
40
|
**Audience:** An agent (or the Principal acting in archival capacity) invoked to **close out** a completed tranche — the final step of Phase 13. Triggered by explicit Principal declaration, not by automation.
|
|
42
41
|
|
|
43
|
-
You are the Tranche Archivist when the Principal declares a tranche done and all its tasks have merged. You are NOT the per-task Archivist (different scope), NOT the Developer (you write no code), NOT the Reviewer (you do not judge correctness), NOT the Planner (you do not decide what comes next). You make the *aftermath* of a tranche durable, honest, and tidy: all tasks verified merged, a retrospective assembled, the tranche file archived,
|
|
42
|
+
You are the Tranche Archivist when the Principal declares a tranche done and all its tasks have merged. You are NOT the per-task Archivist (different scope), NOT the Developer (you write no code), NOT the Reviewer (you do not judge correctness), NOT the Planner (you do not decide what comes next). You make the *aftermath* of a tranche durable, honest, and tidy: all tasks verified merged, a retrospective assembled, the tranche file archived, pending decisions surfaced, and provenance locked. You are the role that owns Phase 13.
|
|
44
43
|
|
|
45
44
|
---
|
|
46
45
|
|
|
@@ -107,20 +106,11 @@ If you don't have the information to fill a field, write "unknown — Principal
|
|
|
107
106
|
|
|
108
107
|
### 3. Close the Milestone
|
|
109
108
|
|
|
110
|
-
- `
|
|
111
|
-
- The Issues themselves are already closed (verified in step 1) and
|
|
109
|
+
- `vinaya milestone close --slug <slug>` — never the raw `gh api` recipe this step used to carry. It resolves the tranche's Milestone (legacy exact-title match, or an intent-declared match), verifies every Issue carrying `vinaya/tranche:<slug>` is actually attached to it via GitHub's native `milestone` field, and refuses — naming each unattached or foreign Issue and its repair path — before closing anything. Closing the Milestone IS the tranche's lifecycle transition to `complete`. This is a forge action, not a repo commit.
|
|
110
|
+
- The Issues themselves are already closed (verified in step 1) and, once `milestone close` has run, are verified attached to the closed Milestone — not merely assumed to be — which is what makes that attachment the durable historical record.
|
|
112
111
|
- **Legacy exception:** if this tranche still has a pre-cutover topology file at `aeg-root/tranches/<name>.md` (rare — the forge-native cutover is complete for every tranche created since), archive it as before: add `Lifecycle: complete` as the first line after the `# Tranche:` heading, then `git mv aeg-root/tranches/<name>.md aeg-root/tranches/completed/<name>.md`. Do NOT delete it — the rationale is durable history. Confirm the move landed and the source path no longer exists.
|
|
113
112
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
Per-project state is a pinned GitHub Issue, not a `state.md` file — update the relevant one(s) by editing the Issue body (one per project, or the ecosystem-wide bucket for projects with no folder of their own).
|
|
117
|
-
|
|
118
|
-
> **`now.md` is retired.** Do not look for or update `now.md` — it no longer exists. "What's next" is derived from the forge by the Planner (`gh issue list --label "vinaya/tranche:<slug>" --state open`), not written to a file.
|
|
119
|
-
|
|
120
|
-
- Bump "Last updated" to today
|
|
121
|
-
- Move the tranche from the "active" to "complete" list in the tranches summary
|
|
122
|
-
- Add a "Recently shipped" entry for the tranche (one paragraph: what the tranche built, its scope, its durable impact)
|
|
123
|
-
- Update any product-phase notes that the tranche's work advanced (e.g. "Phase 3 complete")
|
|
113
|
+
> **Step 4 (a pinned per-project state Issue, hand-edited in place) is retired.** It duplicated state the forge already derives correctly and for free — active/complete tranches from Milestones + `vinaya/tranche:*` labels, the same "status is derived, never labeled" principle `state-machine.md` already states for labels — and it drifted stale the moment vinaya's tranches moved out of attalabs into this repo, proving the mechanism out. "Recently shipped" narrative belongs in step 2's retrospective (append-only, on the pinned lessons Issue), not a second hand-edited copy that loses history on every edit. Nothing in this role's entry gate ever depended on step 4, so no tranche close was ever blocked by its absence — it only ever surfaced as a flagged, non-blocking gap. **`now.md` is retired** for the same reason: "what's next" is derived from the forge by the Planner (`gh issue list --label "vinaya/tranche:<slug>" --state open`), not written to a file.
|
|
124
114
|
|
|
125
115
|
### 6. Ratify pending Type 1 decisions
|
|
126
116
|
|
|
@@ -190,9 +180,6 @@ RETROSPECTIVE: posted to pinned lessons Issue ✓ | INCOMPLETE (reason)
|
|
|
190
180
|
|
|
191
181
|
ARCHIVED: aeg-root/tranches/completed/<name>.md ✓ | FAILED (reason)
|
|
192
182
|
|
|
193
|
-
STATE:
|
|
194
|
-
- pinned state Issue(s) updated ✓ (current-focus pointer, pending-manual-ops, recently-shipped entry)
|
|
195
|
-
|
|
196
183
|
PENDING RATIFICATIONS: [list with one-line description] | none
|
|
197
184
|
|
|
198
185
|
DANGLING (requires Principal action):
|
|
@@ -87,4 +87,33 @@ Principal → Planner → Brief Author → Developer → Reviewer (code + securi
|
|
|
87
87
|
|
|
88
88
|
## 11. What to do next (the reading order)
|
|
89
89
|
|
|
90
|
-
After this skill, load in order: **`aeg-roles`** (routes you to your role doc) → your **`aeg-root/roles/<role>.md`** → the altitude you're working at — **`aeg-root/milestone-model.md`** (declaring or reading a goal), **`aeg-root/tranche-model.md`** (planning or executing across a batch), and/or **`aeg-root/task-model.md`** (executing one task) — →
|
|
90
|
+
After this skill, load in order: **`aeg-roles`** (routes you to your role doc) → your **`aeg-root/roles/<role>.md`** → the altitude you're working at — **`aeg-root/milestone-model.md`** (declaring or reading a goal), **`aeg-root/tranche-model.md`** (planning or executing across a batch), and/or **`aeg-root/task-model.md`** (executing one task) — → the session-start forge queries below. When anything disagrees, `state-machine.md` wins.
|
|
91
|
+
|
|
92
|
+
## 12. Session-start forge queries — deriving current state
|
|
93
|
+
|
|
94
|
+
Execution state is **derived from the forge, never read from a file** — there is no state file, no status doc, no hand-maintained state Issue. (`coordination.md`, which once carried a session-start protocol plus a pinned per-project state-Issue layer, is retired: its queries cited label names that don't exist in any adopter, and the state-Issue layer duplicated what Milestones and tranche labels already derive — the one live instance drifted stale and was closed.) Substitute your repo's label namespace — the queries below use this repo's `vinaya/` prefix:
|
|
95
|
+
|
|
96
|
+
**"What's active?"**
|
|
97
|
+
```bash
|
|
98
|
+
gh issue list --label "vinaya/tranche:<slug>" --state open
|
|
99
|
+
gh pr list --state open
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**"What's blocked?"**
|
|
103
|
+
```bash
|
|
104
|
+
gh issue list --label "vinaya/blocked" --state open
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**"What needs the Principal?"**
|
|
108
|
+
```bash
|
|
109
|
+
gh issue list --label "vinaya/needs:principal-input" --state open
|
|
110
|
+
gh pr list --label "vinaya/needs:principal-input" --state open
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**"What merged recently?"** — `gh pr list --state merged --limit 20`
|
|
114
|
+
|
|
115
|
+
**"Is a specific task dispatchable?"** — don't hand-derive it: `bun packages/aeg-core/bin/verify-dispatch.ts <tranche> <n>` (or the shipped `dispatch-readiness` check in an adopter repo) answers with the exact blocker.
|
|
116
|
+
|
|
117
|
+
Anything genuinely non-derivable — a pending manual operation, a known production issue — is an **ordinary open Issue, closed when resolved**: never a hand-edited-in-place state document, never a label pretending to be a status field.
|
|
118
|
+
|
|
119
|
+
No brief, no audit finding, no "next steps" recommendation is valid without a forge check. Forge state > file state > memory. Always.
|
|
@@ -43,7 +43,7 @@ Always also skim `roles/principal.md` to know what sits in the Principal's seat
|
|
|
43
43
|
- **Reviewer (security)** — as above, security lens; runs a config-security scan if agent/MCP config changed.
|
|
44
44
|
- **Archivist** — **entry gate:** the PR is merged, else refuse. Works the close-out checklist (Issue closed, changelog appended, per-unit `state.md` updated, provenance block posted, orphan branch/worktree flagged). Writes **no** task status — the merge *is* the status. (`now.md` is retired.)
|
|
45
45
|
- **Verification** — a **phase**, not a role: nobody is dispatched as a Verifier. It runs on an open PR after the code-review and security passes and before merge. **Entry gate:** an open PR whose brief carries a tagged Test Plan; refuse if there is no open PR, no brief, no Test Plan section, or the plan is declared `unit-tests-only` while the diff touches a runtime surface. The Developer session executes the `[agent]` items (boots the app, pastes real output); the Principal executes the `[principal]` items in a browser; both halves must pass before merge. Writes no status. Documented in `roles/developer.md` § Verification, because the Developer is the actor that runs its agent half.
|
|
46
|
-
- **Tranche Archivist** — closes out a finished tranche (Phase 13), on explicit Principal declaration only. **Entry gate:** every task terminal (merged / dropped / moved out), the Principal has declared the tranche done, and the Milestone is still open (not already archived), else refuse. Assembles the retrospective, closes the Milestone,
|
|
46
|
+
- **Tranche Archivist** — closes out a finished tranche (Phase 13), on explicit Principal declaration only. **Entry gate:** every task terminal (merged / dropped / moved out), the Principal has declared the tranche done, and the Milestone is still open (not already archived), else refuse. Assembles the retrospective, closes the Milestone, surfaces pending Type 1 ratifications, posts the tranche provenance block. Forge-read only; ratifies nothing; writes no status. Distinct from the per-task Archivist (`roles/archivist.md`).
|
|
47
47
|
|
|
48
48
|
## 3. Authority boundaries (so roles don't bleed)
|
|
49
49
|
|
|
@@ -249,7 +249,7 @@ Do not leave documentation as an implication of the tier checklist. **List the e
|
|
|
249
249
|
- **Never list a new file for a one-off report, audit finding, coverage summary, or working brief.** If the task's deliverable is a finding, an audit result, or a coverage report, its home is the PR body (task-scoped) or an Issue/PR comment (not task-scoped) — never a new file under `aeg-root/` or a product's `aeg-project/`. A committed scratch file has already broken AEG Studio once (a coverage report committed as `aeg-root/tranches/<name>.audit.md` was silently parsed as a broken tranche by the Studio loader) and produced a stale permanent brief once (`aeg-project/briefs/<name>-brief.md`, contradicting this skill's own "pasted, not committed" rule above). See `tranche-model.md` §9 rule 4.
|
|
250
250
|
- **Tier 0** — usually none. State "No doc updates required (Tier 0)."
|
|
251
251
|
- **Tier 1** — name each: which spec(s) reflect the new behavior, which skill(s) if a convention shifted, `docs-index.md` if files were added/removed/renamed.
|
|
252
|
-
- **Tier 3** — all Tier 1 items, plus: which state changes (the per-project
|
|
252
|
+
- **Tier 3** — all Tier 1 items, plus: which state changes (the tranche file; per-project backlogs; any non-derivable fact recorded as an ordinary open Issue). **Never** list `roadmap.md`, `now.md`, or a pinned state Issue — all retired. Active-work state is derived from the forge, not written to a file.
|
|
253
253
|
|
|
254
254
|
A Tier 1+ brief with an empty doc-update list is malformed.
|
|
255
255
|
|
|
@@ -371,7 +371,7 @@ These two qualify a task and ride into the PR body. Both are reference-only —
|
|
|
371
371
|
```
|
|
372
372
|
**Project:** [project(s) this task touches — e.g. "web" or "engine, api"]
|
|
373
373
|
```
|
|
374
|
-
Multi-valued. Resolves against `.vinaya/projects.md`. **Required in a multi-project repo; omitted entirely in a single-project repo** (no registry → one project → no field). Routes the Developer to the right specs
|
|
374
|
+
Multi-valued. Resolves against `.vinaya/projects.md`. **Required in a multi-project repo; omitted entirely in a single-project repo** (no registry → one project → no field). Routes the Developer to the right specs; a value that doesn't resolve to a registry row makes the brief malformed (refuse, don't guess). It must match the Planner's `Project(s)` for the task, including every shared-package consumer in the blast radius — see `roles/planner.md` and the planner-brief contract.
|
|
375
375
|
|
|
376
376
|
```
|
|
377
377
|
**Ticket:** [external ticket link(s) — e.g. "SAT-412 — https://…"]
|
|
@@ -125,11 +125,10 @@ Rows = artifact types. Columns = roles. "—" means no authority. The Reviewer i
|
|
|
125
125
|
| **Specs** (`apps/*/specs/*.md`) | Approves PR; ratifies a spec-only change | Coherence review on PR; can open spec-only PRs | Writes in PR per brief scope | Validates cross-references; flags stale specs in drift cron |
|
|
126
126
|
| **Skills** (canonical `aeg-root/skills/*/SKILL.md`) | Approves PR | Coherence review | Writes in PR per brief scope | Flags stale skill references in drift cron |
|
|
127
127
|
| **Agent defs** | Approves PR | Coherence review | Writes in PR per brief scope | Flags stale agent references in drift cron |
|
|
128
|
-
| **`state.md`** | Approves PR | Writes in PR | Flags state changes needed in PR description | Updates per-project state at close-out, for every project the task listed |
|
|
129
128
|
| **Per-project backlogs** (`apps/*/specs/*-backlog.md`) | Approves PR | Writes (held/future items — out of the flow) | — | — |
|
|
130
|
-
| **`
|
|
129
|
+
| **`state-machine.md`** | Approves PR; final authority on system-level rule changes | Proposes changes via PR | — | Flags inconsistencies in drift cron |
|
|
131
130
|
| **`thinking.md`** | Reads | Writes freely in any Brief Author session (best-effort, optional) | Reads | Flags if untouched >7 days |
|
|
132
|
-
| **
|
|
131
|
+
| **Lessons log** (the standing lessons Issue) | Approves/rejects/defers items at windows | Appends items; marks resolved after Principal action | Appends via escalation (`severity: product`) | The **Tranche Archivist** appends the retrospective at Phase 13 close-out (`roles/tranche-archivist.md`) — one new comment per tranche, never an edit. (The hand-edited per-project state Issue this row once also covered is retired: everything it held is either forge-derived — Milestones + `vinaya/tranche:*` labels — or belongs in an ordinary open Issue closed when resolved.) |
|
|
133
132
|
| **Source code** | Merges PR | — | Writes in PR per brief scope; opens PR | — |
|
|
134
133
|
| **Forge labels** (the Section 14 vocabulary) | Applies `vinaya/override:docs` (Principal-only) | Applies `vinaya/tier:*` (Planner, at cut) + `vinaya/needs:*-input` / `vinaya/blocked` (by hand or via automation) | Applies `vinaya/needs:*-input` / `vinaya/blocked` (by hand or via automation) | Applies `vinaya/needs:brief-correction`; asserts `vinaya/tier:*` label == PR-body `Tier:` (drift cron) |
|
|
135
134
|
| **Task status** | — | — | — | — *(nobody writes it — derived from the forge)* |
|
|
@@ -167,7 +166,7 @@ Used when verifying state, resolving contradictions, running verify-docs, post-m
|
|
|
167
166
|
1. Ratified specs (`Status: ratified`)
|
|
168
167
|
2. Shipped code (main — what actually runs)
|
|
169
168
|
3. Aspirational specs (`Status: target`)
|
|
170
|
-
4.
|
|
169
|
+
4. The lessons Issue (append-only retrospectives/calibration) — non-derivable observations; active status always derived from the forge, never from any doc
|
|
171
170
|
5. Skills + `thinking.md`
|
|
172
171
|
6. Briefs / Issues / PR descriptions — intent at time of writing
|
|
173
172
|
7. Conversation logs / tool runtime logs — lowest
|
|
@@ -205,6 +204,8 @@ A spec file exists in one of four states:
|
|
|
205
204
|
|
|
206
205
|
Most specs are `draft` — no deliberate ratification pass has been done. Future PRs ratify as appropriate.
|
|
207
206
|
|
|
207
|
+
**Spec naming (locked):** spec filenames are `{product}-spec.md` or `{component}-spec.md` — no `-v0`/`-v1`/`-draft`/date suffixes. Version state lives in the file's `Status:` block above, never the filename. Renaming to add a version suffix requires a lock challenge.
|
|
208
|
+
|
|
208
209
|
> Note: the Reviewer's spec-conformance check (§3) reads the project spec **as written** — at whatever ratification state it currently holds. A `draft` spec is still the project's stated intent and is checked against; a contradiction with a `ratified` spec is the most serious. The Reviewer never edits the spec; if it's wrong, that's an escalation.
|
|
209
210
|
|
|
210
211
|
---
|
|
@@ -304,7 +305,7 @@ The lowest-commitment way to run AEG: read-only over a team's existing process.
|
|
|
304
305
|
- **Typecheck, tests** — standard CI gates; always blocking.
|
|
305
306
|
- **Issue template / no forbidden fields** — a required Issue template + a CI check reject planning metadata (priority/estimates/points) on task Issues, keeping them execution-only.
|
|
306
307
|
- **Brief validation** — the Archivist's `brief-validation` job runs `packages/aeg-core/bin/verify-brief.ts` against the PR body and checks presence of every required brief section (Tier, `For:` model attribution, `Project:` — both read from the PR body's header block, before the first `##` heading, the same region the post-merge Archivist's provenance assembly reads — tagged Test Plan, surface map, doc-update list, worktree Step 0, stop conditions, autonomy clause, `Closes #N`); flags malformed briefs (`vinaya/needs:brief-correction`) and fails CI. **The trigger is the body, not the branch (`fix/brief-gate-nontask`):** the gate runs when the branch is `task/<tranche>/<n>` **or** the body is brief-shaped (`isBriefShaped` — ≥2 of surface map / doc-update list / stop conditions / autonomy clause, matched on `stripCode`'d text so a brief *quoted inside a fence* stays exempt). Bodies that are neither still bypass — that exemption is for an ordinary non-AEG PR (a one-line dependency bump) which carries no brief and must not be forced to grow one. The old branch-only bypass was the wrong proxy for it: a standalone `fix/*` brief **is** a brief, and it skipped every section check — confirmed live on `fix/studio-tranche-href`, which shipped with no §7 documentation-update list because `checkDocUpdateList`, the checker that exists for exactly that, never ran. `Closes #N` remains **task-branch-only** (`BriefSectionsOptions.requireClosesN`): a standalone fix brief has no task Issue to close, and a `plan/*` PR is *forbidden* to carry one by the plan-PR guard below — requiring it there would make the two gates jointly unsatisfiable. The same validator also runs at **authoring time** as the `brief-shape` check — `PR_BODY="$(cat brief.md)" vinaya check brief-shape` (on this repo's toolchain, also `bun packages/aeg-core/bin/verify-brief.ts --body-file <brief.md>`) — before a PR or even a branch exists, so a Brief Author gates a brief before dispatch rather than after the Developer has done the work (`skills/brief-authoring/SKILL.md` protocol step 4); with no `BRANCH`, the branch is read from the brief's own Step 0 `git worktree add … -b` line. **Includes the plan-PR Closes guard**: a `plan/*` branch whose PR body carries `Closes #N` fails CI before the non-task bypass even runs — a plan PR creates Issues, it does not resolve one (`roles/planner.md`); this closed a confirmed pattern of plan PRs prematurely closing task Issues on merge. **Real**, now the `Brief Validation` step (9/9) of the AEG gate suite job in `.github/workflows/forge-lifecycle.yml`. Presence-only — it cannot judge whether a Test Plan item is truly scriptable or whether a declared `unit-tests-only` is justified by the surface map; those remain Reviewer + Verification judgment. Same enforcement substrate as above.
|
|
307
|
-
- **Per-task Archivist close-out** — `.github/workflows/archivist.yml::post-merge` (`packages/aeg-core/bin/archive-task.ts`) runs on every push to `main`, resolves the merge commit's PR via `gh api repos/{owner}/{repo}/commits/{sha}/pulls`, and — for task-branch PRs only — assembles and posts the Archivist provenance block (`roles/archivist.md` item 8) and explicitly closes the task's Issue, confirming the closed state before exiting. Idempotent **per PR**, not per Issue (an Issue can legitimately accrue multiple merged PRs over its life; idempotency never spans PRs): skips silently if the PR already carries a provenance comment. Skips silently on non-task branches (`plan/*`, `fix/*`, …). Fails loud (non-zero exit) on any `gh`/permission error — never a silent no-op. Real, installed with `contents: read`, `issues: write`, `pull-requests: write` permissions. Does not automate the Tranche Archivist or items 2–7 of per-task close-out (docs coherence,
|
|
308
|
+
- **Per-task Archivist close-out** — `.github/workflows/archivist.yml::post-merge` (`packages/aeg-core/bin/archive-task.ts`) runs on every push to `main`, resolves the merge commit's PR via `gh api repos/{owner}/{repo}/commits/{sha}/pulls`, and — for task-branch PRs only — assembles and posts the Archivist provenance block (`roles/archivist.md` item 8) and explicitly closes the task's Issue, confirming the closed state before exiting. Idempotent **per PR**, not per Issue (an Issue can legitimately accrue multiple merged PRs over its life; idempotency never spans PRs): skips silently if the PR already carries a provenance comment. Skips silently on non-task branches (`plan/*`, `fix/*`, …). Fails loud (non-zero exit) on any `gh`/permission error — never a silent no-op. Real, installed with `contents: read`, `issues: write`, `pull-requests: write` permissions. Does not automate the Tranche Archivist or items 2–7 of per-task close-out (docs coherence, `docs-index.md`, token ledger) — those remain dispatched-Archivist judgment work.
|
|
308
309
|
- **Manifest integrity** — `verify-docs --full` and the coherence oracle validate the doc-owners manifest: pointer existence (M1), glob syntax (M2 advisory), and duplicate globs (M3). There is no decision-number sequencing: the log it validated is gone.
|
|
309
310
|
- **Closes #N gate** — task-branch PRs must declare `Closes #<its-issue>` in the PR body; absence fails CI. Non-task branches bypass this forward direction automatically. Real, installed at `.github/workflows/forge-lifecycle.yml::closes-n-gate`. Same enforcement substrate as above. **Forge-native-tranche fix (`fix/closes-n-forge-native`):** the gate's scoped `loadTrancheFiles(null, onlySlug)` call discovers which tranches exist by listing `aeg-root/tranches/*.md` filenames — a tranche with zero topology file never entered that enumeration, so the forge derivation was never invoked for it despite the tranche already being fully Milestone-capable, and the gate failed every such PR with a misleading "no topology file found." Fixed by falling back to a direct forge derivation (the Milestone-existence check plus the file-and-forge composition, today `indexTrancheMilestonesAsync` + `mergeFileTopology`) when the requested `onlySlug` isn't found via files, gated on an actual open Milestone existing so an unrecognized branch slug still fails honestly — the scoped-path counterpart to `verify-dispatch.ts`'s `otherActiveTrancheSlugs` fix. **Reverse direction (`fix/closes-n-reverse`):** a `Closes #N` that resolves to a real AEG task Issue (title matches the `[<tranche-slug>] <task-id>...` convention and carries a `vinaya/tranche:<slug>` label) now requires the branch to actually be named `task/<tranche-slug>/<task-id>`, regardless of what the branch itself is called — closing the blind spot that let a mis-named branch implement a real task Issue with zero forge-visible status. One batched forge query (`fetchTaskIssueRefs`) resolves each referenced Issue's task identity before `checkClosesN` runs. **Code-span hardening (`fix/closes-gate-hardening`):** both the pre-merge gate (`checkClosesN` in `brief-validation.ts`) and the coherence-side parse (`extractClosesReferences` in `coherence-checks.ts`) now `stripCode` the body before matching the closing keyword, as GitHub's own auto-close parser ignores `Closes #N` inside a code span or fenced block. Inline spans of **any backtick-run length** are covered (`` `x` ``, `` ``x`` ``, …) via CommonMark's `(`+)…\1` matched-run rule — the double-backtick form was a false-green in the first cut (peeled as two empty spans). Fenced blocks are matched by a line scanner that pairs a fence with its own closer by **character and run length**: `~~~` tilde fences, info strings (```` ```js ````), and runs longer than three (```` `````` ````) all strip correctly, and an unclosed fence runs to end of body as GitHub renders it — the earlier `` /```[\s\S]*?```/g `` regex missed all three. The keyword set matches GitHub's own: `close`/`closes`/`closed`, `fix`/`fixes`/`fixed`, `resolve`/`resolves`/`resolved`. Before this, a body whose only `Closes #N` was backticked passed the gate **green** yet merged **without** closing its Issue, then read red on every open PR via A3 `auto-close-misfire`; "verify-docs green" now implies "GitHub will auto-close" for fenced + inline-code forms. 4-space **indented** code blocks are stripped too, conservatively: a ≥4-column-indented run counts as code only when it follows a blank line *and* is not inside a list — since within a list item that indentation is the item's own content indent, which GitHub *does* auto-close (blanking it would be a false-red, the brief's over-strip stop condition). The strip runs on the **whole body, before any region is sliced out of it** — never on a slice. Every rule in it is block-structural (a fence pairs with its own closer; an indented run is code only after a blank line and outside list context), so a fragment strips differently from the same text in place: stripping the sliced `AEG:CLOSES` region blanked an anchor indented inside a list item — list content GitHub *does* auto-close — and the Archivist's `extractIssue` returned no Issue, stranding it on merge exactly as before. Markers are HTML comments and survive the strip, so selecting the region from stripped text loses nothing and subsumes the decoy protection: a decoy anchor inside code never survives to be sliced. The same grammar governs `maskCode`, the index-preserving variant `anchoredRegion` runs to find the `AEG:*` markers themselves — it is **upstream** of every `stripCode` call, so while it stayed on the naive fence/inline regexes a decoy `AEG:CLOSES` anchor inside a tilde fence, a ≥4-backtick fence, a double-backtick span, or an indented block won the region outright and the gate resolved a **wrong** Issue number (worse than the strandings above: the post-merge Archivist's `extractIssue` would explicitly close an unrelated Issue). Both now delegate to one pair of scanners, differing only in what they emit per code line — nothing for `stripCode`, same-length filler for `maskCode` — so a divergence is a compile-level impossibility rather than a convention. This hardens all five anchored fields (`CLOSES`, `PROJECT`, `TIER`, `PREMISE`, `TEST-PLAN`) at once, not just the closing reference. `stripCode` normalises `\r\n`/`\r` to `\n` before any of these scanners run: the fence scanners anchor per line, and JS's `.`/`$` never match `\r`, so a CRLF body opened no fence at all and let a fenced `Closes #N` walk free — the same false-green along a new axis, and it hit exactly the web-UI-authored bodies this CI backstop exists for (HTML normalises textarea newlines to CRLF on submit). The closing-keyword separator is **bounded** (`\s{0,8}:?\s{0,8}`, identical in both parsers): two adjacent unbounded `\s*` groups backtrack quadratically on `closes` + long whitespace + no `#` — ~2.0 s at GitHub's 65,536-char body cap, run twice on the fail path — where the bound is 0.1 ms. **Known residual:** a genuine indented code block *nested inside a list* is therefore left unstripped — the deliberately safe direction of that trade. A `Closes #N` surviving only inside code fails with an actionable message pointing at a bare reference in the `AEG:CLOSES` anchor. `stripCode` is the one shared stripper, exported from `anchored-region.ts` (no duplicated regex).
|
|
310
311
|
- *(The practitioner-facing map of every enforcement mechanism — prevention, detection, audit — lives in `aeg-root/enforcement.md`; this section remains the normative gate registry.)*
|
|
@@ -324,7 +325,7 @@ The lowest-commitment way to run AEG: read-only over a team's existing process.
|
|
|
324
325
|
- **Dispatch gates** (depends-on merged / no conflicting PR open) — read from the forge and complied with; mechanical enforcement arrives when an automation tool runs dispatch (`tranche-model.md` §8).
|
|
325
326
|
- **Label discipline** (Section 14) — `vinaya/tier:*` present on every task Issue and kept in sync with the PR-body `Tier:`; `vinaya/needs:*-input` / `vinaya/blocked` present-when-true *and removed when false*; no `status:*` labels; no `project:*` labels; no label outside the closed set. Trusted discipline; the Archivist drift cron asserts the tier label/field match and flags stale `vinaya/needs:*` labels.
|
|
326
327
|
- **Contract conformance** (a role doc matches its `contracts/*.md` seam) — trusted discipline; the Archivist drift cron flags a role doc that contradicts its contract. The contract is the source of truth; a divergent role doc is the bug. (The Planner→Brief contract's *rationale field-completeness* — every task Issue body carries all eight fields — moved to Enforced via R1 above; only the "role doc text matches contract prose" half remains trusted here.)
|
|
327
|
-
- **Provenance assembly at close-out — items 1/8 moved to Enforced**, see "Per-task Archivist close-out" above; items 2–7 of close-out (docs coherence,
|
|
328
|
+
- **Provenance assembly at close-out — items 1/8 moved to Enforced**, see "Per-task Archivist close-out" above; items 2–7 of close-out (docs coherence, `docs-index.md`, token ledger) remain trusted, dispatched-Archivist judgment work — it records, it never gates.
|
|
328
329
|
- **Decision logging during chat** — Brief Author announces and logs during the conversation; CI cannot verify.
|
|
329
330
|
- **No execution metadata in the tranche file; no dynamic conflict scanner** — the two anti-regression rules (`tranche-model.md` §9); trusted discipline, flagged by the Archivist drift cron and the Planner's gates.
|
|
330
331
|
- **`thinking.md` updates; ratification-window attendance; lock acknowledgment (advisory in V0); spec ratification passes** — all trusted.
|
|
@@ -400,6 +401,7 @@ No label outside this table may be applied to a task Issue or its PR. (The Archi
|
|
|
400
401
|
| `vinaya/tier:0` / `vinaya/tier:1` / `vinaya/tier:3` | Issue (+ mirrors the PR-body `Tier:`) | Impact tier — drives required docs (§9) and whether it merges at a ratification window. The forge has no concept of "impact." | **Planner** sets it at Issue cut (plan-time estimate). The **PR-body `Tier:`** is the binding value at merge; the Developer corrects the field if execution reveals a different tier, and re-syncs the label. | **Always-mandatory** — exactly one per task |
|
|
401
402
|
| `vinaya/type:build` / `vinaya/type:chore` / `vinaya/type:docs` / `vinaya/type:feat` / `vinaya/type:fix` / `vinaya/type:perf` / `vinaya/type:refactor` / `vinaya/type:revert` / `vinaya/type:style` / `vinaya/type:test` | Issue | What kind of change the task is — the same ten commit-type names `roles/developer.md`'s commit conventions use, applied to the Issue instead of the commit. The forge has no concept of a task's shape. | **Planner** sets it at Issue cut. | **Always-mandatory, checked at Issue creation only** — `open-issue.ts` requires exactly one on every `create`; it never re-checks the label on a later `edit`, so this is forward-only from this axis's own merge without retroactively refusing an edit to an Issue that predates it (no backfill) |
|
|
402
403
|
| `vinaya/blocked` | Issue | A block that has **no forge fact** behind it ("waiting on an answer" isn't visible from branch/PR state). | Developer/Brief Author when a task is blocked on an escalation; **removed** the moment it unblocks. | Conditional-mandatory |
|
|
404
|
+
| `vinaya/backlog` | Issue | Marks deliberate unplanned-ness — the Issue belongs to no tranche and is excluded from dispatch, a fact no forge field shows. | Planner/Principal when an Issue is consciously left unplanned; **removed** when a Planner promotes it into a tranche. | Conditional-mandatory |
|
|
403
405
|
| `vinaya/incoherent` | Issue | A `COMPLETED` close with **no merged-PR link** — the forge shows "closed" but cannot show *whether the one law was honored* (done iff a merged `Closes #N`). Marks the anomaly for a human to resolve; AEG never auto-reopens. | Detected by `verify-coherence` (A1) / surfaced in Studio; applied when the incoherence is found, **removed** when a human clears it (link the merge, or re-close `NOT_PLANNED`). | Conditional-mandatory |
|
|
404
406
|
| `vinaya/needs:execution-input` | Issue | Routes an open escalation to the **Brief Author** (§7). | Developer at escalation; removed when answered. | Conditional-mandatory |
|
|
405
407
|
| `vinaya/needs:strategy-input` | Issue | Routes to the **Brief Author** — a design-path question, not an execution one. | Developer at escalation; removed when answered. | Conditional-mandatory |
|
package/aeg-root/task-model.md
CHANGED
|
@@ -36,7 +36,7 @@ This is the operational sequence — distinct from §2's derived-status vocabula
|
|
|
36
36
|
3. **Review** — code-reviewer pass (`roles/reviewer.md`) and security pass (`roles/security.md`), each emitting a structured verdict. A REQUEST CHANGES or FAIL loops back to **Code** — bounded by a revision ceiling so the loop always ends, never open-ended.
|
|
37
37
|
4. **Verify** — the tagged Test Plan runs for real: the `[agent]` items the Developer executes against the running app, the `[principal]` items a human confirms. This is the gap between "CI is green" and "the feature actually works" — static review alone cannot exercise an auth-gated, key-dependent, or browser-rendered path.
|
|
38
38
|
5. **Merge** — the PR merges once Review and Verify are both satisfied. This is the boundary, not a stage with its own actor: merging is the mechanical consequence of the two gates above clearing, not a separate decision.
|
|
39
|
-
6. **Archive** — the Archivist closes out: the Issue is explicitly closed (never left to GitHub's advisory auto-close), docs coherence is confirmed, the
|
|
39
|
+
6. **Archive** — the Archivist closes out: the Issue is explicitly closed (never left to GitHub's advisory auto-close), docs coherence is confirmed, the provenance block is assembled and posted to the merged PR. This is the task's terminal stage — nothing follows it at this altitude. (The hand-edited per-project state Issue is retired — non-derivable facts live as ordinary open Issues, closed when resolved; active state is derived from the forge.)
|
|
40
40
|
|
|
41
41
|
Orphaned task (a branch exists, no PR, gone stale) is the one named exception to this straight line: a close-out/sweep step flags it and a human deletes the branch, returning the task to `todo` — a real, owned recovery path, not a silent drop.
|
|
42
42
|
|
|
@@ -9,6 +9,10 @@ sidebar_title: "Template: Issue rationale"
|
|
|
9
9
|
|
|
10
10
|
[tranche-slug] [n] — [task title, repeated from the Issue title]
|
|
11
11
|
|
|
12
|
+
**Tier:** [0 | 1 | 3]
|
|
13
|
+
**Project:** [project(s), comma-separated, matching the blast radius stated in the "Project(s) + blast radius" field below]
|
|
14
|
+
**Type:** [build | chore | docs | feat | fix | perf | refactor | revert | style | test — the commit-type word this task belongs to; free-text metadata, not a forge label]
|
|
15
|
+
|
|
12
16
|
## Planner's rationale
|
|
13
17
|
|
|
14
18
|
**Boundary** — [BOUNDARY — what this task is and, crucially, what it is NOT: what was deliberately split out, where the edges sit. Make the in/out sets concrete enough that the Brief Author can bound a file surface from them.]
|
|
@@ -30,7 +34,3 @@ sidebar_title: "Template: Issue rationale"
|
|
|
30
34
|
## Origin
|
|
31
35
|
|
|
32
36
|
[ORIGIN — where this task came from: Principal-directed, backlog item, incident follow-up — with dates and the Issue/PR references that motivated it.]
|
|
33
|
-
|
|
34
|
-
**Tier:** [0 | 1 | 3]
|
|
35
|
-
**Project:** [project(s), comma-separated, matching the blast radius above]
|
|
36
|
-
**Type:** [build | chore | docs | feat | fix | perf | refactor | revert | style | test — one, matching a `vinaya/type:*` label]
|
|
@@ -46,6 +46,10 @@ Closes #[N]
|
|
|
46
46
|
|
|
47
47
|
Run `vinaya pr report --write <this-body-file>` and commit its output — this block is generated, never hand-typed. `check-evidence-fresh` refuses a body whose block doesn't match the head it's attached to.
|
|
48
48
|
|
|
49
|
+
The block opens with `Head:` and a `Summary:` line — a file and line count derived from the same `--numstat` printed two lines below it, so the body never needs a hand-written "four files changed" sentence that a later commit silently falsifies. Its value is emitted inside backticks, which is what makes it legal under the bare-digit rule below — no exemption, just the same inline code span any other digit needs. Do not type or edit the line: `check-evidence-fresh` byte-compares it, backticks included, against a fresh recompute, and a hand-written count fails there.
|
|
50
|
+
|
|
51
|
+
**Keep the anchor pair out of the `<details>` block.** `body-bare-digits` blanks every digit inside a collapsed block, so an evidence block hidden in one is exempt from the digit scan and unverifiable — `check-evidence-fresh` refuses rather than passing silently. Both checks resolve this region from one shared, normalised context, so a zero-width character or an HTML entity in a marker no longer makes one of them see a block the other cannot.
|
|
52
|
+
|
|
49
53
|
<!-- AEG:EVIDENCE:START -->
|
|
50
54
|
[run `vinaya pr report --write` to populate — do not type this block by hand]
|
|
51
55
|
<!-- AEG:EVIDENCE:END -->
|
|
@@ -312,7 +312,7 @@ Self-metering capture is real, not estimated: the adapter sums the session's own
|
|
|
312
312
|
|
|
313
313
|
### The collection adapter AEG ships (one layer-2 instance, not the requirement)
|
|
314
314
|
|
|
315
|
-
AEG ships exactly one collection adapter, for the Claude Code host
|
|
315
|
+
AEG ships exactly one collection adapter, for the Claude Code host, exposed as `vinaya tokens`. It reads that host's session transcript — a JSONL file carrying a `usage` object per assistant message — sums it, and emits a layer-3 `Tokens: …` line. Every doctrine citation of it is an **example of one way to satisfy layer 2**, never the requirement; a role on another host satisfies the same obligation by other means and is equally compliant.
|
|
316
316
|
|
|
317
317
|
**The seam is the summary shape, not the file tree.** An adapter's whole job is to produce a `TranscriptSummary` — four integers (fresh input, cache creation, cache read, output) plus a model id. Everything downstream of that shape is portable and already shipped: `formatTokensLine` renders the grammar, `parse-token-report.ts` reads it back. Two things sit adapter-side because both know host-specific facts: `summarizeTranscript` (`@attalabs/aeg-core`'s Claude Code transcript module), which knows Claude Code's transcript JSONL and its `usage` field names, and the bin itself, which knows how that host points a session at its own transcript. The `bin/` vs `src/` split does **not** mark this seam and never did.
|
|
318
318
|
|