@attalabs/vinaya 0.24.1 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -3
- package/aeg-root/contracts/architect-planner.md +5 -5
- package/aeg-root/contracts/developer-reviewer.md +10 -7
- package/aeg-root/contracts/planner-developer.md +142 -0
- package/aeg-root/contracts/reviewer-archivist.md +2 -2
- package/aeg-root/contracts/tranche-archivist-planner.md +12 -11
- package/aeg-root/enforcement.md +25 -11
- package/aeg-root/process.md +53 -75
- package/aeg-root/roles/archivist.md +3 -3
- package/aeg-root/roles/developer.md +30 -24
- package/aeg-root/roles/planner.md +100 -21
- package/aeg-root/roles/principal.md +14 -11
- package/aeg-root/roles/reviewer.md +33 -17
- package/aeg-root/roles/security.md +28 -13
- package/aeg-root/roles/tranche-archivist.md +2 -2
- package/aeg-root/skills/aeg/SKILL.md +5 -5
- package/aeg-root/skills/aeg-roles/SKILL.md +7 -7
- package/aeg-root/state-machine.md +36 -35
- package/aeg-root/task-model.md +3 -3
- package/aeg-root/templates/brief-template.md +22 -6
- package/aeg-root/templates/issue-rationale-template.md +35 -2
- package/aeg-root/templates/pr-report-template.md +5 -13
- package/aeg-root/tranche-model.md +21 -21
- package/dist/checks/bin/check-body-bare-digits.js +684 -142
- package/dist/checks/bin/check-branch-topology.js +741 -88
- package/dist/checks/bin/check-brief-shape.js +708 -83
- package/dist/checks/bin/check-changeset-coverage.js +1445 -149
- package/dist/checks/bin/check-closes-n.js +741 -88
- package/dist/checks/bin/check-coherence.js +808 -149
- package/dist/checks/bin/check-dead-branch-push.js +617 -81
- package/dist/checks/bin/check-dispatch-readiness.js +811 -152
- package/dist/checks/bin/check-doc-coverage-push.js +1445 -149
- package/dist/checks/bin/check-doc-coverage.js +1447 -151
- package/dist/checks/bin/check-doctrine-no-procedures.js +684 -142
- package/dist/checks/bin/check-doctrine-portability.js +1445 -149
- package/dist/checks/bin/check-evidence-fresh.js +684 -142
- package/dist/checks/bin/check-exec-bits.js +1445 -149
- package/dist/checks/bin/check-first-push-dispatch.js +808 -149
- package/dist/checks/bin/check-issue-assignment.js +741 -88
- package/dist/checks/bin/check-main-branch-refusal.js +618 -82
- package/dist/checks/bin/check-no-disk-state.js +617 -81
- package/dist/checks/bin/check-pr-premise-reassert.js +5401 -0
- package/dist/checks/bin/check-pr-report-density.js +617 -81
- package/dist/checks/bin/check-quoted-command.js +1443 -147
- package/dist/checks/bin/check-reader-resolvable-prose.js +1481 -153
- package/dist/checks/bin/check-registry-gates.js +659 -85
- package/dist/checks/bin/check-retired-vocabulary.js +1443 -147
- package/dist/checks/bin/check-review-gate.js +758 -145
- package/dist/checks/bin/check-single-plan-pr.js +617 -81
- package/dist/checks/bin/check-surface-scope.js +5722 -0
- package/dist/checks/bin/check-test-plan.js +617 -81
- package/dist/checks/bin/check-token-collection-wired.js +617 -81
- package/dist/checks/bin/check-token-report.js +629 -88
- package/dist/checks/bin/check-workspace-escape.js +1443 -147
- package/dist/index.js +8548 -4335
- package/package.json +1 -1
- package/studio-standalone/_node_modules/@attalabs/aeg-core/src/brief-render.ts +2 -2
- package/studio-standalone/_node_modules/@attalabs/aeg-core/src/main-branch-refusal.ts +26 -1
- 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/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.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.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.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.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.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.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.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.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.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.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/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]__0o771t1._.js +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/server/chunks/ssr/{[root-of-the-server]__1pndh3_._.js → [root-of-the-server]__0p8q38b._.js} +1 -1
- 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]__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/_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/_1n0cnq-._.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/chunks/ssr/packages_ui_topbar_index_tsx_1h1gs1y._.js +1 -1
- 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/{3m1kgax7j2vgs.js → 0bn8c8v5q429o.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0doqwpd81sjzn.js → 0keji7wvbe1d1.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/1maoxbrl3pv5d.css +1 -0
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{1uogpj5w2n5ju.js → 3-6a3tinbdb-7.js} +1 -1
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/{0zebsmmk1bvnb.js → 3_9xytdmiv1xi.js} +4 -4
- package/studio-standalone/apps/vinaya-studio/web/package.json +2 -2
- package/aeg-root/contracts/brief-developer.md +0 -141
- package/aeg-root/contracts/planner-brief.md +0 -130
- package/aeg-root/roles/brief-author.md +0 -114
- package/aeg-root/skills/brief-authoring/SKILL.md +0 -509
- package/studio-standalone/apps/vinaya-studio/web/.next/static/chunks/3qc67qhcvbg0o.css +0 -1
- /package/studio-standalone/_node_modules/@attalabs/vinaya/studio-standalone/_node_modules/@attalabs/vinaya/studio-standalone/_node_modules/@attalabs/vinaya/studio-standalone/_node_modules/@attalabs/{aeg-core → vinaya/studio-standalone/_node_modules/@attalabs/aeg-core}/bin/verify-coherence.ts +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{QY2GhiI47-765D9DHGy1I → DMofV2-9FrHE7100GfrpI}/_buildManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{QY2GhiI47-765D9DHGy1I → DMofV2-9FrHE7100GfrpI}/_clientMiddlewareManifest.js +0 -0
- /package/studio-standalone/apps/vinaya-studio/web/.next/static/{QY2GhiI47-765D9DHGy1I → DMofV2-9FrHE7100GfrpI}/_ssgManifest.js +0 -0
|
@@ -15,8 +15,8 @@ performs:
|
|
|
15
15
|
- check-dependency-risk
|
|
16
16
|
- produce-the-verdict
|
|
17
17
|
refuses_when: >
|
|
18
|
-
There's no open PR to security-review; the
|
|
19
|
-
the reviewer authored the code under review.
|
|
18
|
+
There's no open PR to security-review; the task Issue carries no frozen
|
|
19
|
+
`aeg:brief:v1` comment; or the reviewer authored the code under review.
|
|
20
20
|
summary: Ever shipped a change nobody checked for leaked secrets?
|
|
21
21
|
---
|
|
22
22
|
# Security Reviewer — Role Reference
|
|
@@ -27,7 +27,7 @@ You ask one question of an open pull request that a correctness review does not:
|
|
|
27
27
|
|
|
28
28
|
**You own** — six checks, and a verdict that follows from them. Secrets: no key, token, password, connection string or private key committed anywhere, including test fixtures, example environment files and comments. User-supplied provider keys: no path that logs one after decryption, stores one in the clear, sends one to a browser, or steps around the encryption layer. Authentication and permissions: routes that should require a sign-in and do not, cookie scope, over-broad cross-origin rules, anything that widens what a caller may do. Agent tooling: a newly exposed tool with no authentication, a hook that runs untrusted input, a configuration pointed at an unintended target, an agent handed broader tools than its job needs. Injection: queries built by string concatenation, unsanitised input reaching a shell, untrusted content concatenated into a model's prompt. Dependencies: whether a new one is necessary, reputable and pinned. Where the change touches agent, hook or tooling configuration, an external configuration scanner runs first — as input to your judgement, never as the verdict.
|
|
29
29
|
|
|
30
|
-
**You refuse** — when there is no open pull request, when
|
|
30
|
+
**You refuse** — when there is no open pull request, when the task Issue carries no frozen brief comment, so you cannot tell an intended change from a smuggled one, and when you wrote the code yourself.
|
|
31
31
|
|
|
32
32
|
**You never** fix what you find, merge, write status, weaken a finding to be agreeable, or quote a discovered secret in full — you name where it lives and enough characters to identify it, so the report does not become the second leak. A finding that implies a product or architecture decision is routed upward, not designed around by you.
|
|
33
33
|
|
|
@@ -44,21 +44,25 @@ Security review is a specialization of the Reviewer role (`roles/reviewer.md`).
|
|
|
44
44
|
|
|
45
45
|
> The check *categories* below (secret leakage, BYOK/crypto, auth/permissions, agent/MCP exposure, injection, dependency risk) are universal. The specific technologies named under them are **this repo's instance** (its crypto package, auth provider, cookie scope, MCP surfaces) — a different team keeps the categories and substitutes its own stack.
|
|
46
46
|
|
|
47
|
+
<!-- AEG:CLAIM: apps/cli/src/lib/dispatch.ts contains:VINAYA_ROLE: role, -->
|
|
48
|
+
<!-- AEG:CLAIM: packages/aeg-core/src/log/envelope.ts contains:isRole(input.env.role) ? input.env.role : 'unattributed' -->
|
|
49
|
+
A pass started via `vinaya dispatch security --agent <vendor>` carries its role and task in every `vinaya` call it makes; one started by hand in a terminal reads `unattributed` in the Vinaya Log, which is the truth about it.
|
|
50
|
+
|
|
47
51
|
---
|
|
48
52
|
|
|
49
53
|
## When you are the Security Reviewer
|
|
50
54
|
|
|
51
55
|
- A PR is open against `main` and the code-reviewer pass is done (or running in parallel).
|
|
52
|
-
- The
|
|
56
|
+
- The task Issue carries the brief, frozen on its `aeg:brief:v1` comment.
|
|
53
57
|
- Your single question: **could this change leak a secret, widen an attack surface, or misconfigure auth/permissions/agent tooling?**
|
|
54
58
|
|
|
55
59
|
## Entry gate (self-locating) — refuse if it isn't your turn
|
|
56
60
|
|
|
57
61
|
- **No open PR** → *"Nothing to security-review — no open PR."*
|
|
58
|
-
- **No brief
|
|
62
|
+
- **No frozen brief comment on the task Issue** → *"This task's Issue has no `aeg:brief:v1` comment; I can't judge whether a change is in scope or a smuggled surface."*
|
|
59
63
|
- **You authored the code** → *"I can't review my own work."*
|
|
60
64
|
|
|
61
|
-
Read the brief from the
|
|
65
|
+
Read the brief from the task Issue's frozen `aeg:brief:v1` comment first — it tells you what the change is *supposed* to touch, so you can spot a security-relevant change the brief never mentioned.
|
|
62
66
|
|
|
63
67
|
## What you check
|
|
64
68
|
|
|
@@ -87,31 +91,42 @@ When the PR touches agent/skill/hook definitions, MCP configs, or anything under
|
|
|
87
91
|
|
|
88
92
|
## Output format
|
|
89
93
|
|
|
90
|
-
**Run `vinaya review post --role security` with this data; do not hand-type a verdict comment.** The `VERDICT:` line is bare — no bold, no heading, no blockquote — it is machine-read by the pre-merge review gate. So is the `Judged head:` line immediately below it: the gate binds your verdict to the exact commit you reviewed, and a verdict that does not cover the PR's current head does not count as clean, however clean its `VERDICT:` value is (`review-gate.ts`). A verdict also holds for a later head whose patch identity equals the judged head's: the gate compares `git diff <base>...<sha> | git patch-id --stable` on both sides, so a merge from the main branch or a rebase that leaves the PR's own patch untouched keeps your verdict alive rather than costing a round to re-cast it over changes you already read. That comparison ignores whitespace, so a whitespace-only push also keeps your verdict; any change to non-whitespace content does not, and comes back to you. Free-typing this shape into `gh pr comment` is no longer the sanctioned path — a decorated heading or a bolded/blockquoted line the gate's line-anchored parser cannot see reaches the forge looking correct to a human reader and is invisible to `verify-review-gate.ts`, with no pointer back to what was wrong until CI goes red. `vinaya review post` resolves the PR's real head itself (`gh pr view --json headRefOid` — never a self-reported sha), renders every structural line from your validated inputs, posts the comment, and refuses to exit 0 unless its own post re-parses clean through the exact same `extractSecurityReviewVerdict` function the gate calls:
|
|
94
|
+
**Run `vinaya review post --role security` with this data; do not hand-type a verdict comment.** The `VERDICT:` line is bare — no bold, no heading, no blockquote — it is machine-read by the pre-merge review gate. So is the `Judged head:` line immediately below it: the gate binds your verdict to the exact commit you reviewed, and a verdict that does not cover the PR's current head does not count as clean, however clean its `VERDICT:` value is (`review-gate.ts`). A third head line, `Objectives version:`, binds your verdict the same way to the objectives list you judged it against — a hash the command computes from the Issue's (or the PR body's) `## Objectives` list; if the Issue's objectives change after you cast a verdict, the gate treats it exactly like a stale head. A verdict also holds for a later head whose patch identity equals the judged head's: the gate compares `git diff <base>...<sha> | git patch-id --stable` on both sides, so a merge from the main branch or a rebase that leaves the PR's own patch untouched keeps your verdict alive rather than costing a round to re-cast it over changes you already read. That comparison ignores whitespace, so a whitespace-only push also keeps your verdict; any change to non-whitespace content does not, and comes back to you. Free-typing this shape into `gh pr comment` is no longer the sanctioned path — a decorated heading or a bolded/blockquoted line the gate's line-anchored parser cannot see reaches the forge looking correct to a human reader and is invisible to `verify-review-gate.ts`, with no pointer back to what was wrong until CI goes red. `vinaya review post` resolves the PR's real head itself (`gh pr view --json headRefOid` — never a self-reported sha), renders every structural line from your validated inputs, posts the comment, and refuses to exit 0 unless its own post re-parses clean through the exact same `extractSecurityReviewVerdict` function the gate calls:
|
|
91
95
|
|
|
92
96
|
```
|
|
93
97
|
vinaya review post --role security --pr <n> --verdict PASS|FAIL \
|
|
94
|
-
--findings-file <path> --config-scan <text> \
|
|
98
|
+
--findings-file <path> --objectives-file <path> --config-scan <text> \
|
|
95
99
|
--secrets <text> --secrets-evidence-file <path> \
|
|
96
100
|
--task-id <task-id> --model <model> --tokens-in <n|-> --tokens-out <n|-> --cost <text|->
|
|
97
101
|
```
|
|
98
102
|
|
|
99
|
-
The findings file is one finding per line, `SEVERITY|file:line|description` (`|`-delimited: `file:line` already contains a colon), severity one of `CRITICAL|HIGH|MEDIUM|LOW`. Omit `--findings-file` for zero findings.
|
|
103
|
+
The findings file is one finding per line, `SEVERITY|file:line|description` (`|`-delimited: `file:line` already contains a colon), severity one of `CRITICAL|HIGH|MEDIUM|LOW`. Omit `--findings-file` for zero findings.
|
|
104
|
+
|
|
105
|
+
The objectives file is one line per objective, `O<n>|MET|<evidence>` or `O<n>|NOT MET|<evidence>` — the same `|`-delimited shape, evidence being the rest of the line. **Judge MET/NOT MET from the diff, never from the Developer's own report.** `--objectives-file` is required whenever the closed Issue (or the PR body's own `## Objectives` section) has a list to judge; its ids must cover that list exactly. An Issue that predates the objectives cutover renders no `Objectives version:` line and no block at all. The command renders this exact shape (kept here so a human or a debugging agent can still read what it produces — this is documentation, not something to write by hand):
|
|
100
106
|
|
|
101
107
|
```
|
|
102
108
|
VERDICT: PASS | FAIL
|
|
103
109
|
|
|
104
110
|
Judged head: <sha>
|
|
105
111
|
|
|
112
|
+
Objectives version: <hash>
|
|
113
|
+
|
|
106
114
|
FINDINGS (ordered by severity):
|
|
107
115
|
1. [CRITICAL|HIGH|MEDIUM|LOW] <file:line> — <what and why>
|
|
108
116
|
2. ...
|
|
109
117
|
|
|
118
|
+
OBJECTIVES:
|
|
119
|
+
O1: MET | NOT MET — <evidence>
|
|
120
|
+
O2: ...
|
|
121
|
+
|
|
110
122
|
CONFIG SCAN: [not applicable | clean | findings folded in above]
|
|
111
123
|
SECRETS: [none found | listed above, redacted]
|
|
112
124
|
```
|
|
113
125
|
|
|
114
|
-
|
|
126
|
+
<!-- AEG:CLAIM: packages/aeg-core/src/verdict-extraction.ts contains:function firstFiveLines(comment: string): string { -->
|
|
127
|
+
<!-- AEG:CLAIM: apps/cli/src/commands/review-post.ts contains:export function renderEscalationComment(input: EscalationInput): string { -->
|
|
128
|
+
<!-- AEG:CLAIM: apps/cli/src/commands/review-post.ts contains:export function checkRenderedComment(body: string, expectation: RenderExpectation): RenderCheckResult { -->
|
|
129
|
+
Before its own post reaches the forge, `vinaya review post` refuses to post anything the gate would misread: it runs the exact same `VERDICT:`/`Judged head:`/`Objectives version:` extraction the merge gate uses over the rendered comment, and requires exactly the intended verdict to come back — and refuses outright if you pass a `--verdict PASS` together with any `NOT MET` objective, the same contradiction check `--verdict APPROVE` gets. Free text in a finding, `--config-scan`, `--secrets`, or an objective's evidence can say `VERDICT` or span multiple lines without risk — the extraction reads only a comment's first five lines, and in a code-reviewer or security comment a caller field never opens one of those lines (it only trails a fixed, renderer-owned label); an escalation's `--summary` is the one field that does occupy line 5 outright, which is exactly why this pre-post re-parse exists rather than construction alone.
|
|
115
130
|
|
|
116
131
|
- **CRITICAL** — leaked live credential, auth bypass, key sent to client. Any CRITICAL → FAIL.
|
|
117
132
|
- **HIGH** — likely exploitable misconfig or injection surface.
|
|
@@ -119,7 +134,7 @@ Before its own post reaches the forge, `vinaya review post` refuses to post anyt
|
|
|
119
134
|
|
|
120
135
|
Any CRITICAL or HIGH → VERDICT FAIL. Only MEDIUM/LOW → PASS with notes. You do not type that decision by hand: `vinaya review post` derives it from the findings file you pass it — FAIL iff a CRITICAL or HIGH is present, PASS otherwise — and refuses before posting anything if `--verdict` disagrees with the derivation, naming the derived value.
|
|
121
136
|
|
|
122
|
-
A re-pass after the Developer's fixes follows the same re-review rule as the code role: report the state of every prior id (`open`, `fix-claimed`, `reproduced`, `resolved`) in the finding's own description, `F<n> <class> <state>: <text>`, before listing anything new — `vinaya review post` refuses a findings file that drops a prior id with no state token. Round two is delta-only for MEDIUM and LOW: a MEDIUM/LOW finding whose `file:line` falls outside the diff since the previously judged head is refused. A CRITICAL or HIGH outside the delta still drives the verdict on any round and is always accepted. A prior CRITICAL/HIGH you mark `resolved` keeps its severity in the record but no longer drives the verdict — `vinaya review post` derives the verdict only from findings not marked `resolved`; mark `fix-claimed` or `reproduced` instead if it is not actually fixed.
|
|
137
|
+
A re-pass after the Developer's fixes follows the same re-review rule as the code role: report the state of every prior id (`open`, `fix-claimed`, `reproduced`, `resolved`) in the finding's own description, `F<n> <class> <state>: <text>`, before listing anything new — `vinaya review post` refuses a findings file that drops a prior id with no state token. Every prior objective reappears too — a re-pass's `--objectives-file` that drops a prior `O<n>` is refused before posting, the id read from the prior comment's own `OBJECTIVES:` block. Round two is delta-only for MEDIUM and LOW: a MEDIUM/LOW finding whose `file:line` falls outside the diff since the previously judged head is refused. A CRITICAL or HIGH outside the delta still drives the verdict on any round and is always accepted. A prior CRITICAL/HIGH you mark `resolved` keeps its severity in the record but no longer drives the verdict — `vinaya review post` derives the verdict only from findings not marked `resolved`; mark `fix-claimed` or `reproduced` instead if it is not actually fixed.
|
|
123
138
|
|
|
124
139
|
The `SECRETS:` line is evidence-backed, not asserted: the secret scanner's pasted output (check 1) must appear in the verdict comment above it — necessary evidence that the scan ran, never sufficient on its own, since the judgment half of check 1 still stands behind the claim. `SECRETS: none found` with no scan output pasted is an unbacked self-attestation — the exact claim this check exists to catch in others' work, not to commit in your own. `vinaya review post` mechanizes this: passing `--secrets "none found"` without `--secrets-evidence-file <path>` (the actual pasted scanner output) is refused outright.
|
|
125
140
|
|
|
@@ -135,9 +150,9 @@ Do not design the fix yourself; route it to the Planner or Principal.
|
|
|
135
150
|
|
|
136
151
|
## Where you sit in the process
|
|
137
152
|
|
|
138
|
-
Phase 10 (Review) in `process.md`: code-reviewer pass → **security pass (you)** → Principal code review →
|
|
153
|
+
Phase 10 (Review) in `process.md`: code-reviewer pass → **security pass (you)** → Principal code review → Planner spec review → merge.
|
|
139
154
|
|
|
140
|
-
**Your verdict is also a mechanical merge gate (the review-gate tranche, task 1).** A required, blocking CI check (the `review-gate` check — `vinaya check review-gate`, wired into every adopter's generated CI) reads every PR comment from a **principal-allowlisted author** (verdict-author verification, 2026-08-09 — bot and unknown-author comments are ignored) for a clean `PASS` verdict that also covers the PR's current head commit (reviewed-commit binding) — `FAIL`, a missing verdict, an unclear one, or one bound to a superseded commit all fail the check and block merge, same as the code-reviewer pass. This is not advisory: it is the same enforcement class as typecheck or lint. A principal can waive it for one PR with an actor-verified `vinaya/waiver:review` label (`aeg-root/enforcement.md`) — label presence alone is never sufficient.
|
|
155
|
+
**Your verdict is also a mechanical merge gate (the review-gate tranche, task 1).** A required, blocking CI check (the `review-gate` check — `vinaya check review-gate`, wired into every adopter's generated CI) reads every PR comment from a **principal-allowlisted author** (verdict-author verification, 2026-08-09 — bot and unknown-author comments are ignored) for a clean `PASS` verdict that also covers the PR's current head commit (reviewed-commit binding) and the current objectives list (objectives-version binding) — `FAIL`, a missing verdict, an unclear one, or one bound to a superseded commit or a superseded objectives list all fail the check and block merge, same as the code-reviewer pass. This is not advisory: it is the same enforcement class as typecheck or lint. A principal can waive it for one PR with an actor-verified `vinaya/waiver:review` label (`aeg-root/enforcement.md`) — label presence alone is never sufficient.
|
|
141
156
|
|
|
142
157
|
## Turn-end: report your tokens in the verdict comment
|
|
143
158
|
|
|
@@ -178,7 +178,7 @@ FORGE VERIFICATION:
|
|
|
178
178
|
|
|
179
179
|
RETROSPECTIVE: posted to pinned lessons Issue ✓ | INCOMPLETE (reason)
|
|
180
180
|
|
|
181
|
-
ARCHIVED: aeg-root/tranches/completed/<name>.md ✓ | FAILED (reason)
|
|
181
|
+
ARCHIVED: Milestone closed (forge-native) — or `aeg-root/tranches/completed/<name>.md` for a legacy pre-cutover tranche — ✓ | FAILED (reason)
|
|
182
182
|
|
|
183
183
|
PENDING RATIFICATIONS: [list with one-line description] | none
|
|
184
184
|
|
|
@@ -222,7 +222,7 @@ When you are **self-metering** — your host exposes your session's own usage to
|
|
|
222
222
|
|
|
223
223
|
**Trigger:** explicit Principal declaration. The command is: *"Run the Tranche Archivist for tranche <name>."* Nothing else triggers you. Not a CI event. Not a merge event. Not a post-checkout hook. The Principal makes a deliberate statement.
|
|
224
224
|
|
|
225
|
-
**Dispatch:** the Principal pastes the Tranche Archivist brief (or
|
|
225
|
+
**Dispatch:** the Principal pastes the Tranche Archivist brief (or delegates that to the Planner). The brief must include the tranche name and the explicit declaration. A Tranche Archivist without a declaration refuses at the entry gate.
|
|
226
226
|
|
|
227
227
|
**Why this design:** Tranche close involves a retrospective (which requires reflection) and a "what's next" declaration (which requires judgment). These are not mechanical operations. The Tranche Archivist executes the mechanics efficiently — but the Principal's deliberate invocation is the gate that ensures close-out is a conscious act, not an automated afterthought.
|
|
228
228
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: aeg
|
|
3
3
|
sidebar_title: Operating Model (aeg)
|
|
4
|
-
description: The front door to Agentic Execution Governance (AEG) — the operating model every agent works inside. Load at the start of ANY session in this repo, before doing anything substantive, regardless of role. Covers what AEG is, the four truth domains, forge-derived status, the tranche topology file, where the plan vs the flow vs governance live, the dispatch gates, the brief, the anti-regression rules, the orient-from-root layout (`aeg-root/` model + `aeg-project/` state), and the model-vs-product distinction. Ends by routing to the aeg-roles skill and the reading order. Does NOT cover role specifics (see aeg-roles + roles/*.md) or brief
|
|
4
|
+
description: The front door to Agentic Execution Governance (AEG) — the operating model every agent works inside. Load at the start of ANY session in this repo, before doing anything substantive, regardless of role. Covers what AEG is, the four truth domains, forge-derived status, the tranche topology file, where the plan vs the flow vs governance live, the dispatch gates, the brief, the anti-regression rules, the orient-from-root layout (`aeg-root/` model + `aeg-project/` state), and the model-vs-product distinction. Ends by routing to the aeg-roles skill and the reading order. Does NOT cover role specifics (see aeg-roles + roles/*.md) or the mechanics of dispatching one task's brief (see `roles/planner.md` § The dispatch act).
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
<!-- CANONICAL SOURCE. This file is the canonical home of the `aeg` skill, inside the AEG unit (aeg-root/skills/). provides for an agent-specific GENERATED VIEW under `.claude/skills/` (or another agent's equivalent), rebuilt from this file rather than authored by hand — but no such generator exists yet, and this repo has no generated view of this skill: agents are pointed at aeg-root/ directly (this repo's root agent-context file). Edit THIS file; if a generator is ever built, regenerate rather than hand-editing its output. -->
|
|
@@ -35,7 +35,7 @@ AEG runs on **the Repo + the Git forge (GitHub/GitLab) + plain git worktrees**,
|
|
|
35
35
|
- PR merged → merged · `aeg:blocked` label → blocked
|
|
36
36
|
Labels are only `tier:*`, `aeg:blocked`, `needs:*-input` — never status.
|
|
37
37
|
2. **The Repo** = code, specs, skills, PM docs, role docs, the thin tranche topology files, decisions. The source of truth for **plan and governance** (not live status).
|
|
38
|
-
3. **The
|
|
38
|
+
3. **The task Issue's `aeg:brief:v1` comment** = the **just-in-time brief** — a task's full execution context, rendered mechanically and posted once, frozen, never hand-written. The PR body carries only the Developer's report (optionally a reference copy of the brief in a collapsed `<details>` block).
|
|
39
39
|
4. **Local filesystem** = orchestration-tool runtime, worktrees, dev servers. Ephemeral, never canonical.
|
|
40
40
|
|
|
41
41
|
Conversation logs / thinking are **not** artifacts — never cite them as authority.
|
|
@@ -61,11 +61,11 @@ Conflicts are **package-level, and mostly derived, not hand-declared** (collisio
|
|
|
61
61
|
|
|
62
62
|
## 7. The brief
|
|
63
63
|
|
|
64
|
-
The brief is the task's full execution context: **
|
|
64
|
+
The brief is the task's full execution context: **rendered mechanically, never hand-written, posted once frozen as the task Issue's own `aeg:brief:v1` comment**, amended only via escalation. If it isn't in the brief, it doesn't exist. Rendering + dispatch rules: `roles/planner.md` § The dispatch act. Brief Step 0 is always worktree creation (`git worktree add .worktrees/task/<tranche>/<n> -b task/<tranche>/<n> --no-track origin/main`).
|
|
65
65
|
|
|
66
66
|
## 8. Roles (one line each — load the role doc for detail)
|
|
67
67
|
|
|
68
|
-
Principal → Planner →
|
|
68
|
+
Principal → Planner → Developer → Reviewer (code + security) → merge, plus the non-conversational Archivist. The Planner turns intent plus a backlog slice into a tranche (its plan act) and later checks a task's gates and dispatches its rendered brief (its dispatch act) — two acts, one role. **Do not operate from this list — load your role doc.** The **aeg-roles** skill routes you to the right one.
|
|
69
69
|
|
|
70
70
|
## 9. Tiers, decisions, ratification (the governance layer)
|
|
71
71
|
|
|
@@ -78,7 +78,7 @@ Principal → Planner → Brief Author → Developer → Reviewer (code + securi
|
|
|
78
78
|
|
|
79
79
|
- ❌ Never write task status anywhere (file, Issue field, label) — it is derived from the forge.
|
|
80
80
|
- ❌ Never add execution metadata (status, PR #, dates) to the tranche topology file — topology only.
|
|
81
|
-
- ❌ Never
|
|
81
|
+
- ❌ Never hand-write the brief into the Issue body — it is rendered mechanically and posted frozen as the Issue's own `aeg:brief:v1` comment, never in the PR body.
|
|
82
82
|
- ❌ Never put planning metadata (priority, estimates, points) on an Issue — that's the roadmap, outside AEG.
|
|
83
83
|
- ❌ Never build a dynamic conflict scanner — declare conservatively and serialize.
|
|
84
84
|
- ❌ Never read or write `roadmap.md` — retired.
|
|
@@ -20,8 +20,8 @@ Role is determined by **how you were invoked** — the *kind* of surface and the
|
|
|
20
20
|
|---|---|---|
|
|
21
21
|
| A **coding-agent surface** (CLI / IDE), executing a dispatched brief | **Developer** | `roles/developer.md` |
|
|
22
22
|
| A **chat / planning surface**, talking strategy / architecture | **Planner** | `roles/planner.md` |
|
|
23
|
-
| A **chat / planning surface**, turning intent + a backlog slice into a tranche | **Planner
|
|
24
|
-
| A **chat / planning surface**,
|
|
23
|
+
| A **chat / planning surface**, turning intent + a backlog slice into a tranche | **Planner — plan act** | `roles/planner.md` |
|
|
24
|
+
| A **chat / planning surface**, dispatching one task's rendered brief | **Planner — dispatch act** | `roles/planner.md` § The dispatch act |
|
|
25
25
|
| Invoked specifically to **review an open PR** (fresh context) | **Reviewer — code** | `roles/reviewer.md` |
|
|
26
26
|
| Invoked specifically to **security-review an open PR** | **Reviewer — security** | `roles/security.md` |
|
|
27
27
|
| Executing an **open PR's runtime Test Plan before merge** (the `[agent]` half is your Developer session; the Principal runs the `[principal]` half) | **Developer — Verification phase** (not a separate role) | `roles/developer.md` § Verification |
|
|
@@ -36,10 +36,10 @@ Always also skim `roles/principal.md` to know what sits in the Principal's seat
|
|
|
36
36
|
## 2. One line + entry gate per role (then open the doc)
|
|
37
37
|
|
|
38
38
|
- **Principal** — owns direction, ratifies Type 1 decisions and Tier 3 merges. The only role that ratifies irreversible decisions.
|
|
39
|
-
- **Planner** — intent + backlog slice → a thin tranche of sibling-aware tasks (a Milestone and labeled Issues; writes no briefs, no status). Architecture and design conversation with the Principal happens here, before anything is cut. May make Type 2 decisions ACTIVE immediately; Type 1 → PENDING.
|
|
40
|
-
- **
|
|
39
|
+
- **Planner (plan act)** — intent + backlog slice → a thin tranche of sibling-aware tasks (a Milestone and labeled Issues; writes no briefs, no status). Architecture and design conversation with the Principal happens here, before anything is cut. May make Type 2 decisions ACTIVE immediately; Type 1 → PENDING.
|
|
40
|
+
- **Planner (dispatch act)** — checks one task's dispatch gates (Issue exists, dependencies merged, no open conflicting sibling, render complete), then runs `vinaya task dispatch` (see `roles/planner.md` § The dispatch act) — there is no separate brief to hand-write, the render is mechanical. **Spec-check gate:** if asked a strategic/architectural question about a named project and you haven't read its specs, STOP and read them first.
|
|
41
41
|
- **Developer** — executes ONE dispatched brief. **Entry gate:** read the brief fully; confirm dispatch gates against the forge (`depends-on` merged, no `conflicts-with` sibling PR open); **Step 0 = create the worktree** (`task/<tranche>/<n>`); then pre-flight. Opens the PR and stops — does not merge, does not review itself, never writes status.
|
|
42
|
-
- **Reviewer (code)** — invoked fresh on an open PR. **Entry gate:** an open PR
|
|
42
|
+
- **Reviewer (code)** — invoked fresh on an open PR. **Entry gate:** an open PR whose task Issue carries the frozen `aeg:brief:v1` comment, else refuse. Reads the diff + the brief (from that comment) + (advisory) the project spec; emits a VERDICT; read + review-comment authority only; does not edit code, does not merge.
|
|
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.
|
|
@@ -47,11 +47,11 @@ Always also skim `roles/principal.md` to know what sits in the Principal's seat
|
|
|
47
47
|
|
|
48
48
|
## 3. Authority boundaries (so roles don't bleed)
|
|
49
49
|
|
|
50
|
-
- Only the **Principal** ratifies Type 1 (irreversible) decisions. The **Planner**
|
|
50
|
+
- Only the **Principal** ratifies Type 1 (irreversible) decisions. The **Planner** (either act) may ratify Type 2 (reversible) — ACTIVE immediately.
|
|
51
51
|
- The **Developer** mutates code on its branch only; it never merges, never reviews its own work, never writes status.
|
|
52
52
|
- **Reviewers** have read + PR-review-comment authority only — no code edits, no merge. Review is always a **separate, fresh-context** invocation from the Developer.
|
|
53
53
|
- The **Archivist** updates living-state PM docs at close-out but writes no task status and authors no code.
|
|
54
|
-
- **Escalation severity** routes the ask: `execution` and `strategy` →
|
|
54
|
+
- **Escalation severity** routes the ask: `execution` and `strategy` → Planner (how to run the task vs which design path to take), `product` → Principal. Labels `needs:execution-input` / `needs:strategy-input` / `needs:principal-input`.
|
|
55
55
|
|
|
56
56
|
## 4. Reminder
|
|
57
57
|
|