@journeykit/canon 0.29.0 → 0.31.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/dist/skills/SKILL.src.md +48 -22
- package/dist/skills/reference/brief-polish.md +4 -4
- package/dist/skills/reference/brief-shape.md +38 -7
- package/dist/skills/reference/canon-authoring.md +6 -6
- package/dist/skills/reference/canon-gate.md +49 -34
- package/dist/skills/reference/canon-learn.md +2 -2
- package/dist/skills/reference/canon-plan-import.md +2 -2
- package/dist/skills/reference/canon-plugins.md +6 -6
- package/dist/skills/reference/canon-report-dashboard.md +12 -8
- package/dist/skills/reference/canon-review.md +26 -25
- package/dist/skills/reference/canon-storage.md +20 -3
- package/dist/skills/reference/canon-subject.md +132 -98
- package/dist/skills/reference/role-implementer.md +42 -28
- package/dist/skills/reference/role-orchestrator.md +40 -24
- package/dist/skills/reference/role-planner.md +32 -17
- package/dist/skills/reference/role-reviewer.md +48 -30
- package/man/canon-adapter-authorize.1 +2 -2
- package/man/canon-adapter-validate.1 +2 -2
- package/man/canon-adapter.1 +2 -2
- package/man/canon-artifacts-move.1 +2 -2
- package/man/canon-artifacts-store.1 +2 -2
- package/man/canon-artifacts-verify.1 +2 -2
- package/man/canon-artifacts.1 +2 -2
- package/man/canon-brief-approve.1 +7 -4
- package/man/canon-brief-check.1 +2 -2
- package/man/canon-brief-show.1 +2 -2
- package/man/canon-brief.1 +8 -7
- package/man/canon-change-new.1 +4 -4
- package/man/canon-change.1 +3 -3
- package/man/canon-completion.1 +2 -2
- package/man/canon-context-pack-add.1 +2 -2
- package/man/canon-context-pack-show.1 +2 -2
- package/man/canon-context-pack-verify.1 +2 -2
- package/man/canon-context-pack.1 +2 -2
- package/man/canon-context.1 +2 -2
- package/man/canon-dashboard.1 +2 -2
- package/man/canon-demo-init.1 +2 -2
- package/man/canon-demo-review.1 +2 -2
- package/man/canon-demo.1 +2 -2
- package/man/canon-dispatch-begin.1 +10 -10
- package/man/canon-dispatch-diff.1 +2 -2
- package/man/canon-dispatch-end.1 +2 -2
- package/man/canon-dispatch.1 +2 -2
- package/man/canon-divergence-accept.1 +6 -6
- package/man/canon-divergence-add.1 +6 -6
- package/man/canon-divergence-defer.1 +6 -6
- package/man/canon-divergence-list.1 +2 -2
- package/man/canon-divergence-resolve.1 +6 -6
- package/man/canon-divergence.1 +2 -2
- package/man/canon-evidence-add.1 +16 -16
- package/man/canon-evidence-approval-payload.1 +10 -10
- package/man/canon-evidence-audit.1 +10 -10
- package/man/canon-evidence.1 +3 -3
- package/man/canon-export.1 +2 -2
- package/man/canon-feature-new.1 +6 -6
- package/man/canon-feature.1 +2 -2
- package/man/canon-finding-add.1 +23 -11
- package/man/canon-finding-close.1 +8 -8
- package/man/canon-finding-list.1 +4 -4
- package/man/canon-finding.1 +4 -4
- package/man/canon-format.1 +2 -2
- package/man/canon-gate-check.1 +2 -2
- package/man/canon-gate-install-hooks.1 +2 -2
- package/man/canon-gate-promote.1 +2 -2
- package/man/canon-gate.1 +2 -2
- package/man/canon-ingest-plans.1 +2 -2
- package/man/canon-ingest-records.1 +4 -4
- package/man/canon-ingest-sessions.1 +2 -2
- package/man/canon-ingest.1 +2 -2
- package/man/canon-init.1 +2 -2
- package/man/canon-inventory-sync.1 +2 -2
- package/man/canon-inventory.1 +2 -2
- package/man/canon-ledger-compact.1 +2 -2
- package/man/canon-ledger.1 +2 -2
- package/man/canon-migrate.1 +25 -3
- package/man/canon-plugin-sync.1 +2 -2
- package/man/canon-plugin.1 +2 -2
- package/man/canon-policy-approve.1 +2 -2
- package/man/canon-policy-show.1 +2 -2
- package/man/canon-policy.1 +2 -2
- package/man/canon-prompt-add.1 +2 -2
- package/man/canon-prompt-show.1 +2 -2
- package/man/canon-prompt.1 +2 -2
- package/man/canon-purge.1 +2 -2
- package/man/canon-query.1 +5 -5
- package/man/canon-regime-show.1 +2 -2
- package/man/canon-regime.1 +2 -2
- package/man/canon-report-build.1 +2 -2
- package/man/canon-report-check.1 +2 -2
- package/man/canon-report-snapshot.1 +2 -2
- package/man/canon-report.1 +2 -2
- package/man/canon-retrieve.1 +5 -5
- package/man/canon-review-change.1 +6 -6
- package/man/canon-review-scenario.1 +6 -6
- package/man/canon-review.1 +2 -2
- package/man/canon-scenario-new.1 +10 -10
- package/man/canon-scenario.1 +2 -2
- package/man/canon-schema.1 +2 -2
- package/man/canon-search.1 +104 -0
- package/man/canon-selftest.1 +2 -2
- package/man/canon-skills-check.1 +2 -2
- package/man/canon-skills-doctor.1 +2 -2
- package/man/canon-skills-install.1 +2 -2
- package/man/canon-skills-show.1 +2 -2
- package/man/canon-skills.1 +2 -2
- package/man/canon-status.1 +7 -2
- package/man/canon-strategy-approval-payload.1 +2 -2
- package/man/canon-strategy-promote.1 +2 -2
- package/man/canon-strategy-rollback.1 +5 -5
- package/man/canon-strategy.1 +2 -2
- package/man/canon-subject-adopt.1 +4 -4
- package/man/canon-subject-move.1 +5 -5
- package/man/canon-subject-new.1 +5 -5
- package/man/canon-subject-show.1 +2 -2
- package/man/canon-subject-unadopt.1 +5 -5
- package/man/canon-subject.1 +2 -2
- package/man/canon-task-done.1 +2 -2
- package/man/canon-task.1 +2 -2
- package/man/canon-tier-age.1 +2 -2
- package/man/canon-tier.1 +2 -2
- package/man/canon-trace.1 +56 -0
- package/man/canon.1 +8 -2
- package/package.json +4 -4
package/dist/skills/SKILL.src.md
CHANGED
|
@@ -34,8 +34,9 @@ a feature, a one-line request included. A human is needed once per scope:
|
|
|
34
34
|
approves the brief and the policy, `.canon/policy.yaml`, which is what
|
|
35
35
|
the gate grades the work against. The human may also approve it on the `canon dashboard` briefs page; you never use that form.
|
|
36
36
|
The human records the answer, never you:
|
|
37
|
-
`canon brief approve <slug> --approver <their name> --note "<their words>"`
|
|
38
|
-
|
|
37
|
+
`canon brief approve <slug> <slug> --approver <their name> --note "<their words>"`
|
|
38
|
+
(one or more slugs, one answer for all, nothing written if any is refused)
|
|
39
|
+
refuses every agent role (`HUMAN_ONLY`). Report that exact call, every slug filled in, and
|
|
39
40
|
wait; never remove or unset your role (`env -u CANON_ROLE`, dropping `--as`) to run it yourself.
|
|
40
41
|
Never edit the policy to make the gate pass: a policy that differs from
|
|
41
42
|
the approved one fails closed (`POLICY_CHANGED_SINCE_APPROVAL`, not
|
|
@@ -43,16 +44,20 @@ a feature, a one-line request included. A human is needed once per scope:
|
|
|
43
44
|
approval is not approved (`BRIEF_CHANGED_SINCE_APPROVAL`): it needs a new
|
|
44
45
|
answer. The ship guard and `canon evidence add` refuse an unapproved or
|
|
45
46
|
edited brief, but those are backstops: the stop itself is at step 1.
|
|
46
|
-
- **Approval is scoped.** Evidence for a scenario
|
|
47
|
-
changes its
|
|
48
|
-
on a live subject waits on its own scenarios
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
47
|
+
- **Approval is scoped.** Evidence for a scenario tagged `@flow:<change>.<F-id>`
|
|
48
|
+
needs the approval of the changes its tags name only, so a new unapproved
|
|
49
|
+
change on a live subject waits on its own scenarios; an untagged scenario
|
|
50
|
+
answers to every change with an `Approved:` line (an edited one refuses); `change new` and
|
|
51
|
+
`subject adopt` warn when the subject is live. `canon subject unadopt <subject-id> --change <change>`
|
|
52
|
+
takes a draft change back off (refused once approved). The subject
|
|
53
|
+
answers for every adopted change that is tagged (a scenario of the subject
|
|
54
|
+
is tagged `@flow:<change>.*`), has an `Approved:` line, or is a chore:
|
|
55
|
+
reopen and ship pass only when all of them are approved now, whatever the
|
|
56
|
+
order they were adopted or approved in, and `canon status` lists one entry
|
|
57
|
+
per such change in `briefs`. A pending draft (never approved, not a chore,
|
|
58
|
+
tagged by no scenario) blocks nothing and the transition prints one line
|
|
59
|
+
naming every draft; a draft a scenario is tagged for blocks until it is
|
|
60
|
+
approved. `canon skills show canon-subject`
|
|
56
61
|
- **Inside an approved scope, never stop for a human.** Fixes, follow-ups,
|
|
57
62
|
review rounds and re-reviews stay in the approved change (never
|
|
58
63
|
`canon change new`: a new change is a new scope) and go straight on: scenario,
|
|
@@ -110,7 +115,7 @@ needs its change-level review alone. What counts as code is `code.exclude` in
|
|
|
110
115
|
`canon status`, `meta.next` and the refusal hint lead with one batch over
|
|
111
116
|
every report, for example
|
|
112
117
|
`canon evidence add --all-scenarios --report junit:a.xml --report junit:b.xml --role implementer`
|
|
113
|
-
(with the real report paths, and `--project
|
|
118
|
+
(with the real report paths, and `--project <id>` when the repo has several
|
|
114
119
|
spec roots), never a loop per scenario. With a `--report`, `--class` defaults
|
|
115
120
|
to `test-run` and `--ref` to the report paths, and the bound cases decide the
|
|
116
121
|
verdict: any failed case `divergent`, a skipped one and none failed
|
|
@@ -137,6 +142,25 @@ refuse, never pass, when it cannot be reached. Moving an existing store with
|
|
|
137
142
|
`canon artifacts move --tier <tier>` is the repo owner's decision, not a step
|
|
138
143
|
of the loop.
|
|
139
144
|
|
|
145
|
+
### Search and trace
|
|
146
|
+
|
|
147
|
+
`canon search "<text>"` finds a record, a brief section or flow step, or a
|
|
148
|
+
scenario's text (title, steps, tables, `Examples`, the Background and Rule it
|
|
149
|
+
inherits) and lists each hit with its neighbors in the record graph: the
|
|
150
|
+
records it names or that name it, the review loop around a finding, the brief
|
|
151
|
+
step a scenario covers. A reference no committed source holds is a neighbor
|
|
152
|
+
marked `placeholder`, never an error. `--kind` (repeatable) keeps hits of those
|
|
153
|
+
kinds, `--expand <N>` sets the hops (default 1), `--limit <N>` the hits (default
|
|
154
|
+
20). Korean is found from three characters; a shorter text is found as a part of
|
|
155
|
+
a node's text, in id order. The text is read as typed: quotes and `AND` are not
|
|
156
|
+
syntax. `canon trace <finding key|review id|sha>` follows the review, finding,
|
|
157
|
+
fix, re-review and evidence chain of a loop in time order, the archive's
|
|
158
|
+
earlier versions included. Both read, and first refresh, a derived index,
|
|
159
|
+
`.canon/index/search.db`: gitignored, never a source of records, safe to delete
|
|
160
|
+
(the next run rebuilds it, and only `data.index.rebuilt` differs). Records still
|
|
161
|
+
staged, and those in postgres or an object store, are not in it; `data.index`
|
|
162
|
+
names the stores not read.
|
|
163
|
+
|
|
140
164
|
## Know your role
|
|
141
165
|
|
|
142
166
|
canon cannot detect a role; you declare it. Pass `--as <role>` or set
|
|
@@ -175,7 +199,7 @@ A role is guidance, not enforcement: `--role` on `evidence add` and
|
|
|
175
199
|
`warnings` and, for a repeated write that changed nothing, `unchanged: true`.
|
|
176
200
|
On failure branch on `error.code`, fix the option `error.field` names
|
|
177
201
|
using the `error.expected` values (`field` is an option name, or a JSON
|
|
178
|
-
pointer such as `/items/2/
|
|
202
|
+
pointer such as `/items/2/scenario` into an `--input` document), and
|
|
179
203
|
follow `error.hint`: every refusal carries a working invocation. The codes
|
|
180
204
|
are stable; `canon schema --errors --json` lists them and
|
|
181
205
|
`canon schema --error <CODE>` explains one.
|
|
@@ -185,9 +209,11 @@ A role is guidance, not enforcement: `--role` on `evidence add` and
|
|
|
185
209
|
A refusal leaves the tree unchanged.
|
|
186
210
|
- Repeating a write is safe: a record that already exists with identical
|
|
187
211
|
content is reported `unchanged` (`meta.unchanged`), not duplicated.
|
|
188
|
-
-
|
|
189
|
-
`--
|
|
190
|
-
`--session-
|
|
212
|
+
- An option that takes an id is the bare noun (`--change add-login`,
|
|
213
|
+
`--scenario auth.login.01`, `--actor reviewer-1`, `--project root`,
|
|
214
|
+
`--session s-1`), and an `--input` document key is that name without `Id`
|
|
215
|
+
(`scenario`, `actor`; the stored record and report JSON keep `scenario_id`,
|
|
216
|
+
`scenarioId`). The primary object of a command is its operand
|
|
191
217
|
(`canon subject move <id> --to verifying`, `canon change new <slug>`), and
|
|
192
218
|
`--kind` values carry no `_record` suffix (`--kind evidence`).
|
|
193
219
|
- `canon status` sends the planner to write the brief while `brief check`
|
|
@@ -218,8 +244,8 @@ before anything is written: an invalid element writes nothing and exits 2,
|
|
|
218
244
|
|
|
219
245
|
```text
|
|
220
246
|
canon scenario new --input '[{"operands":["auth.login.01"],"title":"Logs in","case":"happy"},{"operands":["auth.login.02"],"title":"Wrong password","case":"failure"}]'
|
|
221
|
-
canon evidence add --input '[{"
|
|
222
|
-
canon finding add --input '[{"
|
|
247
|
+
canon evidence add --input '[{"scenario":"auth.login.01","class":"test-run","ref":"npm test","role":"implementer"},{"scenario":"auth.login.02","class":"test-run","ref":"npm test","role":"implementer"}]'
|
|
248
|
+
canon finding add --input '[{"change":"add-login","round":1,"seq":1,"severity":"note","actor":"reviewer-1","summary":"Token is logged"},{"change":"add-login","round":1,"seq":2,"severity":"blocker","introducedUnknown":true,"actor":"reviewer-1","summary":"No rate limit"}]'
|
|
223
249
|
```
|
|
224
250
|
|
|
225
251
|
`--input` never carries `--commit` or `--plan-digest`, and the destructive
|
|
@@ -252,7 +278,7 @@ and `canon context` warn when the repo holds 0.27-era state and put
|
|
|
252
278
|
2. `canon migrate --commit --plan-digest <digest>` with that digest applies it.
|
|
253
279
|
It moves the layout, rewrites canon's own hooks and scripts, compacts the
|
|
254
280
|
ledger, replaces an old full skill with the stub, and backs up every file it
|
|
255
|
-
rewrites under `.canon/migrate-backup
|
|
281
|
+
rewrites under `.canon/migrate-backup/` (local and git-ignored; `--revert` needs it). It refuses uncommitted changes
|
|
256
282
|
under a path it moves.
|
|
257
283
|
3. `canon skills install` refreshes the stub and the scripts; `canon skills check`
|
|
258
284
|
confirms them.
|
|
@@ -293,10 +319,10 @@ on the list.
|
|
|
293
319
|
|
|
294
320
|
- **Fix a bug:** the approved change if there is one, else the planner (`canon change new`); first a failing run of the scenario (`canon scenario new --case failure`, then `canon evidence add`), then the fix. `canon skills show role-implementer`.
|
|
295
321
|
- **Add or change a feature:** `canon subject new`, `canon change new`, then the brief. `canon skills show role-planner`.
|
|
296
|
-
- **Pure refactor, dependency, build, CI or infra:** `canon change new <slug> --subject
|
|
322
|
+
- **Pure refactor, dependency, build, CI or infra:** `canon change new <slug> --subject <id> --change-kind chore`; data or interface changes are not chores. `canon skills show role-planner`.
|
|
297
323
|
- **Review someone's change:** `CANON_ROLE=reviewer`, `canon brief check <slug>`. `canon skills show role-reviewer`.
|
|
298
324
|
- **Resume:** `canon status --json`, then follow `meta.next`. `canon skills show role-orchestrator`.
|
|
299
|
-
- **Plan more work on a live subject:** `canon change new <slug> --subject
|
|
325
|
+
- **Plan more work on a live subject:** `canon change new <slug> --subject <id>` (it warns until the brief is approved; `canon subject unadopt` parks a draft). `canon skills show canon-subject`, `canon skills show role-planner`.
|
|
300
326
|
- **Upgrade canon in a repo:** `canon migrate` (previews), then `canon migrate --commit --plan-digest <digest>`, then `canon skills install`. See "Upgrading a repo from 0.27" above and `canon skills show role-orchestrator`.
|
|
301
327
|
|
|
302
328
|
**Done when:** you have named your role and loaded its guide, and `canon status --json` lists your next step in `meta.next`.
|
|
@@ -151,7 +151,7 @@ still draws a finding. Never waive the rule for the whole section.
|
|
|
151
151
|
|
|
152
152
|
- en. Before: "On 3 March the team agreed on a grid as the default view." After: "The default view is a grid."
|
|
153
153
|
- ko. 전: "3월 3일 회의에서 기본 보기를 격자로 하기로 했다." 후: "기본 보기는 격자다."
|
|
154
|
-
- waive one date:
|
|
154
|
+
- waive one date: frontmatter entry `rule: prose.decision-history`, `section: detail`, `reason: "연체 요금은 2026-12-01부터 적용되는 동작이다"`, `match: "2026-12-01"`
|
|
155
155
|
|
|
156
156
|
What it misses: a decision written in other words ("회의에서 정한 대로" is not
|
|
157
157
|
listed on purpose, it reads as behavior). Over-reports: a date that is
|
|
@@ -209,8 +209,8 @@ uses the section key `brief`.
|
|
|
209
209
|
|
|
210
210
|
- `canon brief check --json`: read the `prose.*` findings, then the sections they sit in. Fix by section, not by rule.
|
|
211
211
|
- A finding is a prompt to reread, not a verdict. When the flagged text is the precise term (a state name, a quoted label, a command), keep it and waive that rule in that section:
|
|
212
|
-
|
|
213
|
-
To waive one finding and keep the rest of the rule live in that section, add the text the finding names
|
|
212
|
+
an entry of the frontmatter `waive` list: `- rule: <rule-id>`, `section: <section-key>`, `reason: "<reason>"`.
|
|
213
|
+
To waive one finding and keep the rest of the rule live in that section, add the text the finding names as `match: "<text>"` (an empty reason or match, an unknown rule id or an unknown key is a blocker).
|
|
214
214
|
A waiver is right when the text is a quotation or a fixed term, and wrong when it excuses a sentence you could simply rewrite. One rule, one section, a reason the human can read.
|
|
215
215
|
|
|
216
216
|
## The loop
|
|
@@ -224,7 +224,7 @@ uses the section key `brief`.
|
|
|
224
224
|
|
|
225
225
|
- Never change meaning: no flow step, rule, limit or failure path added, removed or softened while rewording.
|
|
226
226
|
- Never rewrite to dodge a rule (a near synonym, a list used to hide a long sentence); say the concrete thing.
|
|
227
|
-
- Never touch flow ids or subheadings, and never polish the
|
|
227
|
+
- Never touch flow ids or subheadings, and never polish the headings.
|
|
228
228
|
- Never translate the brief to match a `language:` setting.
|
|
229
229
|
- Never treat a clean run as a claim about who wrote the brief.
|
|
230
230
|
|
|
@@ -8,26 +8,57 @@ check reports `brief.section-missing`, `brief.section-duplicate`,
|
|
|
8
8
|
|
|
9
9
|
## Scope
|
|
10
10
|
|
|
11
|
-
`.canon/changes/<slug>/brief.md`: section
|
|
11
|
+
`.canon/changes/<slug>/brief.md`: section headings, order, and leftover
|
|
12
12
|
template text. A feature brief runs intent → outcome → flow → detail →
|
|
13
13
|
acceptance → questions → out-of-scope; a chore brief runs intent → category →
|
|
14
|
-
invariants → checks → out-of-scope (
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
invariants → checks → out-of-scope (`kind: chore` in the frontmatter). Sections
|
|
15
|
+
are found by their English `##` heading, whatever the brief's language; a
|
|
16
|
+
`##` line that is not one of the headings below is body text of the section
|
|
17
|
+
before it. `language:` only picks the language of the prose rules and the
|
|
18
|
+
guidance.
|
|
19
|
+
|
|
20
|
+
| Section | Heading | Role | What goes in it |
|
|
21
|
+
| --- | --- | --- | --- |
|
|
22
|
+
| intent | `## Intent` | context | What problem this solves, for whom, and why now. One to three sentences. |
|
|
23
|
+
| outcome | `## Desired outcome` | normative | What is observably true once this ships, from the user's side. |
|
|
24
|
+
| flow | `## User flow` | normative | A numbered list; each item starts with its id and reads sees → does → becomes: `1. F1 The user sees … → does … → becomes …`. |
|
|
25
|
+
| detail | `## Step detail` | normative | One `### F1 …` subheading per flow step, in the flow's order: rules, states and edge cases of that step. |
|
|
26
|
+
| acceptance | `## Acceptance` | normative | Per step: what must be observable, and which failure path is covered. Do not write scenario ids here. |
|
|
27
|
+
| questions | `## Questions and assumptions` | question | What is unresolved and what you assumed; anything that could change policy goes here. Write `None.` if nothing. |
|
|
28
|
+
| out-of-scope | `## Out of scope` | context | What this change deliberately does not do. Write `None.` if nothing. |
|
|
29
|
+
| category (chore) | `## Category` | context | Exactly one of `refactor`, `dependency`, `build`, `ci`, `infra`. |
|
|
30
|
+
| invariants (chore) | `## Invariants` | normative | What must not change: behavior, public interfaces, data, outputs. A change that alters any of them is a feature, not a chore. |
|
|
31
|
+
| checks (chore) | `## Checks` | normative | How you show the invariants held: the suite that is run again at the chore commit, and anything else you compare. |
|
|
32
|
+
|
|
33
|
+
`canon change new` writes the brief with these headings and nothing under
|
|
34
|
+
them: an empty section is a section not yet written, and `canon brief show`
|
|
35
|
+
prints the guidance of each empty one (in `language:`). A wrong heading
|
|
36
|
+
(`## Intnet`, `## intent`) is reported with the nearest heading.
|
|
17
37
|
|
|
18
38
|
## Inspect
|
|
19
39
|
|
|
20
40
|
- `canon brief check --json`: each finding names the rule, section key, line and hint.
|
|
21
|
-
- Every section present once, in order, with its
|
|
41
|
+
- Every section present once, in order, with its exact English heading; no `TODO`/`TBD`; no empty section (write `None.` where nothing applies).
|
|
22
42
|
- The flow is a numbered list with ids `F1`, `F2`, … each reading sees → does → becomes.
|
|
23
43
|
- Intent describes what the product does today and Outcome what is true after; leftover implementation paths belong in a `Source:` line or nowhere.
|
|
24
44
|
- A chore's category is exactly one of `refactor`, `dependency`, `build`, `ci`, `infra`; its invariants and checks say something.
|
|
25
|
-
-
|
|
45
|
+
- Waivers live in the frontmatter, visible on the page, and the approval covers them:
|
|
46
|
+
```
|
|
47
|
+
---
|
|
48
|
+
waive:
|
|
49
|
+
- rule: prose.length
|
|
50
|
+
section: brief
|
|
51
|
+
reason: "why the rule does not apply"
|
|
52
|
+
match: "optional text the finding contains"
|
|
53
|
+
---
|
|
54
|
+
```
|
|
55
|
+
Each entry has a known `rule`, a `section` key (or `brief`) and a non-empty `reason`; an unknown key is a blocker. Adding one after the approval is a change after the approval.
|
|
56
|
+
- A brief that still has `<!-- canon:… -->` comments or Korean headings is in the old format: `canon migrate` (preview first) rewrites it, and the human runs `--commit` when it re-binds an approval.
|
|
26
57
|
|
|
27
58
|
## NEVER
|
|
28
59
|
|
|
29
60
|
- Never fill a section with text you made up to silence a placeholder: write what the request and the repo support, and put the rest in Questions.
|
|
30
|
-
- Never delete a section,
|
|
61
|
+
- Never delete a section, rename a heading to another role, or add a global waiver to pass. A waiver is one rule in one section with a reason the human can read.
|
|
31
62
|
- Never turn a chore's missing invariants into "none" to pass: behavior-changing work is a feature change.
|
|
32
63
|
|
|
33
64
|
## Verify
|
|
@@ -84,7 +84,7 @@ enum, like `lane`.
|
|
|
84
84
|
## Subject pinning
|
|
85
85
|
|
|
86
86
|
Every scenario belongs to a Subject (the durable product unit, see
|
|
87
|
-
`canon-subject`). Write the Subject first, then pin with `--subject
|
|
87
|
+
`canon-subject`). Write the Subject first, then pin with `--subject`;
|
|
88
88
|
the scenario index carries the tag onto the index record and
|
|
89
89
|
`spec_coverage.scope` filters on it. An unpinned scenario is invisible to
|
|
90
90
|
a scoped gate.
|
|
@@ -94,9 +94,9 @@ a scoped gate.
|
|
|
94
94
|
```bash
|
|
95
95
|
canon feature new checkout.cart --title "Cart" # once per surface
|
|
96
96
|
canon scenario new checkout.cart.01 --title "Adding an item raises the count" \
|
|
97
|
-
--subject
|
|
97
|
+
--subject checkout-core --lane behavior --case happy # once per behavior
|
|
98
98
|
canon scenario new checkout.cart.04 --title "Adding an out-of-stock item is refused" \
|
|
99
|
-
--subject
|
|
99
|
+
--subject checkout-core --lane behavior --case failure # and its failure path
|
|
100
100
|
```
|
|
101
101
|
|
|
102
102
|
There is no format or sync step after these: the scaffold writes a
|
|
@@ -115,10 +115,10 @@ camelCase keys. `canon schema scenario new --json` shows the input schema
|
|
|
115
115
|
and an example. There is no `--from`.
|
|
116
116
|
|
|
117
117
|
```text
|
|
118
|
-
canon scenario new --input '[{"operands":["checkout.cart.01"],"title":"Adding an item raises the count","
|
|
118
|
+
canon scenario new --input '[{"operands":["checkout.cart.01"],"title":"Adding an item raises the count","subject":"checkout-core","lane":"behavior","case":"happy"},{"operands":["checkout.cart.04"],"title":"Adding an out-of-stock item is refused","subject":"checkout-core","lane":"behavior","case":"failure"}]'
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
- `--actor
|
|
121
|
+
- `--actor <id>` (or `CANON_ACTOR` in the environment) puts YOUR id on the
|
|
122
122
|
provenance line. Default is `canon-scaffold`.
|
|
123
123
|
- **Keep the `# canon:` lines when you fill in the scenario.** Dropping one
|
|
124
124
|
makes `canon inventory sync` abort on `missing-provenance`; restore it
|
|
@@ -160,7 +160,7 @@ wait for evidence, which `canon gate check` reports.
|
|
|
160
160
|
- **A Feature title that is a theme.** "Fidelity of the original
|
|
161
161
|
experience" names no surface. Name the screen.
|
|
162
162
|
- **Hand-stamped provenance.** Eighty lines with one timestamp and the
|
|
163
|
-
same `agent_id`. Use `canon scenario new --actor
|
|
163
|
+
same `agent_id`. Use `canon scenario new --actor`.
|
|
164
164
|
- **Coverage by splitting.** One behavior as two scenarios so two rows go
|
|
165
165
|
green. One behavior, one id.
|
|
166
166
|
- **Runner tags as classification.** `@design`, `@p2`, `@wip` are
|
|
@@ -129,11 +129,11 @@ A present section, even `require_evidence: false` or a malformed one
|
|
|
129
129
|
|
|
130
130
|
- **Unimplemented** — no `EvidenceRecord` carries the scenario's
|
|
131
131
|
`(project_id, scenario_id)`. Author one with
|
|
132
|
-
`canon evidence add --scenario
|
|
132
|
+
`canon evidence add --scenario <id> --project <root-id>`; the
|
|
133
133
|
root id is needed once more than one spec root is configured, because
|
|
134
134
|
two roots may carry the same scenario id. `--summary` is allowed here too (scanned for fabrication
|
|
135
135
|
markers like a task's); it is a row suffix only when the record also
|
|
136
|
-
names a `--task
|
|
136
|
+
names a `--task`. A record carrying both `--task` and `--scenario`
|
|
137
137
|
is one attestation answering both joins: it counts for the task cell
|
|
138
138
|
and for the scenario cell (verdicts, the shipped gate, the review gate).
|
|
139
139
|
- **Mismatched** — the folded divergence state is `open`,
|
|
@@ -161,7 +161,7 @@ A present section, even `require_evidence: false` or a malformed one
|
|
|
161
161
|
(a review written before 0.15 has no pins and skips this check), and,
|
|
162
162
|
when `distinct_actor` (default `true`), is by a reviewer and actor
|
|
163
163
|
other than the scenario's evidence actor and from a session other than
|
|
164
|
-
any evidence session when both carry one (`--session
|
|
164
|
+
any evidence session when both carry one (`--session`);
|
|
165
165
|
gaps are `unreviewed-promotion`, and the detail says whether the
|
|
166
166
|
review is missing, a self-review, stale (naming whether the spec, the
|
|
167
167
|
evidence or both changed), or not signed. With `block_on_findings`
|
|
@@ -205,14 +205,20 @@ Two refusals rather than a silent pass, both surfacing as
|
|
|
205
205
|
`divergence`, or `subject` sent anywhere but `local`) refuses, because
|
|
206
206
|
the gate reads one tier and would otherwise pass by seeing nothing.
|
|
207
207
|
|
|
208
|
-
|
|
208
|
+
Unparseable rows in those three kinds do NOT surface as
|
|
209
209
|
`malformed-evidence`; they are kept off the evidence violation set on
|
|
210
|
-
purpose, so enabling nothing changes no existing verdict.
|
|
210
|
+
purpose, so enabling nothing changes no existing verdict. A row whose file
|
|
211
|
+
name is not the one its body computes (a layout violation) is the
|
|
212
|
+
exception once `spec_coverage` judges the corpus: the gate names it as
|
|
213
|
+
`malformed-evidence`, because every read skips it and the corpus being
|
|
214
|
+
judged would otherwise be missing it silently. Without the section the
|
|
215
|
+
gate stays as it was; `canon query --kind <kind>` and `canon status`
|
|
216
|
+
report such files.
|
|
211
217
|
|
|
212
218
|
### Accepted divergence and re-verification
|
|
213
219
|
|
|
214
220
|
```bash
|
|
215
|
-
canon divergence accept cart.add.01 --project
|
|
221
|
+
canon divergence accept cart.add.01 --project root --reason "known gap" --tracking "issue#12" --expiry 2026-12-31 --actor reviewer-2 --role reviewer --session review-session-1
|
|
216
222
|
```
|
|
217
223
|
|
|
218
224
|
Accepting a scenario whose latest evidence is `divergent` as a known gap
|
|
@@ -234,10 +240,10 @@ Re-verification is one rule with two triggers: a blocker whose latest
|
|
|
234
240
|
disposition is `fixed`, and a chore change once approved, keep the subject
|
|
235
241
|
from shipping until every one of its evidenced scenarios has evidence
|
|
236
242
|
recorded after the close or the approval. A blocker that names its
|
|
237
|
-
scenarios (`finding add --scenario
|
|
238
|
-
names them with the per-scenario command (`canon evidence add --project
|
|
239
|
-
<root-id> --scenario
|
|
240
|
-
refusal names the scenarios and the batch command: `canon evidence add --project
|
|
243
|
+
scenarios (`finding add --scenario`) asks only those, and the refusal
|
|
244
|
+
names them with the per-scenario command (`canon evidence add --project
|
|
245
|
+
<root-id> --scenario <id> --report <format>:<path>` plus `--class`, `--role` and `--ref`). Otherwise the
|
|
246
|
+
refusal names the scenarios and the batch command: `canon evidence add --project <root-id>
|
|
241
247
|
--all-scenarios --report <format>:<path> --class test-run --role
|
|
242
248
|
implementer --ref "<test command>"`. Reviews pin what the evidence says
|
|
243
249
|
(its verdict and the identity of its checks), not which record it is, so
|
|
@@ -253,17 +259,17 @@ canon never generates or runs an audit. An external evaluator does, and
|
|
|
253
259
|
canon records its result:
|
|
254
260
|
|
|
255
261
|
```bash
|
|
256
|
-
canon evidence audit cart.add.01 --project
|
|
262
|
+
canon evidence audit cart.add.01 --project root \
|
|
257
263
|
--ref "judge run 42" --role reviewer \
|
|
258
|
-
--evaluator
|
|
264
|
+
--evaluator judge --evaluator-version 1.2 \
|
|
259
265
|
--evaluator-digest 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 \
|
|
260
266
|
--audit-result refuted --report junit:audit/counterexample.xml
|
|
261
267
|
```
|
|
262
268
|
|
|
263
|
-
- `evidence audit` requires the scenario operand, `--ref`, `--evaluator
|
|
269
|
+
- `evidence audit` requires the scenario operand, `--ref`, `--evaluator`,
|
|
264
270
|
`--evaluator-version`, `--evaluator-digest` (sha256, 64 lowercase hex)
|
|
265
|
-
and `--audit-result confirmed|refuted|indeterminate`, with `--project
|
|
266
|
-
where several spec roots exist. It takes no `--task
|
|
271
|
+
and `--audit-result confirmed|refuted|indeterminate`, with `--project`
|
|
272
|
+
where several spec roots exist. It takes no `--task`, `--verdict`,
|
|
267
273
|
`--surface-ref` or `--approval-*`; the evaluator flags exist on no other
|
|
268
274
|
command. All refusals exit `2`.
|
|
269
275
|
- The record carries `audit: {evaluator_id, evaluator_version,
|
|
@@ -297,15 +303,15 @@ The approval is never assumed: the agent writes the brief, stops and
|
|
|
297
303
|
reports it, and builds nothing for that scope until the human answers.
|
|
298
304
|
`canon evidence add` is the backstop for that stop (0.16 M7). It
|
|
299
305
|
refuses (exit `1`, nothing staged or stored) while a subject the record
|
|
300
|
-
attests for has an enforced, unapproved brief: the
|
|
301
|
-
|
|
306
|
+
attests for has an enforced, unapproved brief: a change the record
|
|
307
|
+
answers to (below) has a canon `.canon/changes/<change>/brief.md` with no `Approved:`
|
|
302
308
|
line, was edited after its approval (`BRIEF_CHANGED_SINCE_APPROVAL`), or
|
|
303
309
|
there is no canon `brief.md` yet but the change comes from an
|
|
304
310
|
external openspec plan with a `proposal.md` under the plan sources (the
|
|
305
311
|
check `canon status` and the ship guard use; see
|
|
306
312
|
`canon-subject`; which changes a scenario answers to is scoped by its `@flow:<change>.<F-id>` tags, described there). The subjects are the scenario's `@subject` owner for
|
|
307
|
-
`--scenario
|
|
308
|
-
`--task
|
|
313
|
+
`--scenario`, and every subject adopting the task's change for
|
|
314
|
+
`--task`:
|
|
309
315
|
|
|
310
316
|
```stderr
|
|
311
317
|
canon evidence add: unreviewed-promotion demo-subject — evidence for world.demo.01: brief not approved — .canon/changes/c-demo/brief.md has no `Approved:` line, so the human has not answered it; once they do, record their words with `canon brief approve c-demo --approver <the human> --note "<their words>"`
|
|
@@ -335,7 +341,7 @@ brief_override:
|
|
|
335
341
|
reason: the human approved in chat; the line follows
|
|
336
342
|
waived:
|
|
337
343
|
- { class: unreviewed-promotion, subject: demo-subject }
|
|
338
|
-
actor: { agent_id: lead } # from --actor
|
|
344
|
+
actor: { agent_id: lead } # from --actor
|
|
339
345
|
```
|
|
340
346
|
|
|
341
347
|
Under `--json` the same waiver is `data.overrides[]` (`code` of the waived
|
|
@@ -370,8 +376,9 @@ review waivers: 1 advisory(ies) — not failing the gate:
|
|
|
370
376
|
The waiver lasts only until the subject's next status write.
|
|
371
377
|
|
|
372
378
|
`canon subject move <id> --to shipped` also refuses where a brief exists and
|
|
373
|
-
is not approved (the subject
|
|
374
|
-
|
|
379
|
+
is not approved (a change the subject answers for, that is one a scenario of
|
|
380
|
+
the subject is tagged `@flow:<change>.*` for, one with an `Approved:` line,
|
|
381
|
+
or a chore, has a canon
|
|
375
382
|
`brief.md` with no `Approved:` line or one the brief's text no longer
|
|
376
383
|
matches, or an external `proposal.md` and no canon `brief.md` yet;
|
|
377
384
|
see `canon-subject`), as an `unreviewed-promotion` naming
|
|
@@ -431,14 +438,14 @@ what backed the claim:
|
|
|
431
438
|
|
|
432
439
|
```bash
|
|
433
440
|
# any file: a Playwright trace, screenshots, an agent QA log — by sha256
|
|
434
|
-
canon evidence add --scenario
|
|
441
|
+
canon evidence add --scenario cart.add.04 --project root \
|
|
435
442
|
--class agent-qa --ref "stagehand run 7" --role implementer \
|
|
436
443
|
--artifact test-results/cart-trace.zip
|
|
437
444
|
# a JUnit XML or Cucumber JSON report: also records the matched case + outcome
|
|
438
|
-
canon evidence add --scenario
|
|
439
|
-
canon evidence add --scenario
|
|
445
|
+
canon evidence add --scenario cart.add.04 --project root --class test-run --ref "cargo nextest run" --role implementer --report junit:target/nextest/default/junit.xml
|
|
446
|
+
canon evidence add --scenario cart.add.04 --project root --class test-run --ref "cucumber-js" --role implementer --report cucumber:reports/cucumber.json
|
|
440
447
|
# a Swift Testing event stream (swift test --experimental-event-stream-output <path>)
|
|
441
|
-
canon evidence add --scenario
|
|
448
|
+
canon evidence add --scenario cart.add.04 --project root --class test-run --ref "swift test" --role implementer --report swift-testing:.build/events.jsonl
|
|
442
449
|
```
|
|
443
450
|
|
|
444
451
|
A case is bound when the scenario id is its OWN: the first
|
|
@@ -490,12 +497,12 @@ not close it.
|
|
|
490
497
|
One test run proves many scenarios. Bind it once:
|
|
491
498
|
|
|
492
499
|
```bash
|
|
493
|
-
canon evidence add --project
|
|
500
|
+
canon evidence add --project root --all-scenarios \
|
|
494
501
|
--report junit:target/nextest/default/junit.xml \
|
|
495
502
|
--class test-run --ref "cargo nextest run" --role implementer
|
|
496
503
|
```
|
|
497
504
|
|
|
498
|
-
Each indexed scenario of `--project
|
|
505
|
+
Each indexed scenario of `--project` that owns a case (the rule above)
|
|
499
506
|
gets its own record, with only its own cases. Its verdict comes from
|
|
500
507
|
them: `faithful` when every case passed, `divergent` when one failed,
|
|
501
508
|
`not-applicable` when one was skipped and none failed. `--verdict <v>`
|
|
@@ -515,18 +522,18 @@ It is all or nothing: a claimed `faithful` verdict over a failed case,
|
|
|
515
522
|
a fabrication marker in `--summary`, an unapproved brief for any
|
|
516
523
|
scenario's subject refuses the whole batch, and nothing is written. Each
|
|
517
524
|
record binds only what the batch names (nothing is carried forward).
|
|
518
|
-
`--scenario
|
|
525
|
+
`--scenario`, `--task`,
|
|
519
526
|
`--report-case`, `canon evidence audit` and the approval flags name one subject
|
|
520
527
|
and are refused with `--all-scenarios`.
|
|
521
528
|
|
|
522
|
-
A task's evidence with `--report` and no `--scenario
|
|
529
|
+
A task's evidence with `--report` and no `--scenario` binds EVERY case
|
|
523
530
|
in the report, so a `faithful` verdict needs all of them to pass.
|
|
524
531
|
|
|
525
532
|
Many records at once without a report: `--input` takes inline JSON, a file
|
|
526
533
|
or `-`; an array (or NDJSON) is a batch, validated element by element before
|
|
527
534
|
the first write (a refusal writes nothing, exit 2). Keys are the option
|
|
528
535
|
names in camelCase plus `operands`: one object per scenario, with
|
|
529
|
-
`
|
|
536
|
+
`scenario`, `class`, `ref` and `role`. `canon schema evidence add --json`
|
|
530
537
|
shows the input schema and an example. Each element reports `written`,
|
|
531
538
|
`unchanged` or `failed` in `data.items[]`.
|
|
532
539
|
|
|
@@ -546,7 +553,7 @@ current pinned review saw, `canon evidence add` prints one line per
|
|
|
546
553
|
review it makes stale (its verdict or checks differ from what the review saw), with the command that re-pins it:
|
|
547
554
|
|
|
548
555
|
```stderr
|
|
549
|
-
canon evidence add: review by `reviewer-2` of cart.add.01 is now stale (this record's verdict or checks differ from what it saw); re-pin it: canon review scenario cart.add.01 --project
|
|
556
|
+
canon evidence add: review by `reviewer-2` of cart.add.01 is now stale (this record's verdict or checks differ from what it saw); re-pin it: canon review scenario cart.add.01 --project root --actor reviewer-2 --role reviewer --original-spec-ref specs/kind=feature/area=cart/add.feature
|
|
550
557
|
```
|
|
551
558
|
|
|
552
559
|
The decision is the gate's own (the same stale-review rule `canon gate
|
|
@@ -678,7 +685,7 @@ task at all is a loud failure naming every source consulted. A repo with
|
|
|
678
685
|
no `.canon/changes/` and `sources: []` is refused: "this repo configures
|
|
679
686
|
no plan sources (no `.canon/changes` and no `plans.sources` entries in
|
|
680
687
|
canon.yaml) … write the change with `canon change new`, or list your
|
|
681
|
-
external plans under `plans.sources`" (`canon dispatch begin --task
|
|
688
|
+
external plans under `plans.sources`" (`canon dispatch begin --task` says the
|
|
682
689
|
same).
|
|
683
690
|
It requires
|
|
684
691
|
a matching non-`Divergent` evidence record, and flips `- [ ]` → `- [x]`
|
|
@@ -700,7 +707,7 @@ A flip on evidence that cannot prove the task still succeeds, but warns
|
|
|
700
707
|
on stderr: when none of the task's evidence records binds a file and one
|
|
701
708
|
of them cites a canon command as its `--ref` (`canon gate check`,
|
|
702
709
|
`canon status`), the warning says to bind the artifact or report that
|
|
703
|
-
proves the task (`canon evidence add --task
|
|
710
|
+
proves the task (`canon evidence add --task <id> --artifact <path>` or
|
|
704
711
|
`--report <format>:<path>`). A canon command reports on canon's own
|
|
705
712
|
records, so it is never the proof of a task.
|
|
706
713
|
|
|
@@ -773,6 +780,14 @@ canon gate install-hooks --repo .
|
|
|
773
780
|
canon gate install-hooks --repo . --event PreToolUse --matcher Edit --command "canon gate check" --timeout 30
|
|
774
781
|
```
|
|
775
782
|
|
|
783
|
+
It installs no git hook: copy the script into git's `pre-commit` hook
|
|
784
|
+
(`.git/hooks/pre-commit`) or call it from a hook runner. The output names the two
|
|
785
|
+
agent hook files and the script, also under `--dry-run`. In `--json`,
|
|
786
|
+
`installed` is true when an agent hook file changed and
|
|
787
|
+
`preCommitScriptWritten` when the script was written. A `--repo` that is not an
|
|
788
|
+
existing directory exits 2 with `HOOKS_INSTALL_FAILED` (also under `--dry-run`)
|
|
789
|
+
and creates nothing.
|
|
790
|
+
|
|
776
791
|
Prefer this over hand-editing `settings.json`/`hooks.json`.
|
|
777
792
|
|
|
778
793
|
## `canon selftest --suite trust-spine-gate`
|
|
@@ -183,9 +183,9 @@ record.
|
|
|
183
183
|
An operator-requested rollback is a distinct authenticated action:
|
|
184
184
|
|
|
185
185
|
```text
|
|
186
|
-
canon strategy rollback <strategy_id> --reason "<reason>" --actor
|
|
186
|
+
canon strategy rollback <strategy_id> --reason "<reason>" --actor alice \
|
|
187
187
|
--signature-file rollback.sig --approval-at 2026-10-02T12:00:00Z \
|
|
188
|
-
[--contradicting-trajectory
|
|
188
|
+
[--contradicting-trajectory <trajectory_id>] --repo .
|
|
189
189
|
```
|
|
190
190
|
|
|
191
191
|
`--signature-file` is an armored SSH detached signature over the
|
|
@@ -13,8 +13,8 @@ one, and neither can `canon gate`.
|
|
|
13
13
|
one `<slug>/` directory per change holding `brief.md` (and a `tasks.md`
|
|
14
14
|
only when someone adds one: an optional work note), written by
|
|
15
15
|
`canon change new` (see `canon-subject`). Every plan reader —
|
|
16
|
-
`canon ingest plans`, `canon task done`, `canon evidence add --task
|
|
17
|
-
`canon dispatch begin --task
|
|
16
|
+
`canon ingest plans`, `canon task done`, `canon evidence add --task`,
|
|
17
|
+
`canon dispatch begin --task`, `canon status` and the brief check — reads it
|
|
18
18
|
first whenever the directory exists, with no `plans:` entry. Being first,
|
|
19
19
|
it owns a change id an external source also carries (the external copy
|
|
20
20
|
is the later duplicate, skipped and counted under `duplicate_change_id`).
|
|
@@ -70,12 +70,12 @@ error; the next step (3) reads the overlay back.
|
|
|
70
70
|
## 3. Project a read
|
|
71
71
|
|
|
72
72
|
```bash
|
|
73
|
-
canon query --kind scenario --plugin
|
|
74
|
-
canon query --kind scenario --plugin
|
|
75
|
-
canon query --kind scenario # no --plugin
|
|
73
|
+
canon query --kind scenario --plugin porting # human table, projected fields appended
|
|
74
|
+
canon query --kind scenario --plugin porting --json # merged record bodies
|
|
75
|
+
canon query --kind scenario # no --plugin: byte-identical to the core view
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
`--plugin
|
|
78
|
+
`--plugin <id>` folds the plugin's overlay records (latest-by-
|
|
79
79
|
`(join_key, at)`) onto each queried core record. Fail-soft everywhere:
|
|
80
80
|
|
|
81
81
|
- No overlay record for a core key → that record projects UNMODIFIED (no
|
|
@@ -85,7 +85,7 @@ canon query --kind scenario # no --plugin-id: byte-ide
|
|
|
85
85
|
SKIPPED + diagnosed; siblings still project.
|
|
86
86
|
- An absent plugin/manifest → the unmodified core view + a diagnostic,
|
|
87
87
|
never a process error.
|
|
88
|
-
- Omitting `--plugin
|
|
88
|
+
- Omitting `--plugin` is byte-identical to `canon query`'s output without
|
|
89
89
|
plugins — it's a purely additive layer.
|
|
90
90
|
|
|
91
91
|
**Done when:** the projected table or JSON shows the plugin's fields on the
|
|
@@ -108,7 +108,7 @@ scenarios you synced.
|
|
|
108
108
|
(zero new files) and a genuine coverage edit supersedes the prior
|
|
109
109
|
overlay via latest-`at`-wins.
|
|
110
110
|
3. `canon plugin sync porting` writes/dedupes those candidates.
|
|
111
|
-
4. `canon query --kind scenario --plugin
|
|
111
|
+
4. `canon query --kind scenario --plugin porting [--json]` projects
|
|
112
112
|
`covered`/`surface_ref` back onto each scenario.
|
|
113
113
|
|
|
114
114
|
`canon gate check`'s verdicts are byte-identical with and without a
|
|
@@ -151,12 +151,16 @@ canon dashboard --snapshot /tmp/canon-snap --port 8080
|
|
|
151
151
|
`/briefs.html` lists every live change whose brief awaits the human (no
|
|
152
152
|
`Approved:` line, or edited since) with its intent, outcome, flow steps,
|
|
153
153
|
acceptance, questions and assumptions, and its `canon brief check`
|
|
154
|
-
blockers and advisories.
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
154
|
+
blockers and advisories. Each brief that has no blocker has a selection box
|
|
155
|
+
and the page shows how many are selected. The human types their name and their
|
|
156
|
+
answer once and clicks Approve: one request carries every selected brief with
|
|
157
|
+
the sha256 of the file the page read, and records exactly what `canon brief
|
|
158
|
+
approve <id>+ --approver <name> --note <text>` records, the `Approved:` line
|
|
159
|
+
bound to the brief digest and the policy approval, for each. A brief that
|
|
160
|
+
changed after the page loaded (`BRIEF_CHANGED_SINCE_PAGE_LOAD`) or that has
|
|
161
|
+
blockers refuses the whole request (409 `BRIEF_APPROVE_REFUSED`, naming each
|
|
162
|
+
refused brief): nothing is written and the page says to read it again. A request
|
|
163
|
+
naming one brief the old way (`changeId`, `sha256`) is still accepted. The server is localhost only and
|
|
160
164
|
refuses requests from other origins (`DASHBOARD_ORIGIN_REFUSED`).
|
|
161
165
|
|
|
162
166
|
For an agent the human stop is unchanged: when clean briefs are waiting,
|
|
@@ -182,7 +186,7 @@ In `canon report`'s own render order. Each panel names the view that
|
|
|
182
186
|
computes it; nothing here is derived a second time.
|
|
183
187
|
|
|
184
188
|
- **Trust matrix** (`mart_trust_matrix`) — Change/task coverage × green × who.
|
|
185
|
-
`covered` means at least one `
|
|
189
|
+
`covered` means at least one `evidence` record exists for this `task_id`,
|
|
186
190
|
NOT that policy's REQUIRED evidence is present — that is `canon gate
|
|
187
191
|
check`'s question, and this view deliberately does not answer it. `green`
|
|
188
192
|
is the plain `verdict = 'faithful'` proxy over the latest attestation, not
|
|
@@ -258,7 +262,7 @@ computes it; nothing here is derived a second time.
|
|
|
258
262
|
- **Review rounds** (`mart_review_rounds`) — one row per `(change_id, round)`
|
|
259
263
|
over `Finding` records (`canon finding add`, then `canon finding close` to
|
|
260
264
|
move a finding's disposition), folded to the latest version
|
|
261
|
-
of each `
|
|
265
|
+
of each `(change_id, round, seq)` finding first, so a finding raised
|
|
262
266
|
`open` and later closed is counted once and in one disposition bucket.
|
|
263
267
|
A round that found
|
|
264
268
|
nothing wrote no `Finding` and so has no row: the table
|