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