@journeykit/canon 0.27.0 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/skills/SKILL.src.md +245 -89
  2. package/dist/skills/reference/brief-align.md +4 -2
  3. package/dist/skills/reference/brief-clarify.md +7 -5
  4. package/dist/skills/reference/brief-harden.md +4 -2
  5. package/dist/skills/reference/brief-polish.md +7 -5
  6. package/dist/skills/reference/brief-shape.md +4 -2
  7. package/dist/skills/reference/canon-artifact-ingest.md +11 -7
  8. package/dist/skills/reference/canon-authoring.md +16 -2
  9. package/dist/skills/reference/canon-context.md +21 -11
  10. package/dist/skills/reference/canon-fmt.md +10 -2
  11. package/dist/skills/reference/canon-gate.md +107 -69
  12. package/dist/skills/reference/canon-inventory.md +23 -15
  13. package/dist/skills/reference/canon-learn.md +23 -19
  14. package/dist/skills/reference/canon-plan-import.md +10 -7
  15. package/dist/skills/reference/canon-plugins.md +15 -8
  16. package/dist/skills/reference/canon-policy.md +20 -16
  17. package/dist/skills/reference/canon-report-dashboard.md +30 -19
  18. package/dist/skills/reference/canon-retrieve.md +13 -10
  19. package/dist/skills/reference/canon-review.md +96 -68
  20. package/dist/skills/reference/canon-session-ingest.md +7 -3
  21. package/dist/skills/reference/canon-storage.md +65 -39
  22. package/dist/skills/reference/canon-subject.md +116 -79
  23. package/dist/skills/reference/canon-vocab.md +1 -1
  24. package/dist/skills/reference/role-implementer.md +295 -64
  25. package/dist/skills/reference/role-orchestrator.md +547 -55
  26. package/dist/skills/reference/role-planner.md +189 -32
  27. package/dist/skills/reference/role-reviewer.md +257 -58
  28. package/dist/skills/scripts/canon-retrieve-pre-dispatch.sh +10 -5
  29. package/man/canon-adapter-authorize.1 +44 -0
  30. package/man/canon-adapter-validate.1 +44 -0
  31. package/man/canon-adapter.1 +46 -0
  32. package/man/canon-artifacts-move.1 +63 -0
  33. package/man/canon-artifacts-store.1 +54 -0
  34. package/man/canon-artifacts-verify.1 +48 -0
  35. package/man/canon-artifacts.1 +45 -0
  36. package/man/canon-brief-approve.1 +62 -0
  37. package/man/canon-brief-check.1 +44 -0
  38. package/man/canon-brief-show.1 +50 -0
  39. package/man/canon-brief.1 +63 -0
  40. package/man/canon-change-new.1 +66 -0
  41. package/man/canon-change.1 +42 -0
  42. package/man/canon-completion.1 +60 -0
  43. package/man/canon-context-pack-add.1 +47 -0
  44. package/man/canon-context-pack-show.1 +44 -0
  45. package/man/canon-context-pack-verify.1 +44 -0
  46. package/man/canon-context-pack.1 +50 -0
  47. package/man/canon-context.1 +44 -0
  48. package/man/canon-dashboard.1 +50 -0
  49. package/man/canon-demo-init.1 +44 -0
  50. package/man/canon-demo-review.1 +44 -0
  51. package/man/canon-demo.1 +47 -0
  52. package/man/canon-dispatch-begin.1 +80 -0
  53. package/man/canon-dispatch-diff.1 +41 -0
  54. package/man/canon-dispatch-end.1 +60 -0
  55. package/man/canon-dispatch.1 +45 -0
  56. package/man/canon-divergence-accept.1 +68 -0
  57. package/man/canon-divergence-add.1 +97 -0
  58. package/man/canon-divergence-defer.1 +71 -0
  59. package/man/canon-divergence-list.1 +56 -0
  60. package/man/canon-divergence-resolve.1 +68 -0
  61. package/man/canon-divergence.1 +51 -0
  62. package/man/canon-evidence-add.1 +168 -0
  63. package/man/canon-evidence-approval-payload.1 +65 -0
  64. package/man/canon-evidence-audit.1 +121 -0
  65. package/man/canon-evidence.1 +57 -0
  66. package/man/canon-export.1 +108 -0
  67. package/man/canon-feature-new.1 +62 -0
  68. package/man/canon-feature.1 +39 -0
  69. package/man/canon-finding-add.1 +196 -0
  70. package/man/canon-finding-close.1 +117 -0
  71. package/man/canon-finding-list.1 +59 -0
  72. package/man/canon-finding.1 +67 -0
  73. package/man/canon-format.1 +49 -0
  74. package/man/canon-gate-check.1 +44 -0
  75. package/man/canon-gate-install-hooks.1 +59 -0
  76. package/man/canon-gate-promote.1 +62 -0
  77. package/man/canon-gate.1 +50 -0
  78. package/man/canon-ingest-plans.1 +53 -0
  79. package/man/canon-ingest-records.1 +56 -0
  80. package/man/canon-ingest-sessions.1 +62 -0
  81. package/man/canon-ingest.1 +50 -0
  82. package/man/canon-init.1 +98 -0
  83. package/man/canon-inventory-sync.1 +50 -0
  84. package/man/canon-inventory.1 +39 -0
  85. package/man/canon-ledger-compact.1 +50 -0
  86. package/man/canon-ledger.1 +54 -0
  87. package/man/canon-migrate.1 +89 -0
  88. package/man/canon-plugin-sync.1 +53 -0
  89. package/man/canon-plugin.1 +39 -0
  90. package/man/canon-policy-approve.1 +50 -0
  91. package/man/canon-policy-show.1 +41 -0
  92. package/man/canon-policy.1 +52 -0
  93. package/man/canon-prompt-add.1 +47 -0
  94. package/man/canon-prompt-show.1 +41 -0
  95. package/man/canon-prompt.1 +43 -0
  96. package/man/canon-purge.1 +70 -0
  97. package/man/canon-query.1 +111 -0
  98. package/man/canon-regime-show.1 +50 -0
  99. package/man/canon-regime.1 +39 -0
  100. package/man/canon-report-build.1 +44 -0
  101. package/man/canon-report-check.1 +41 -0
  102. package/man/canon-report-snapshot.1 +47 -0
  103. package/man/canon-report.1 +45 -0
  104. package/man/canon-retrieve.1 +56 -0
  105. package/man/canon-review-change.1 +98 -0
  106. package/man/canon-review-scenario.1 +98 -0
  107. package/man/canon-review.1 +42 -0
  108. package/man/canon-scenario-new.1 +80 -0
  109. package/man/canon-scenario.1 +39 -0
  110. package/man/canon-schema.1 +63 -0
  111. package/man/canon-selftest.1 +69 -0
  112. package/man/canon-skills-check.1 +47 -0
  113. package/man/canon-skills-doctor.1 +47 -0
  114. package/man/canon-skills-install.1 +53 -0
  115. package/man/canon-skills-show.1 +104 -0
  116. package/man/canon-skills.1 +48 -0
  117. package/man/canon-status.1 +51 -0
  118. package/man/canon-strategy-approval-payload.1 +53 -0
  119. package/man/canon-strategy-promote.1 +59 -0
  120. package/man/canon-strategy-rollback.1 +62 -0
  121. package/man/canon-strategy.1 +45 -0
  122. package/man/canon-subject-adopt.1 +53 -0
  123. package/man/canon-subject-move.1 +80 -0
  124. package/man/canon-subject-new.1 +65 -0
  125. package/man/canon-subject-show.1 +44 -0
  126. package/man/canon-subject-unadopt.1 +63 -0
  127. package/man/canon-subject.1 +51 -0
  128. package/man/canon-task-done.1 +47 -0
  129. package/man/canon-task.1 +42 -0
  130. package/man/canon-tier-age.1 +50 -0
  131. package/man/canon-tier.1 +39 -0
  132. package/man/canon.1 +169 -0
  133. package/package.json +9 -5
@@ -27,10 +27,10 @@ Every violation carries one of these stable, grep-able strings:
27
27
  | `stale-evidence` | A passing record degraded to stale: its declared surface changed since its `evidence_sha`, or HEAD moved past `staleness.max_commits_behind`. Only degrades an already-green record. Also: a file bound to a latest evidence record whose bytes are gone — no intact blob in `.canon/artifacts/sha256/` and no working-tree copy with the recorded digest — or a file bound to an in-effect review with no intact blob (see Bound evidence stays provable below). |
28
28
  | `malformed-evidence` | A candidate record doesn't parse, is misfiled, or carries an unparseable interim tag. Malformed evidence is no evidence. |
29
29
  | `flagged` | The human-only `flagged` overlay is set — never green regardless of passing evidence. |
30
- | `unevidenced-flip` | `canon gate task <task_id>` was asked to flip a checkbox with no matching, non-`Divergent` evidence record. |
31
- | `fabricated-evidence` | An evidence note contains a blocklisted marker (`"would pass"`, `"TBD"`, `"n/a"`) standing as a whole word — never inside a path, a file name, a URL or a longer word, so `pack.json/atlas` is not `n/a` — or a bare `verified` claim with no attached command result. `canon evidence add` refuses such a note before writing (`canon evidence add: refused — fabricated-evidence …`, exit 1). |
30
+ | `unevidenced-flip` | `canon task done <task_id>` was asked to flip a checkbox with no matching, non-`Divergent` evidence record. |
31
+ | `fabricated-evidence` | An evidence note contains a blocklisted marker (`"would pass"`, `"TBD"`, `"n/a"`) standing as a whole word — never inside a path, a file name, a URL or a longer word, so `pack.json/atlas` is not `n/a` — or a bare `verified` claim with no attached command result. `canon evidence add` refuses such a note before writing (refused with `fabricated-evidence`, exit 1). |
32
32
  | `open-blocker` | With `spec_coverage.require_review` set (and `block_on_findings`, the default), a Finding whose latest version is severity `blocker`, disposition `open`, on a change an in-scope subject adopted — or closed `fixed` while an evidenced scenario of the subject has no evidence recorded after the close (re-verification). Subject string `<change_id>#<round>.<seq>`. See `canon-review`. |
33
- | `false-success` | The latest audit record (`canon evidence add --kind audit`) of a scenario says `refuted`: an external evaluator found a counterexample to the claimed success. Always on, regardless of policy or sampling, and takes precedence over any declared faithful verdict; only a newer audit (`confirmed` or `indeterminate`) clears it. The detail names the evaluator, its version, its sha256 and the counterexample paths. |
33
+ | `false-success` | The latest audit record (`canon evidence audit`) of a scenario says `refuted`: an external evaluator found a counterexample to the claimed success. Always on, regardless of policy or sampling, and takes precedence over any declared faithful verdict; only a newer audit (`confirmed` or `indeterminate`) clears it. The detail names the evaluator, its version, its sha256 and the counterexample paths. |
34
34
 
35
35
  ## `canon gate check [--repo <dir>] [--release]`
36
36
 
@@ -53,17 +53,27 @@ repo ROOT's `.canon/policy.yaml` and `.canon/ledger` from any subdirectory.
53
53
 
54
54
  When `.canon/policy.yaml` exists but has no approval, the gate prints
55
55
  `advisory: policy not approved: …` after its result, naming
56
- `canon policy approve --by <who>`; the exit code is unchanged. When its
56
+ `canon policy approve --approver <who>`; the exit code is unchanged. When its
57
57
  bytes no longer match the approved digest, or the approval cannot be read,
58
58
  the gate fails closed: the violation is reported and the exit is `1` (see
59
59
  `canon-policy`).
60
60
 
61
+ On a repository that still holds 0.27 canon state, `canon gate check` (like
62
+ `canon status` and `canon context`) warns and puts `canon migrate --json`
63
+ first in `meta.next`: run `canon migrate` (a preview), then `canon migrate
64
+ --commit --plan-digest <digest from the preview>`, then `canon skills
65
+ install`. Read the whole result with `--json`: `data.violations` lists the
66
+ failures by class and `meta.next` the steps.
67
+
68
+ **Done when:** `canon gate check` exits `0` with no violation; `canon status`
69
+ repeats the result and names what is still open.
70
+
61
71
  The gate is a read command: it writes nothing. A scenario index that is
62
72
  stale (a `.feature` file added, edited or deleted since the last sync) is
63
73
  graded as the refresh would leave it, built in memory from the changed
64
74
  files with the code `canon inventory sync` runs; the index on disk is
65
75
  brought up to date by the next command that writes (`canon evidence add`,
66
- `canon review add`, `canon subject status`) or by `canon inventory sync`.
76
+ `canon review scenario`, `canon subject move`) or by `canon inventory sync`.
67
77
  It prints no refresh line.
68
78
 
69
79
  A root that fails to sync (format violations, a duplicate id) cannot be
@@ -119,11 +129,11 @@ A present section, even `require_evidence: false` or a malformed one
119
129
 
120
130
  - **Unimplemented** — no `EvidenceRecord` carries the scenario's
121
131
  `(project_id, scenario_id)`. Author one with
122
- `canon evidence add --scenario-id <id> --project-id <root-id>`; both
123
- flags are required together, because two spec roots may carry the same
124
- scenario id. `--summary` is allowed here too (scanned for fabrication
132
+ `canon evidence add --scenario-id <id> --project-id <root-id>`; the
133
+ root id is needed once more than one spec root is configured, because
134
+ two roots may carry the same scenario id. `--summary` is allowed here too (scanned for fabrication
125
135
  markers like a task's); it is a row suffix only when the record also
126
- names a `--task`. A record carrying both `--task` and `--scenario-id`
136
+ names a `--task-id`. A record carrying both `--task-id` and `--scenario-id`
127
137
  is one attestation answering both joins: it counts for the task cell
128
138
  and for the scenario cell (verdicts, the shipped gate, the review gate).
129
139
  - **Mismatched** — the folded divergence state is `open`,
@@ -141,12 +151,12 @@ A present section, even `require_evidence: false` or a malformed one
141
151
  case). This is the gap evidence presence cannot see: every scenario
142
152
  attested, none of them specifying a refusal. Untagged scenarios satisfy
143
153
  no case, so an unclassified corpus is reported, not passed. Works with
144
- `require_evidence: false` too. `canon subject status <id> --to shipped`
154
+ `require_evidence: false` too. `canon subject move <id> --to shipped`
145
155
  applies the same rule to the scenarios the subject owns.
146
156
  - **Independent review** (`require_review`) — scenarios whose subject is
147
157
  in `require_review.scope` (default `[verifying, shipped]`; `[]` = every
148
158
  scenario; independent of `scope` above) need a `Review` record
149
- (`canon review add`) whose latest version per reviewer is `signed`,
159
+ (`canon review scenario`) whose latest version per reviewer is `signed`,
150
160
  still matches the scenario digest and latest evidence it pinned
151
161
  (a review written before 0.15 has no pins and skips this check), and,
152
162
  when `distinct_actor` (default `true`), is by a reviewer and actor
@@ -171,7 +181,7 @@ A present section, even `require_evidence: false` or a malformed one
171
181
  - **Sampled audits** (`require_audit`) — a deterministic sample of
172
182
  in-scope scenarios (`require_audit.scope`, default `[verifying,
173
183
  shipped]`; `exclude_lanes` applies) must carry an external audit
174
- (`canon evidence add --kind audit`, see Audit records below). A sampled
184
+ (`canon evidence audit`, see Audit records below). A sampled
175
185
  scenario whose latest audit is missing or `indeterminate` is
176
186
  `uncovered-cell`:
177
187
 
@@ -202,11 +212,13 @@ purpose, so enabling nothing changes no existing verdict.
202
212
  ### Accepted divergence and re-verification
203
213
 
204
214
  ```bash
205
- canon divergence accept --project-id <root-id> --scenario-id <id> --reason "<why>" --tracking <issue-url-or-ref> [--expiry YYYY-MM-DD] --reviewer <me> --actor-id <me> --session-id <session> --as reviewer
215
+ canon divergence accept cart.add.01 --project-id root --reason "known gap" --tracking "issue#12" --expiry 2026-12-31 --actor-id reviewer-2 --role reviewer --session-id review-session-1
206
216
  ```
207
217
 
208
- A reviewer accepts a scenario whose latest evidence is `divergent` as a
209
- known gap limited by something outside the change; never to skip a fix.
218
+ Accepting a scenario whose latest evidence is `divergent` as a known gap
219
+ limited by something outside the change is a human-only act: with a role
220
+ declared (`--as`, `CANON_ROLE`) the leaf is refused with `HUMAN_ONLY`. It is
221
+ never a way to skip a fix.
210
222
  Refused (`DIVERGENCE_ACCEPT_REFUSED`) unless the latest verdict is
211
223
  divergent and the session and actor differ from the evidence's. The record
212
224
  pins that evidence: new evidence for the scenario, or `--expiry` passing,
@@ -224,36 +236,36 @@ from shipping until every one of its evidenced scenarios has evidence
224
236
  recorded after the close or the approval. A blocker that names its
225
237
  scenarios (`finding add --scenario-id`) asks only those, and the refusal
226
238
  names them with the per-scenario command (`canon evidence add --project-id
227
- <root-id> --scenario-id <id> --report <format>:<path> …`). Otherwise the
239
+ <root-id> --scenario-id <id> --report <format>:<path>` plus `--class`, `--role` and `--ref`). Otherwise the
228
240
  refusal names the scenarios and the batch command: `canon evidence add --project-id <root-id>
229
- --all-scenarios --report <format>:<path> --kind test-run --role
230
- implementer --ref "<test command>" …`. Reviews pin what the evidence says
241
+ --all-scenarios --report <format>:<path> --class test-run --role
242
+ implementer --ref "<test command>"`. Reviews pin what the evidence says
231
243
  (its verdict and the identity of its checks), not which record it is, so
232
244
  recording the suite again with the same verdicts from the same cases leaves
233
245
  every scenario review current. A chore instead needs one change-level
234
- review of the chore itself (`canon review add --change-id <slug> …`) before
246
+ review of the chore itself (`canon review change <slug>`) before
235
247
  `--to shipped`; a changed verdict or case set stales that scenario's
236
248
  review as before (and a new `divergence accept`, where the gap remains).
237
249
 
238
- ### Audit records (`--kind audit`)
250
+ ### Audit records (`canon evidence audit`)
239
251
 
240
252
  canon never generates or runs an audit. An external evaluator does, and
241
253
  canon records its result:
242
254
 
243
255
  ```bash
244
- canon evidence add --kind audit --project-id root --scenario-id cart.add.01 \
256
+ canon evidence audit cart.add.01 --project-id root \
245
257
  --ref "judge run 42" --role reviewer \
246
258
  --evaluator-id judge --evaluator-version 1.2 \
247
- --evaluator-digest <64 lowercase hex sha256> \
259
+ --evaluator-digest 9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08 \
248
260
  --audit-result refuted --report junit:audit/counterexample.xml
249
261
  ```
250
262
 
251
- - `--kind audit` requires `--evaluator-id`, `--evaluator-version`,
252
- `--evaluator-digest` (sha256, 64 lowercase hex), `--audit-result
253
- confirmed|refuted|indeterminate`, and `--scenario-id` with
254
- `--project-id`. It refuses `--task`, `--verdict`, `--surface-ref` and
255
- `--approval-*`; the four evaluator flags are refused on any other kind.
256
- All refusals exit `2`.
263
+ - `evidence audit` requires the scenario operand, `--ref`, `--evaluator-id`,
264
+ `--evaluator-version`, `--evaluator-digest` (sha256, 64 lowercase hex)
265
+ and `--audit-result confirmed|refuted|indeterminate`, with `--project-id`
266
+ where several spec roots exist. It takes no `--task-id`, `--verdict`,
267
+ `--surface-ref` or `--approval-*`; the evaluator flags exist on no other
268
+ command. All refusals exit `2`.
257
269
  - The record carries `audit: {evaluator_id, evaluator_version,
258
270
  evaluator_digest, result}`; its verdict is derived (`confirmed` →
259
271
  faithful, `refuted` → divergent, `indeterminate` → not-applicable).
@@ -263,10 +275,10 @@ canon evidence add --kind audit --project-id root --scenario-id cart.add.01 \
263
275
  - Audits fold apart: per `(project_id, scenario_id)` there is a latest
264
276
  declared record and a latest audit. An audit never becomes the
265
277
  scenario's latest declared verdict.
266
- - `canon subject status <id> --to shipped` refuses `false-success`, and an
278
+ - `canon subject move <id> --to shipped` refuses `false-success`, and an
267
279
  owed sampled audit when `require_audit.scope` covers `shipped`.
268
280
  - `canon status` shows an `audits` section (sampled / confirmed / owed /
269
- refuted) and suggests `canon evidence add --kind audit …` in `next:`.
281
+ refuted) and suggests `canon evidence audit` in `next:`.
270
282
 
271
283
  ### A record binds what its own write names
272
284
 
@@ -275,7 +287,7 @@ canon evidence add --kind audit --project-id root --scenario-id cart.add.01 \
275
287
  from an earlier record, in a single add or in a suite batch
276
288
  (`--all-scenarios`), and no drop is recorded: history keeps the earlier
277
289
  records, and a new record is reviewed on its own files. An audit
278
- (`--kind audit`) replaces a refutation the same way, so a counterexample
290
+ (`canon evidence audit`) replaces a refutation the same way, so a counterexample
279
291
  never rides along into a confirming audit. `--drop-attachment` and
280
292
  `--drop-reason` no longer exist.
281
293
 
@@ -293,11 +305,11 @@ external openspec plan with a `proposal.md` under the plan sources (the
293
305
  check `canon status` and the ship guard use; see
294
306
  `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
295
307
  `--scenario-id`, and every subject adopting the task's change for
296
- `--task`:
308
+ `--task-id`:
297
309
 
298
- ```
299
- 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 --change-id c-demo --by <the human> --note "<their words>"`
300
- canon evidence add: refused — stop, report the brief to the human and wait for their answer: nothing is built or attested for a subject before its brief is approved. Record their answer with `canon brief approve --by <the human> --note "<their words>"` only from that answer; to attest anyway, pass --override-reason <text>, which is recorded on the evidence record
310
+ ```stderr
311
+ 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>"`
312
+ canon evidence add: refused — stop, report the brief to the human and wait for their answer: nothing is built or attested for a subject before its brief is approved. Record their answer with `canon brief approve --approver <the human> --note "<their words>"` only from that answer; to attest anyway, pass --override-reason <text>, which is recorded on the evidence record
301
313
  ```
302
314
 
303
315
  For a change from an external plan with no canon brief yet, the first
@@ -307,13 +319,13 @@ openspec/changes/c-ext/proposal.md, which canon reads and never edits, so
307
319
  its approval lives in that canon file, so the human has not answered it;
308
320
  once they do, create .canon/changes/c-ext/brief.md holding a `Source:
309
321
  openspec/changes/c-ext/proposal.md` line, then record their words with
310
- `canon brief approve --change-id c-ext --by <the human> --note "<their words>"` ``. An `Approved:` line in the
322
+ `canon brief approve c-ext --approver <the human> --note "<their words>"` ``. An `Approved:` line in the
311
323
  external `proposal.md` itself is never read.
312
324
 
313
325
  A subject with no brief to answer (no adopted change, or a newest change
314
326
  with neither a canon `brief.md` nor an external `proposal.md`) and a
315
327
  scenario no subject owns are unaffected.
316
- `canon review add` and `canon finding add` are never refused.
328
+ `canon review scenario` and `canon finding add` are never refused.
317
329
  `--override-reason "<one line>"` attests anyway, prints the `waived …`
318
330
  lines and `override recorded by `<actor>` for the N brief refusal(s)
319
331
  above: <reason>`, and records on the evidence record:
@@ -326,6 +338,12 @@ brief_override:
326
338
  actor: { agent_id: lead } # from --actor-id
327
339
  ```
328
340
 
341
+ Under `--json` the same waiver is `data.overrides[]` (`code` of the waived
342
+ refusal, `reason` verbatim), so a caller sees what its `--override-reason`
343
+ let through; a repeat of an identical record is `unchanged`
344
+ (`meta.unchanged`) and records no second override. `--override-reason`
345
+ exists on `subject move` too (see `canon-subject`).
346
+
329
347
  A blank or multi-line reason exits 2; an override when nothing refused is
330
348
  not recorded. `canon status` lists each such record as a `warning:`, and
331
349
  `canon gate check` prints them after the result without failing:
@@ -337,7 +355,7 @@ brief overrides: 1 evidence record(s) attested before their brief was approved
337
355
 
338
356
  ### Review-waiver advisories
339
357
 
340
- A subject moved into a review-scoped status with `canon subject status <id> --to <state>
358
+ A subject moved into a review-scoped status with `canon subject move <id> --to <state>
341
359
  --override-reason` (see `canon-subject`) keeps the `unreviewed-promotion`
342
360
  and `open-blocker` gaps its waiver recorded visible without failing the
343
361
  gate. Only those exact `(class, subject)` pairs are waived; a gap that
@@ -351,7 +369,7 @@ review waivers: 1 advisory(ies) — not failing the gate:
351
369
 
352
370
  The waiver lasts only until the subject's next status write.
353
371
 
354
- `canon subject status <id> --to shipped` also refuses where a brief exists and
372
+ `canon subject move <id> --to shipped` also refuses where a brief exists and
355
373
  is not approved (the subject's scope, its newest adopted change walking back past pending drafts
356
374
  no scenario is tagged `@flow:<change>.*` for, has a canon
357
375
  `brief.md` with no `Approved:` line or one the brief's text no longer
@@ -414,13 +432,13 @@ what backed the claim:
414
432
  ```bash
415
433
  # any file: a Playwright trace, screenshots, an agent QA log — by sha256
416
434
  canon evidence add --scenario-id cart.add.04 --project-id root \
417
- --kind agent-qa --ref "stagehand run 7" --role implementer \
435
+ --class agent-qa --ref "stagehand run 7" --role implementer \
418
436
  --artifact test-results/cart-trace.zip
419
437
  # a JUnit XML or Cucumber JSON report: also records the matched case + outcome
420
- canon evidence add ... --report junit:target/nextest/default/junit.xml
421
- canon evidence add ... --report cucumber:reports/cucumber.json
438
+ canon evidence add --scenario-id cart.add.04 --project-id root --class test-run --ref "cargo nextest run" --role implementer --report junit:target/nextest/default/junit.xml
439
+ canon evidence add --scenario-id cart.add.04 --project-id root --class test-run --ref "cucumber-js" --role implementer --report cucumber:reports/cucumber.json
422
440
  # a Swift Testing event stream (swift test --experimental-event-stream-output <path>)
423
- canon evidence add ... --report swift-testing:.build/events.jsonl
441
+ canon evidence add --scenario-id cart.add.04 --project-id root --class test-run --ref "swift test" --role implementer --report swift-testing:.build/events.jsonl
424
442
  ```
425
443
 
426
444
  A case is bound when the scenario id is its OWN: the first
@@ -474,7 +492,7 @@ One test run proves many scenarios. Bind it once:
474
492
  ```bash
475
493
  canon evidence add --project-id root --all-scenarios \
476
494
  --report junit:target/nextest/default/junit.xml \
477
- --kind test-run --ref "cargo nextest run" --role implementer
495
+ --class test-run --ref "cargo nextest run" --role implementer
478
496
  ```
479
497
 
480
498
  Each indexed scenario of `--project-id` that owns a case (the rule above)
@@ -497,30 +515,50 @@ It is all or nothing: a claimed `faithful` verdict over a failed case,
497
515
  a fabrication marker in `--summary`, an unapproved brief for any
498
516
  scenario's subject refuses the whole batch, and nothing is written. Each
499
517
  record binds only what the batch names (nothing is carried forward).
500
- `--scenario-id`, `--task`,
501
- `--report-case`, `--kind audit` and the approval flags name one subject
518
+ `--scenario-id`, `--task-id`,
519
+ `--report-case`, `canon evidence audit` and the approval flags name one subject
502
520
  and are refused with `--all-scenarios`.
503
521
 
504
522
  A task's evidence with `--report` and no `--scenario-id` binds EVERY case
505
523
  in the report, so a `faithful` verdict needs all of them to pass.
506
524
 
525
+ Many records at once without a report: `--input` takes inline JSON, a file
526
+ or `-`; an array (or NDJSON) is a batch, validated element by element before
527
+ the first write (a refusal writes nothing, exit 2). Keys are the option
528
+ names in camelCase plus `operands`: one object per scenario, with
529
+ `scenarioId`, `class`, `ref` and `role`. `canon schema evidence add --json`
530
+ shows the input schema and an example. Each element reports `written`,
531
+ `unchanged` or `failed` in `data.items[]`.
532
+
533
+ `--rev <rev>` names the commit the evidence ran against (default `HEAD`).
534
+ Evidence for uncommitted code is recorded with its `codeTree` and
535
+ `worktreeDirty`; outside git, or with no commit, the add is refused with
536
+ `NO_COMMIT`.
537
+
538
+ **Done when:** `canon gate check` shows no violation for the scenarios you
539
+ recorded evidence for; each record's own output line says whether it was
540
+ written or `unchanged`.
541
+
507
542
  ### A write that makes a review stale says so (0.18)
508
543
 
509
544
  When new evidence (one record or a batch) supersedes the evidence a
510
545
  current pinned review saw, `canon evidence add` prints one line per
511
546
  review it makes stale (its verdict or checks differ from what the review saw), with the command that re-pins it:
512
547
 
513
- ```
514
- 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 add --project-id root --scenario-id cart.add.01 --reviewer reviewer-2 --actor-id reviewer-2 --role reviewer --pin <HEAD sha> --original-spec-ref specs/kind=feature/area=cart/add.feature
548
+ ```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-id root --actor-id reviewer-2 --role reviewer --original-spec-ref specs/kind=feature/area=cart/add.feature
515
550
  ```
516
551
 
517
552
  The decision is the gate's own (the same stale-review rule `canon gate
518
553
  check` reports). The command repeats the review's reviewer, actor, role,
519
- session, provenance ref, runtime labels and artifacts, pinned at `HEAD` (`<sha>`
520
- when the repository has no commit). A record that is only staged says
554
+ session, provenance ref, runtime labels and artifacts, at the default
555
+ `--rev` (`HEAD`). A record that is only staged says
521
556
  the review "goes stale once this evidence is promoted": promote first,
522
- then re-pin. The reviewer re-reviews before re-pinning; several
523
- scenarios re-pin in one `canon review add` (see `canon-review`).
557
+ then re-review. The reviewer re-reviews before re-pinning; several
558
+ scenarios re-review in one `canon review scenario` (see `canon-review`).
559
+
560
+ **Done when:** `canon gate check` reports no stale review for the scenarios
561
+ you recorded evidence for; the re-review's own output says `pinned`.
524
562
 
525
563
  ## Bound evidence stays provable (the artifact store)
526
564
 
@@ -534,11 +572,11 @@ raise the limit with `--max-artifact-mib <N>`.
534
572
  Where those bytes live is `canon.yaml`'s `artifact_store: { backend: local |
535
573
  <s3 tier>, prefix: artifacts/ }` (default `local`: the directory above,
536
574
  git-tracked, no credentials). With an object-store tier, `evidence add`,
537
- `review add` and `evidence vault` upload each blob under
575
+ `review scenario` and `artifacts store` upload each blob under
538
576
  `<prefix>sha256/<digest>` and keep nothing locally. `canon gate check` and
539
577
  `canon artifacts verify [--full]` ask the store (a HEAD per digest; `--full`
540
578
  downloads and re-hashes) and refuse, never pass, when it cannot be reached.
541
- `canon artifacts migrate --to <tier> [--dry-run]` moves an existing local
579
+ `canon artifacts move --tier <tier>` (a preview; `--commit --plan-digest` acts) moves an existing local
542
580
  store; it is the repo owner's decision. See `canon-storage`.
543
581
 
544
582
  `canon gate check` re-checks every file bound to a LATEST evidence record
@@ -548,11 +586,11 @@ store; it is the repo owner's decision. See `canon-storage`.
548
586
  after the working-tree file is rewritten (a smoke script that rewrites
549
587
  `reports/smoke.json` on every run no longer orphans the record);
550
588
  - no blob, but the working-tree path still hashes to the recorded digest
551
- → clean, with an advisory naming `canon evidence vault` (records from
589
+ → clean, with an advisory naming `canon artifacts store` (records from
552
590
  before the store existed):
553
591
 
554
592
  ```
555
- evidence artifacts: 1 bound file(s) not in the artifact store — not failing the gate; run `canon evidence vault` to store them before the working tree changes:
593
+ evidence artifacts: 1 bound file(s) not in the artifact store — not failing the gate; run `canon artifacts store` to store them before the working tree changes:
556
594
  unstored cart.add.01 reports/junit.xml (sha256 b7cb…) is verified against the working tree only
557
595
  ```
558
596
  - anything else → `stale-evidence` naming the path, the recorded digest,
@@ -568,7 +606,7 @@ subject's status, and a repo with no `spec_coverage` would otherwise never
568
606
  have its bindings checked. A superseded record is not checked —
569
607
  re-attesting is the fix.
570
608
 
571
- Files bound to a review (`canon review add --artifact`, see
609
+ Files bound to a review (`canon review scenario --artifact`, see
572
610
  `canon-review`) are checked by the same rule for every CURRENT in-effect
573
611
  review: the latest per `(project_id, scenario_id, reviewer)`, less any
574
612
  that went stale against its scenario (its spec or evidence pin moved). A stale review is
@@ -585,7 +623,7 @@ Anything else is `stale-evidence` on the review's scenario, and the
585
623
  detail names the review: ``review by `<reviewer>` (actor `<id>`,
586
624
  <time>)``.
587
625
 
588
- `canon evidence vault [--max-artifact-mib <N>]` stores the bytes for
626
+ `canon artifacts store [--max-artifact-mib <N>]` stores the bytes for
589
627
  existing evidence records and current reviews (a superseded review's files are not vaulted): every attachment whose
590
628
  working-tree file still matches its digest is copied in, and everything
591
629
  else is listed as not stored, with both digests. It exits `0` whenever it
@@ -621,7 +659,7 @@ Malformed `risk_tiers` sections produce a stable `uncovered-cell` policy
621
659
  violation (`risk_tiers policy-invalid: ...`) instead of degrading to an
622
660
  empty clean map.
623
661
 
624
- ## `canon gate task <task_id> [--repo <dir>]`
662
+ ## `canon task done <task_id> [--repo <dir>]`
625
663
 
626
664
  For imported external plans, and for a `tasks.md` that already exists in
627
665
  a canon change. `canon change new` writes no `tasks.md` (0.19), and
@@ -640,7 +678,7 @@ task at all is a loud failure naming every source consulted. A repo with
640
678
  no `.canon/changes/` and `sources: []` is refused: "this repo configures
641
679
  no plan sources (no `.canon/changes` and no `plans.sources` entries in
642
680
  canon.yaml) … write the change with `canon change new`, or list your
643
- external plans under `plans.sources`" (`canon dispatch --task` says the
681
+ external plans under `plans.sources`" (`canon dispatch begin --task-id` says the
644
682
  same).
645
683
  It requires
646
684
  a matching non-`Divergent` evidence record, and flips `- [ ]` → `- [x]`
@@ -654,7 +692,7 @@ exits `1` with the blocking violation on stderr. After a flip, the plan
654
692
  source is re-ingested so the record store's task status agrees with the
655
693
  checkbox (`canon query --kind task` reads `done`); a failed re-ingest is
656
694
  a stderr warning naming `canon ingest plans`, never a failed flip.
657
- The success line is `canon gate task: <task_id> flipped — written
695
+ The success line is `canon task done: <task_id> flipped — written
658
696
  directly; nothing to promote`. An already-`[x]` row is an idempotent no-op (exit `0`). An unknown
659
697
  `task_id` is reported (exit `1`).
660
698
 
@@ -662,19 +700,19 @@ A flip on evidence that cannot prove the task still succeeds, but warns
662
700
  on stderr: when none of the task's evidence records binds a file and one
663
701
  of them cites a canon command as its `--ref` (`canon gate check`,
664
702
  `canon status`), the warning says to bind the artifact or report that
665
- proves the task (`canon evidence add --task <id> --artifact <path>` or
703
+ proves the task (`canon evidence add --task-id <id> --artifact <path>` or
666
704
  `--report <format>:<path>`). A canon command reports on canon's own
667
705
  records, so it is never the proof of a task.
668
706
 
669
707
  ```bash
670
- canon gate task my-change#5.2 --repo .
708
+ canon task done my-change#5.2 --repo .
671
709
  ```
672
710
 
673
711
  This is canon's own authority for the checkbox grammar — always flip
674
- through `canon gate task`, never by hand.
712
+ through `canon task done`, never by hand.
675
713
 
676
714
  Canon only reads external plans, with this one exception: for a task
677
- from an external plan source, `canon gate task` flips the checkbox in
715
+ from an external plan source, `canon task done` flips the checkbox in
678
716
  that plan's own `tasks.md` (or plan document). It is the one place canon
679
717
  writes into an external plan; their briefs and approvals still live in
680
718
  `.canon/changes/<change>/brief.md`. (Open for the maintainer: record
@@ -711,8 +749,8 @@ commits everything staged. It stays safe to run anyway: with nothing
711
749
  staged it prints
712
750
  `nothing staged` and exits `0`. `divergence add` stages for `canon
713
751
  gate promote` and names it, under the same `write:` rule. Every
714
- other write — `review add`, `subject new|adopt|status`, `change new`, `scenario new`, `feature new`,
715
- `gate task` (it edits the plan document and re-ingests it)
752
+ other write — `review scenario`, `subject new|adopt|move`, `change new`, `scenario new`, `feature new`,
753
+ `task done` (it edits the plan document and re-ingests it)
716
754
  — is final when it returns, and its success line ends `— written
717
755
  directly; nothing to promote`. Full promote-on-write contract:
718
756
  `canon-storage` (Staged writes and promotion). `divergence resolve|defer|accept` stage and promote their own record in the same run and end `— staged and promoted in this run; nothing to promote`.
@@ -737,7 +775,7 @@ canon gate install-hooks --repo . --event PreToolUse --matcher Edit --command "c
737
775
 
738
776
  Prefer this over hand-editing `settings.json`/`hooks.json`.
739
777
 
740
- ## `canon gate selftest`
778
+ ## `canon selftest --suite trust-spine-gate`
741
779
 
742
780
  Runs the shipped fixture corpus — one fixture per failure class (ten,
743
781
  including `false-success`), each a
@@ -747,7 +785,7 @@ deliberately broken corpus proving that class fires and ONLY that class
747
785
  check` run's green.
748
786
 
749
787
  ```bash
750
- canon gate selftest
788
+ canon selftest --suite trust-spine-gate
751
789
  ```
752
790
 
753
791
  ## Reading a violation
@@ -7,13 +7,14 @@ records every downstream stage joins against.
7
7
  ## You rarely run it yourself
8
8
 
9
9
  Since 0.16 the commands that read the index see added, edited and deleted
10
- `.feature` files without a sync step. `canon evidence add`, `canon review
11
- add` and `canon subject status` refresh the index on disk first, with the
10
+ `.feature` files without a sync step. `canon evidence add`, `canon evidence
11
+ audit`, `canon artifacts store`, `canon divergence accept`, `canon review
12
+ scenario` and `canon subject move` refresh the index on disk first, with the
12
13
  same code this command runs, scoped to the changed files, and say so in one
13
14
  stderr line:
14
15
 
15
- ```
16
- canon evidence add: refreshed the scenario index from 1 changed feature file(s) (.canon/specs/kind=feature/area=cart/add.feature): 1 record(s) written
16
+ ```stderr
17
+ canon artifacts store: refreshed the scenario index from 1 changed feature file(s) (.canon/specs/kind=feature/area=cart/add.feature): 1 record(s) written
17
18
  ```
18
19
 
19
20
  `canon status` and `canon gate check` are read commands and write nothing:
@@ -44,8 +45,8 @@ not the index already holds its scenarios, `shipped` is refused, and
44
45
  fix it; run `canon migrate`, which moves `features/kind=feature/` to
45
46
  `<root>/kind=feature/`.
46
47
 
47
- `canon migrate --dry-run` prints the plan without writing anything, and
48
- `canon migrate` applies it. Commit first: it refuses while a path it
48
+ `canon migrate` prints the plan without writing anything, and
49
+ `canon migrate --commit --plan-digest <digest>` applies it. Commit first: it refuses while a path it
49
50
  moves has uncommitted changes, and when a destination already exists.
50
51
  A root at the repo-level `specs` moves to `.canon/specs`, and
51
52
  `canon.yaml` records `former_roots: [specs]`, so reviews pinned before
@@ -68,19 +69,19 @@ kept an old index gets it rewritten on the first read.
68
69
 
69
70
  ## Where the index sits in the loop
70
71
 
71
- ```
72
+ ```text
72
73
  author .feature corpus (canon scenario new)
73
74
  │
74
75
  ▼
75
76
  scenario index # refreshed by the writers; `canon inventory sync` rebuilds it
76
77
  │
77
78
  ▼
78
- canon review add # attests a review — see canon-inventory downstream / canon-gate
79
- canon divergence {add,promote,resolve,defer,accept,status} # tracks/resolves a divergence
79
+ canon review scenario # attests a review — see canon-inventory downstream / canon-gate
80
+ canon divergence add|resolve|defer|accept|list # tracks/resolves a divergence
80
81
  canon gate check [--release] # trust-ladder / staleness / coverage — see canon-gate
81
82
  │
82
83
  ▼
83
- canon ingest artifacts # with artifacts.native_records: true in canon.yaml —
84
+ canon ingest records # with artifacts.native_records: true in canon.yaml —
84
85
  # feeds review/divergence verdicts into the flywheel
85
86
  # (see canon-artifact-ingest)
86
87
  ```
@@ -98,7 +99,7 @@ canon inventory sync --spec-root ./specs # ad hoc: ignore canon.yaml entirely
98
99
 
99
100
  Per configured root, in order:
100
101
 
101
- 1. **Validate** — runs `canon format --check` over the root. ANY violation
102
+ 1. **Validate** — runs `canon format` over the root. ANY violation
102
103
  (missing provenance, layout-grammar, …) ABORTS THE WHOLE ROOT: zero
103
104
  records written for it, the violation(s) reported. Never a partial sync.
104
105
  2. **Scan** — walks `<root>/kind=feature/area=<area>/<surface>.feature`, pairing each
@@ -124,6 +125,13 @@ The scenario index shape is deliberately general: `title` +
124
125
  `source_digest`, nothing else. It carries no coverage field — coverage
125
126
  stays `canon gate check`'s own authority (see `canon-gate`).
126
127
 
128
+ `--dry-run` runs the same validation and reports what would be written
129
+ without writing. A rerun that finds every digest unchanged writes nothing.
130
+
131
+ **Done when:** `canon inventory sync` exits `0` with no violation or sync
132
+ error for the root, and `canon query --kind scenario` lists the scenarios;
133
+ `canon status` then reads the index without a `NOT refreshed` line.
134
+
127
135
  ## `specs.roots[]` config (`canon.yaml`)
128
136
 
129
137
  ```yaml
@@ -149,7 +157,7 @@ specs:
149
157
 
150
158
  ## Sync-abort causes
151
159
 
152
- - **A `canon format --check` validation violation** in the root's corpus →
160
+ - **A `canon format` validation violation** in the root's corpus →
153
161
  whole root aborts, 0 writes, violations reported.
154
162
  - **A root on the pre-0.17 layout** (a `.feature` file under
155
163
  `<root>/features/`) → a `layout-grammar` violation at path `features`;
@@ -160,12 +168,12 @@ specs:
160
168
 
161
169
  ## How the index feeds the rest
162
170
 
163
- - **Review** — `canon review add` attests a verdict against a synced
171
+ - **Review** — `canon review scenario` attests a verdict against a synced
164
172
  scenario. (See `canon-inventory` downstream commands and each command's `--help`.)
165
- - **Divergence** — `canon divergence {add,promote,resolve,defer,accept,status}`
173
+ - **Divergence** — `canon divergence add|resolve|defer|accept|list`
166
174
  tracks/resolves divergences against synced scenarios.
167
175
  - **Gate** — `canon gate check` enforces trust-ladder / staleness /
168
176
  coverage over the corpus (see `canon-gate`).
169
- - **Ingest** — `canon ingest artifacts` with `artifacts.native_records:
177
+ - **Ingest** — `canon ingest records` with `artifacts.native_records:
170
178
  true` in `canon.yaml` feeds review/divergence verdicts into the
171
179
  reward flywheel (see `canon-artifact-ingest`).