@journeykit/canon 0.37.0 → 0.39.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 (119) hide show
  1. package/dist/skills/SKILL.src.md +29 -13
  2. package/dist/skills/reference/canon-artifact-ingest.md +0 -2
  3. package/dist/skills/reference/canon-gate.md +56 -2
  4. package/dist/skills/reference/canon-report-dashboard.md +27 -36
  5. package/dist/skills/reference/canon-review.md +10 -1
  6. package/dist/skills/reference/canon-storage.md +54 -4
  7. package/dist/skills/reference/role-implementer.md +6 -5
  8. package/dist/skills/reference/role-orchestrator.md +28 -23
  9. package/dist/skills/reference/role-planner.md +3 -3
  10. package/dist/skills/reference/role-reviewer.md +6 -3
  11. package/man/canon-adapter-authorize.1 +2 -2
  12. package/man/canon-adapter-validate.1 +2 -2
  13. package/man/canon-adapter.1 +2 -2
  14. package/man/canon-artifacts-move.1 +2 -2
  15. package/man/canon-artifacts-prune.1 +77 -0
  16. package/man/canon-artifacts-store.1 +2 -2
  17. package/man/canon-artifacts-verify.1 +4 -2
  18. package/man/canon-artifacts.1 +5 -2
  19. package/man/canon-brief-approve.1 +2 -2
  20. package/man/canon-brief-check.1 +2 -2
  21. package/man/canon-brief-show.1 +2 -2
  22. package/man/canon-brief.1 +2 -2
  23. package/man/canon-change-new.1 +2 -2
  24. package/man/canon-change.1 +2 -2
  25. package/man/canon-completion.1 +2 -2
  26. package/man/canon-context-pack-add.1 +2 -2
  27. package/man/canon-context-pack-show.1 +2 -2
  28. package/man/canon-context-pack-verify.1 +2 -2
  29. package/man/canon-context-pack.1 +2 -2
  30. package/man/canon-context.1 +2 -2
  31. package/man/canon-dashboard.1 +2 -2
  32. package/man/canon-demo-init.1 +2 -2
  33. package/man/canon-demo-review.1 +2 -2
  34. package/man/canon-demo.1 +2 -2
  35. package/man/canon-dispatch-begin.1 +3 -3
  36. package/man/canon-dispatch-diff.1 +2 -2
  37. package/man/canon-dispatch-end.1 +2 -2
  38. package/man/canon-dispatch.1 +2 -2
  39. package/man/canon-divergence-accept.1 +2 -2
  40. package/man/canon-divergence-add.1 +2 -2
  41. package/man/canon-divergence-defer.1 +2 -2
  42. package/man/canon-divergence-list.1 +2 -2
  43. package/man/canon-divergence-resolve.1 +2 -2
  44. package/man/canon-divergence.1 +2 -2
  45. package/man/canon-evidence-add.1 +3 -3
  46. package/man/canon-evidence-approval-payload.1 +2 -2
  47. package/man/canon-evidence-audit.1 +3 -3
  48. package/man/canon-evidence.1 +2 -2
  49. package/man/canon-export.1 +2 -6
  50. package/man/canon-feature-new.1 +2 -2
  51. package/man/canon-feature.1 +2 -2
  52. package/man/canon-finding-add.1 +2 -2
  53. package/man/canon-finding-close.1 +4 -4
  54. package/man/canon-finding-list.1 +3 -3
  55. package/man/canon-finding.1 +2 -2
  56. package/man/canon-format.1 +2 -2
  57. package/man/canon-gate-check.1 +2 -2
  58. package/man/canon-gate-install-hooks.1 +2 -2
  59. package/man/canon-gate-promote.1 +2 -2
  60. package/man/canon-gate.1 +2 -2
  61. package/man/canon-ingest-plans.1 +2 -2
  62. package/man/canon-ingest-records.1 +2 -2
  63. package/man/canon-ingest.1 +4 -8
  64. package/man/canon-init.1 +28 -10
  65. package/man/canon-inventory-sync.1 +2 -2
  66. package/man/canon-inventory.1 +2 -2
  67. package/man/canon-ledger-compact.1 +2 -2
  68. package/man/canon-ledger.1 +2 -2
  69. package/man/canon-migrate.1 +2 -2
  70. package/man/canon-plugin-sync.1 +2 -2
  71. package/man/canon-plugin.1 +2 -2
  72. package/man/canon-policy-approve.1 +2 -2
  73. package/man/canon-policy-show.1 +2 -2
  74. package/man/canon-policy.1 +2 -2
  75. package/man/canon-prompt-add.1 +2 -2
  76. package/man/canon-prompt-show.1 +2 -2
  77. package/man/canon-prompt.1 +2 -2
  78. package/man/canon-purge.1 +8 -8
  79. package/man/canon-query.1 +2 -6
  80. package/man/canon-regime-show.1 +2 -2
  81. package/man/canon-regime.1 +2 -2
  82. package/man/canon-report-build.1 +2 -2
  83. package/man/canon-report-check.1 +2 -2
  84. package/man/canon-report-snapshot.1 +2 -2
  85. package/man/canon-report.1 +2 -2
  86. package/man/canon-retrieve.1 +2 -2
  87. package/man/canon-review-change.1 +2 -2
  88. package/man/canon-review-scenario.1 +2 -2
  89. package/man/canon-review.1 +2 -2
  90. package/man/canon-scenario-new.1 +2 -2
  91. package/man/canon-scenario.1 +2 -2
  92. package/man/canon-schema.1 +2 -2
  93. package/man/canon-search.1 +2 -6
  94. package/man/canon-selftest.1 +2 -4
  95. package/man/canon-skills-check.1 +22 -5
  96. package/man/canon-skills-doctor.1 +24 -7
  97. package/man/canon-skills-install.1 +22 -5
  98. package/man/canon-skills-show.1 +2 -4
  99. package/man/canon-skills.1 +3 -3
  100. package/man/canon-status.1 +2 -2
  101. package/man/canon-strategy-approval-payload.1 +2 -2
  102. package/man/canon-strategy-promote.1 +2 -2
  103. package/man/canon-strategy-rollback.1 +3 -3
  104. package/man/canon-strategy.1 +2 -2
  105. package/man/canon-subject-adopt.1 +2 -2
  106. package/man/canon-subject-move.1 +2 -2
  107. package/man/canon-subject-new.1 +2 -2
  108. package/man/canon-subject-show.1 +2 -2
  109. package/man/canon-subject-unadopt.1 +2 -2
  110. package/man/canon-subject.1 +2 -2
  111. package/man/canon-task-done.1 +2 -2
  112. package/man/canon-task.1 +2 -2
  113. package/man/canon-tier-age.1 +2 -2
  114. package/man/canon-tier.1 +2 -2
  115. package/man/canon-trace.1 +4 -4
  116. package/man/canon.1 +5 -5
  117. package/package.json +4 -4
  118. package/dist/skills/reference/canon-session-ingest.md +0 -224
  119. package/man/canon-ingest-sessions.1 +0 -62
@@ -160,7 +160,21 @@ an object-store tier, in which case `evidence add`, `review scenario`, `review c
160
160
  `canon artifacts verify` (`--full` re-hashes every blob) ask the store and
161
161
  refuse, never pass, when it cannot be reached. Moving an existing store with
162
162
  `canon artifacts move --tier <tier>` is the repo owner's decision, not a step
163
- of the loop.
163
+ of the loop. So is `canon artifacts prune`, which deletes the blobs no record
164
+ binds any more (the store only grows: a report written anew on every run adds a
165
+ blob per run). A blob stays while the latest evidence or a current review binds
166
+ it (what the gate and `artifacts verify` read), while a record not promoted yet
167
+ binds it, and, with `--keep-days N`, while any evidence or review of the last
168
+ `N` days binds it; the bare run previews the blobs it deletes and why the rest
169
+ stay, and `--commit --plan-digest` deletes. A deleted local blob stays in git
170
+ history (shrinking that history is the repo owner's call, not the command's); a
171
+ deleted object of an object-store tier is gone for good. The preview and the
172
+ commit also cover the stale temp files a killed blob write leaves in
173
+ `.canon/artifacts/sha256` (`.tmp-<sha256>-<pid>-<nanos>`, a regular file
174
+ modified over five minutes ago): the plan lists them in `data.staleTemps`, and
175
+ `artifacts verify` only counts them (it deletes nothing and its exit does not
176
+ change). A temp file is no finished blob, so deleting it changes no record; one
177
+ that git already tracks must be taken out of the commit.
164
178
 
165
179
  ### Search and trace
166
180
 
@@ -215,8 +229,11 @@ A role is guidance, not enforcement: `--role` on `evidence add` and
215
229
  your complete command set, every option of every leaf included. Run `canon schema <command> --json` only for a
216
230
  command it does not list, or after a `USAGE` refusal (read `error.field`
217
231
  and `error.expected` first). `canon schema --json` is the tree of every group and command
218
- with its `effect` and `x-canon.roles` (`--as <role>` lists one role's, and `x-canon.as` names it);
219
- its `options` define once the options that two or more commands share (`--repo`, `--as`, `--actor`, …)
232
+ with its `effect` and `x-canon.roles` (`--as <role>` lists one role's, and `x-canon.as` names it).
233
+ `x-canon.roles` is the string `all` for a command all four roles use, else an array of
234
+ role names (empty: only a human runs it), so read it as `roles == "all"` or a name in the array;
235
+ the root's `x-canon.rolesForm` says so once. The tree's
236
+ `options` define once the options that two or more commands share (`--repo`, `--as`, `--actor`, …)
220
237
  and a command names them. `canon schema <group> --json` lists a group's
221
238
  commands; `canon schema <command> --json` is the call surface of one command and nothing
222
239
  else: `options` (each name of a tree option, or an object with `valueType`, a typed
@@ -316,9 +333,9 @@ leaves below take one object only.
316
333
 
317
334
  ### Preview, then `--commit`
318
335
 
319
- The five commands that delete or rewrite existing data (`canon purge`,
336
+ The six commands that delete or rewrite existing data (`canon purge`,
320
337
  `canon tier age`, `canon ledger compact`, `canon artifacts move`,
321
- `canon migrate`) act in two steps. The bare run previews: it writes nothing,
338
+ `canon artifacts prune`, `canon migrate`) act in two steps. The bare run previews: it writes nothing,
322
339
  exits 0 and prints the effects and a `planDigest`. Read the effects, then act
323
340
  with `--commit --plan-digest <planDigest>`. It refuses (`PLAN_STALE`) when
324
341
  the plan differs from the one you previewed, so run the preview again. Appends
@@ -327,7 +344,7 @@ preview helps elsewhere (`init`, `skills install`, `export`, `inventory sync`,
327
344
  `subject adopt`, …) `--dry-run` validates fully and writes nothing.
328
345
 
329
346
  ```bash
330
- canon purge --kind session --before 2026-01-01
347
+ canon purge --kind run --before 2026-01-01
331
348
  ```
332
349
 
333
350
  ## Upgrading a repo from 0.27
@@ -353,15 +370,15 @@ and `canon context` warn when the repo holds 0.27-era state and put
353
370
  ```bash
354
371
  # canon.yaml, starter policy (--policy light|standard|strict, default strict; see canon-policy), AGENTS.md block, commented plans examples
355
372
  canon init
356
- # harnesses for the canon skill; without it init takes the detected .claude/.codex/.omp/.pi (it never asks)
357
- canon init --providers=claude,codex
373
+ # harnesses for the canon skill, one --harness each (--no-harness for none); without them init takes the detected .claude/.codex/.omp/.pi (it never asks)
374
+ canon init --harness claude --harness codex
358
375
  # follows canon.yaml skills.providers (else the install lock's, else the detected ones; none detected installs nothing); prunes projected files the bundle no longer ships when their bytes match the lock, keeps a modified one and reports `kept:`
359
376
  canon skills install
360
- # any subset or none; rewrites skills.providers
361
- canon skills install --providers=claude,codex,omp,pi
377
+ # any subset; rewrites skills.providers (--no-harness records none)
378
+ canon skills install --harness claude --harness codex --harness omp --harness pi
362
379
  # read-only drift check; exit 1 (SKILLS_CHECK_FAILED) names each orphan, a projected file the bundle no longer ships
363
380
  canon skills check
364
- # diagnostics, incl. a stray canon projection for an unselected provider and a projection a formatter rewrote, and `orphan:` lines for projected files the bundle no longer ships; never deletes user files
381
+ # diagnostics, incl. a stray canon projection for an unselected harness and a projection a formatter rewrote, and `orphan:` lines for projected files the bundle no longer ships; never deletes user files
365
382
  canon skills doctor
366
383
  ```
367
384
 
@@ -372,7 +389,7 @@ Claude gets `.claude/skills/canon/`, Codex `.agents/skills/canon/`, OMP
372
389
  `.omp/skills/canon/`, Pi `.pi/skills/canon/` (the retrieve script is a sidecar,
373
390
  not an installed hook). `check` reports a stub written by another canon
374
391
  version; `install` rewrites it. The harness list lives in `canon.yaml` as
375
- `skills: { providers: [...] }`; change it with `canon skills install --providers=<list>`,
392
+ `skills: { providers: [...] }`; change it with `canon skills install --harness <name>` once for each name (or `--no-harness`),
376
393
  never by assuming a default.
377
394
 
378
395
  `install` and `doctor` end with `owned-paths:`, the globs of every path
@@ -430,7 +447,6 @@ current step needs.
430
447
  | `canon-gate` | Evidence, gates, task checkboxes, hooks. |
431
448
  | `canon-review` | Findings and reviews. |
432
449
  | `canon-artifact-ingest` | `canon ingest records`: artifacts into verdict trajectories. |
433
- | `canon-session-ingest` | `canon ingest sessions`: agent transcripts into session records. |
434
450
  | `canon-plan-import` | `canon ingest plans`: plan state into change and task records. |
435
451
  | `canon-storage` | Storage rungs, tiers, retention, export, purge. |
436
452
  | `canon-policy` | The policy and the CEL expressions behind it. |
@@ -71,8 +71,6 @@ promotion/demotion.
71
71
 
72
72
  ## What this skill does NOT cover
73
73
 
74
- - Session/cost ingestion (`canon ingest sessions`) — a different
75
- pipeline; see the `canon-session-ingest` skill.
76
74
  - Strategy promotion/demotion mechanics — see the `canon-learn` skill;
77
75
  this skill only produces the verdict evidence promotion reads.
78
76
  - The `regime_key` grammar itself — see `canon-retrieve`, which derives
@@ -24,7 +24,7 @@ Every violation carries one of these stable, grep-able strings:
24
24
  | `uncovered-cell` | Either a policy-required evidence cell (role × artifact) with no matching record, or — with `spec_coverage` enabled — a spec scenario that is unimplemented or mismatched, or a feature surface missing a `require_cases` case. The detail string distinguishes them. Coverage means "a test exists", not "a test passed": even a `Divergent` verdict satisfies the role-cell form. At `verifying → shipped`, a `Divergent` latest verdict is `uncovered-cell` unless a reviewer accepted it (see Accepted divergence below), and a chore's approval, like a blocker closed `fixed`, needs every evidenced scenario evidenced again afterwards (see Re-verification below). |
25
25
  | `unreviewed-promotion` | An artifact tagged `reviewed` has no matching ledger review record — or, with `spec_coverage.require_review` set, an in-scope scenario has no qualifying `Review`: none at all, only self-reviews, only stale reviews (the spec or evidence it pinned changed since), or only `indeterminate`/`unavailable` ones. Also, subject `policy`: the policy changed since its approval or its approval is unreadable (fails closed; see `canon-policy`). See `canon-review`. |
26
26
  | `trust-below-required` | Achieved trust level is below `policy.yaml`'s `trust_required` for its class — RELEASE-scoped only (`canon gate check --release`); never fires on an ordinary run. |
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). |
27
+ | `stale-evidence` | A passing record degraded to stale: a path that changed since its `evidence_sha` matches its declared surface (`--surface-ref`, a path pattern read from the repository root; the detail names the declarations and paths that matched), 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
30
  | `unevidenced-flip` | `canon task done <task_id>` was asked to flip a checkbox with no matching, non-`Divergent` evidence record. |
@@ -266,6 +266,32 @@ approval needs a new review, and so does a review of other code, as when the
266
266
  same brief is approved again over code that came after the review. An approval
267
267
  with no recorded tree (written before 0.37) follows the rule above.
268
268
 
269
+ A policy may narrow what a chore asks for with `code_scopes` (0.38): a key is
270
+ a scenario id's area (`core`) or surface (`app.bulkread`), the value a list of
271
+ path patterns written like `code.exclude`; the surface key wins over the area
272
+ key, and a scenario with neither has no scope. For a scenario with a scope the
273
+ chore compares the code tree of its latest evidence with the tree now, and asks
274
+ for new evidence only when a changed path (added, modified, deleted, a rename
275
+ by its old and its new path) matches the scope; the refusal names the first
276
+ three such paths and how many there are. No scope, no recorded tree, or an old
277
+ tree that cannot be computed (the commit is gone, the evidence was recorded over
278
+ uncommitted code) keep the rule above. The scopes stand only while the policy
279
+ is the one a human approved: an agent cannot widen them (an edit after the
280
+ approval fails closed, and so does a change that a brief approval would have
281
+ approved implicitly), and `status` and
282
+ `gate check` warn, never refuse, about a pattern that matches no file or a key
283
+ that matches no scenario. A shared file (lock file, build setting, fixture)
284
+ belongs in the scope of every scenario that depends on it.
285
+ A key none of whose patterns matches a file of the current code tree declares no
286
+ scope (a misspelt `Core/**` never exempts; matching is byte-exact), and an empty
287
+ list is malformed, so that scenario follows the rule above; both are warned.
288
+ `canon brief approve` records the policy approval in its own call except when
289
+ the policy's `code_scopes` differs from the last approved policy's: then it
290
+ approves the brief only, leaves the policy approval stale (the gate fails closed
291
+ until a human reads the scopes and runs `canon policy approve`) and names the
292
+ changed keys, so an agent cannot widen the scopes by asking for a brief's
293
+ approval.
294
+
269
295
  ### Audit records (`canon evidence audit`)
270
296
 
271
297
  canon never generates or runs an audit. An external evaluator does, and
@@ -599,7 +625,11 @@ git-tracked, no credentials). With an object-store tier, `evidence add`,
599
625
  `canon artifacts verify [--full]` ask the store (a HEAD per digest; `--full`
600
626
  downloads and re-hashes) and refuse, never pass, when it cannot be reached.
601
627
  `canon artifacts move --tier <tier>` (a preview; `--commit --plan-digest` acts) moves an existing local
602
- store; it is the repo owner's decision. See `canon-storage`.
628
+ store; it is the repo owner's decision. `canon artifacts prune` (a preview;
629
+ `--commit --plan-digest` acts) deletes the blobs no record binds any more and
630
+ leaves what `gate check` and `artifacts verify` read, so their answers do not
631
+ change (it also deletes the stale `.tmp-` files a killed blob write left, which
632
+ `artifacts verify` counts without deleting); it is the repo owner's decision too. See `canon-storage`.
603
633
 
604
634
  `canon gate check` re-checks every file bound to a LATEST evidence record
605
635
  (the latest per task and per `(project_id, scenario_id)`):
@@ -669,6 +699,30 @@ binding. This is still attestation input, not proof of the changed paths;
669
699
  run/diff metadata is authoritative when available, and an unavailable
670
700
  binding is a gate violation rather than a clean result.
671
701
 
702
+ A `--surface-ref` that is not `effect:...` is a path pattern read from the
703
+ repository root with the glob of `code.exclude`: `*` and `?` do not cross
704
+ `/`, `**` does, a directory matches everything below it, and a trailing `/`
705
+ is dropped. `src/`, `src`, `src/**` and `src/*.rs` all go `stale-evidence`
706
+ when `src/a.rs` changes; for `src/x/b.rs` the first three do and `src/*.rs`
707
+ does not. A name with no `/` is the file at the root: `Cargo.toml` is
708
+ the root manifest, not every crate's. A value identical to a changed path
709
+ matches it, and `effect:` is never compared with paths. A value that
710
+ matches no file of the work tree is recorded all the same, with a
711
+ `SURFACE_REF_UNMATCHED` warning. The `paths` of a risk tier keep their
712
+ older reading (`*` crosses `/`) until the next release that breaks
713
+ compatibility.
714
+
715
+ When git cannot read the base commit of a passing cell, `canon gate check`
716
+ prints one `staleness_unresolvable` advisory and `canon status` one
717
+ `STALENESS_UNRESOLVABLE` warning, with the same sentence: how many
718
+ (subject, role) cells, how many for each reason (`base_missing`: the commit
719
+ is not in this repository, as in a shallow clone or after `git gc
720
+ --prune=now`; `base_not_ancestor`: it is not an ancestor of HEAD, as after
721
+ a squash merge; `git_unavailable`: git did not answer), the first three
722
+ subjects, and `git fetch --unshallow` in a shallow clone. Verdicts and the
723
+ exit status do not change: a `base_missing` or `git_unavailable` cell adds
724
+ nothing, a `base_not_ancestor` cell is judged from `<base>..HEAD`.
725
+
672
726
  Approval identity is separate from attestation text. An approval counts
673
727
  only when it carries a detached SSH signature (`ssh-keygen -Y sign -n
674
728
  canon-approval-v1` over `canon evidence approval-payload`'s bytes) that
@@ -1,9 +1,9 @@
1
1
  # canon-report-dashboard
2
2
 
3
- canon's single status surface: `canon report build` renders TEN panels to
4
- markdown, `canon report snapshot` exports the same ten marts to
3
+ canon's single status surface: `canon report build` renders NINE panels to
4
+ markdown, `canon report snapshot` exports the same nine marts to
5
5
  Parquet, and `canon dashboard` serves a small zero-network web app that
6
- renders SEVEN of them from such a snapshot. Neither surface computes an
6
+ renders SIX of them from such a snapshot. Neither surface computes an
7
7
  aggregate itself — both read canon's precomputed
8
8
  `crates/canon-store/sql/views.sql` marts, and each run reads the corpus
9
9
  ONCE (`crates/canon-report/src/query.rs`'s `PIN_CORPUS_SQL`), so no two
@@ -35,7 +35,7 @@ drift-checked.
35
35
 
36
36
  ## `canon report build [--repo <dir>]`
37
37
 
38
- Renders the current ten-panel report to `<repo>/.canon/REPORT.md`.
38
+ Renders the current nine-panel report to `<repo>/.canon/REPORT.md`.
39
39
  `--repo` resolves through the nearest-`canon.yaml`-ancestor walk every
40
40
  subcommand uses — omit it (or pass `.`) to run from any subdirectory.
41
41
 
@@ -82,7 +82,7 @@ and commit the result.
82
82
 
83
83
  ## `canon report snapshot <dir>`
84
84
 
85
- Exports all ten views to `<dir>/<table>.parquet` plus a
85
+ Exports all nine views to `<dir>/<table>.parquet` plus a
86
86
  `<dir>/manifest.json`. One explicit `COPY` per view — the exported
87
87
  columns are each view's own `SELECT` list, wider than the curated column
88
88
  subset the markdown tables render. `file` is always
@@ -98,7 +98,6 @@ existing consumer's order never moves:
98
98
  "source_digest": "...",
99
99
  "tables": [
100
100
  { "table": "mart_trust_matrix", "file": "mart_trust_matrix.parquet" },
101
- { "table": "mart_session_costs", "file": "mart_session_costs.parquet" },
102
101
  { "table": "mart_role_memory", "file": "mart_role_memory.parquet" },
103
102
  { "table": "mart_flywheel_funnel", "file": "mart_flywheel_funnel.parquet" },
104
103
  { "table": "mart_review_burndown", "file": "mart_review_burndown.parquet" },
@@ -174,7 +173,7 @@ human's explicit answer, with `--relayed-via`. The page lists the approvals an
174
173
  agent recorded for the human under "Approved through an agent" (`relayed` in
175
174
  `GET /api/briefs`), with the role, actor and tool of each.
176
175
 
177
- The dashboard renders SEVEN panels — trust matrix, session costs, role
176
+ The dashboard renders SIX panels — trust matrix, role
178
177
  memory, flywheel funnel, review burn-down, review rounds, review totals.
179
178
  **Scope status
180
179
  and subjects are exported to the snapshot but have no dashboard panel**;
@@ -186,7 +185,7 @@ The dashboard's freshness banner shows the snapshot's
186
185
  snapshot, not necessarily the live checkout" note — treat "matches
187
186
  `canon report`" as "matches the inputs that produced THIS snapshot".
188
187
 
189
- ## Reading the ten panels
188
+ ## Reading the nine panels
190
189
 
191
190
  In `canon report`'s own render order. Each panel names the view that
192
191
  computes it; nothing here is derived a second time.
@@ -202,17 +201,6 @@ computes it; nothing here is derived a second time.
202
201
  version; `green` and `who` are read off one whole winner row, so they can
203
202
  never come from two different attestations.
204
203
 
205
- - **Session costs** (`mart_session_costs`) — token/cost per
206
- `(session, client, role, workspace_label)`. Every `run`/`session`/
207
- `token_usage` record is folded to its latest version first, so
208
- a re-ingested corrected cost REPLACES the superseded figure instead of being summed with it.
209
- `workspace_label` is NOT a repo identity: it is the last non-empty path
210
- segment of the `token_usage` event's workspace key and nothing more, so it
211
- SPLITS one repo whose worktrees sit in differently-named directories and
212
- MERGES two different repos sharing a directory name. Two stronger fields
213
- exist and this mart reads neither — the event's own `workspace_key`, and
214
- `Session.project_key`, which `canon-cli` stamps to the main worktree's key.
215
-
216
204
  - **Role memory** (`mart_role_memory`) — per-`(role, regime_key)` strategy
217
205
  counts. `hit_rate` is NOT a retrieval hit rate: it is the fraction of that
218
206
  namespace's distilled strategies carrying no `demotion` flag, i.e.
@@ -355,25 +343,28 @@ computes it; nothing here is derived a second time.
355
343
  a row is one change's review history, and `findings` moves with how
356
344
  much reviewing happened rather than with the change.
357
345
 
358
- Two marts in `views.sql` are NOT report panels and are not exported by
359
- `--snapshot`: `mart_records_by_kind` and `mart_session_run_handoff`.
360
- Read them with DuckDB directly against `views.sql`.
346
+ One mart in `views.sql` is NOT a report panel and is not exported by
347
+ `--snapshot`: `mart_records_by_kind`. It counts records per stored kind, so
348
+ rows of the retired `session`/`event` kinds that remain in a store still show
349
+ there until `canon purge` deletes them. Read it with DuckDB directly against
350
+ `views.sql`.
361
351
 
362
352
  - **Run observability** (`mart_run_observability`) — one row per folded
363
- `run_id`, appended as the tenth report/snapshot table after the established
364
- nine tables. It reports lifecycle identifiers/status/timestamps, latency
365
- only when both timestamps exist, event and label counts, child-run count,
366
- guidance count, lineage provider/model, and token/cost source totals. These
367
- are bounded observations and proxies: event counts do not infer tool calls,
368
- retries, or human interventions, and no field claims guidance caused an
369
- outcome. `directive_event_count` and `guidance_count` are counts only;
370
- directive and guidance text is never emitted. `*_unknown` columns explicitly
371
- expose missing joins/coverage, including missing session/project/task/lineage,
372
- end timestamps, event times, costs, and guidance. Workspace absolute paths
373
- and verbatim directives/guidance are intentionally omitted. The adapter
374
- contract is strict read-only validation; this panel does not execute
375
- adapters or enforce provider sandbox capabilities. Privacy-safe omission of
376
- paths and directive/guidance text is part of the current semantics.
353
+ `run_id`, the ninth and last report/snapshot table after the established
354
+ eight tables. It reports lifecycle identifiers/status/timestamps, latency
355
+ only when both timestamps exist, child-run count, guidance count, and
356
+ lineage provider/model, all read from the `Run` record alone. These are
357
+ bounded observations and proxies: no field claims guidance caused an
358
+ outcome. `guidance_count` is a count only; guidance text is never emitted.
359
+ `*_unknown` columns explicitly expose missing values, including missing
360
+ session/project/task/parent-run lineage, end timestamps, provider/model and
361
+ guidance; a `Run` stored without `project_key` reads `project_key_unknown`.
362
+ There are no cost, token or event columns: canon has no cost or token
363
+ report and no replacement for it. Workspace absolute paths and verbatim
364
+ guidance are intentionally omitted. The adapter contract is strict
365
+ read-only validation; this panel does not execute adapters or enforce
366
+ provider sandbox capabilities. Privacy-safe omission of paths and guidance
367
+ text is part of the current semantics.
377
368
 
378
369
  ## What this skill does NOT cover
379
370
 
@@ -88,6 +88,15 @@ on the closing version, shown by `finding list` as `[reason: …]` and carried
88
88
  in the JSON. Give the reason when you reject or defer: it is the only record
89
89
  of why the finding was not fixed.
90
90
 
91
+ Closing `rejected` or `deferred` overturns the judgement of whoever raised
92
+ the finding, so it is the reviewer's: a call that declares another role
93
+ (`--as` or `CANON_ROLE`: planner, implementer, orchestrator) is refused
94
+ with `FINDING_ROLE_DENIED`, nothing is written and the finding stays open.
95
+ `fixed` is closed by every role. The closing version records the role the
96
+ call declared (`--role` is accepted only when it names that role, or when
97
+ none is declared) and no role when none was; `finding list` names who
98
+ closed each closed finding and under which role (`closedBy`, `closedRole`).
99
+
91
100
  `--scenario` (repeatable, each a scenario the index knows; refused with
92
101
  `SCENARIO_NOT_FOUND` otherwise) names the scenarios the finding is
93
102
  about. After a `fixed` close, fresh evidence for those scenarios alone
@@ -448,7 +457,7 @@ subject's `change_ids` (`canon subject adopt`). The subject string is
448
457
  `<change_id>#<round>.<seq>`:
449
458
 
450
459
  ```
451
- open-blocker c-demo#1.1 — open blocker finding by `reviewer-2` on change `c-demo` (subject `demo-subject`): unbounded subprocess wait; fix it and `canon finding close <change> --round <n> --seq <n> --disposition fixed`, or close it as rejected or deferred
460
+ open-blocker c-demo#1.1 — open blocker finding by `reviewer-2` on change `c-demo` (subject `demo-subject`): unbounded subprocess wait; fix it and `canon finding close <change> --round <n> --seq <n> --disposition fixed`, or have a reviewer close it as rejected or deferred
452
461
  ```
453
462
 
454
463
  Findings on changes no in-scope subject has adopted do not block.
@@ -172,6 +172,52 @@ uploads, reads back and verifies every local blob, then writes the
172
172
  `.canon/artifacts/`; commit the removals, `.gitignore` and `canon.yaml`. It is
173
173
  resumable and a second run finds nothing to do.
174
174
 
175
+ The store only grows: a report written anew on every run adds a blob per run.
176
+ `canon artifacts prune [--keep-days N]` (a preview; `--commit --plan-digest
177
+ <digest>` acts) deletes the blobs no record binds. It keeps a blob for every
178
+ reason that holds, and the preview names them: `latest-evidence` (the latest
179
+ evidence per task and per `(project_id, scenario_id)` binds it, what the gate and
180
+ `artifacts verify` read), `current-review` (a review still in effect binds it),
181
+ `staged` (a record not promoted yet binds it) and `within-keep-days` (with
182
+ `--keep-days N`, evidence or a review of the last `N` days, in the ledger or its
183
+ archive, binds it). Everything else in the configured store goes: the local
184
+ directory, or the objects of the tier `artifact_store:` names by the same rule
185
+ (a copy left in the local directory of such a repo is judged by it too). The
186
+ preview counts the blobs and bytes that go and stay, lists the blobs to delete
187
+ a page at a time (`--limit`, `--cursor`, `--all`) and offers no `--commit` when
188
+ there is nothing to delete. The plan digest covers the blobs to delete, the
189
+ blobs to keep with their reasons and every record read, so evidence added since
190
+ the preview is `PLAN_STALE` and nothing is deleted. A repo whose records,
191
+ staging area or archive cannot be read in full is refused: a blob is never
192
+ deleted on a guess. After a prune, `artifacts verify` and `gate check` answer as
193
+ they did. A deleted local blob leaves the working tree: commit the removal. It
194
+ stays in git history, and shrinking that history is the repo owner's call, not
195
+ the command's. A deleted object of a tier cannot be undone, and the preview says
196
+ so with the object count. A delete that fails stops the run: with nothing deleted yet
197
+ it is `ARTIFACTS_STORE_FAILED` (an object) or `WRITE_FAILED` (a local file); after
198
+ some, `ARTIFACTS_PRUNE_INCOMPLETE` names what was deleted, and a new preview
199
+ lists what remains.
200
+
201
+ A blob write stages `.canon/artifacts/sha256/.tmp-<sha256>-<pid>-<nanos>` and
202
+ renames it when it is complete; a write killed in between (SIGKILL, a power
203
+ cut) leaves the file, and nothing else removes it. `canon artifacts prune`
204
+ counts the **stale** ones (a regular file of exactly that name shape, modified
205
+ more than five minutes ago; a younger file may be a live write, and a link, a
206
+ directory, a file stamped in the future or a name of another shape such as
207
+ `.tmp-notes` is never touched) in `data.staleTemps` (`files`, `bytes` and the
208
+ first names), apart from the blobs, and the commit deletes exactly the ones the
209
+ plan lists. They are part of the plan digest, so a temp file added or removed
210
+ since the preview is `PLAN_STALE`; the commit checks each again under the
211
+ store lock and skips one that changed; a repo with only temp files and no blob
212
+ to delete still gets the `--commit` command. `canon artifacts verify` takes no
213
+ lock and deletes nothing: it prints one line with the count and bytes and
214
+ `canon artifacts prune` when there are any, `data.staleTemps` always carries
215
+ `files` and `bytes` (`unreadable` instead, never a zero, when the store
216
+ directory cannot be read), and the exit follows the bound files alone. A temp
217
+ file is no finished blob, so deleting it changes no record. One that was
218
+ already committed is a tracked file: take it out of the commit (`git rm`, then
219
+ commit); the preview's `staleTemps.gitNote` says so.
220
+
175
221
  ## What `canon report build` does and doesn't read
176
222
 
177
223
  canon exposes layered `stg_`/`int_`/`mart_` query views; `canon report build`
@@ -197,7 +243,11 @@ is the canonical data-lifecycle boundary: the bare run previews: it prints the r
197
243
  its `planDigest` and deletes nothing; `--commit --plan-digest <planDigest>` deletes only if
198
244
  the plan recomputed now has the same digest (`PLAN_STALE`, exit 2, when the
199
245
  data moved). The only purgeable kinds are
200
- `session`, `run`, `event`, and `trajectory`; the cutoff applies to every
246
+ `run` and `trajectory`, plus the retired `session` and `event` (kept for this
247
+ release only so stored rows can be deleted — delete them now, after the next
248
+ release only direct database access remains; they read no routing, so they
249
+ find rows in every configured tier even after `canon migrate` removes the
250
+ `routing:`/`aging:` keys); the cutoff applies to every
201
251
  routed rung and every configured aging destination, including retained
202
252
  historical versions. For `trajectory`, the command also purges the
203
253
  operator-local Parquet learn store under `learn.root` in `canon.yaml`;
@@ -290,13 +340,13 @@ skills:
290
340
  providers: [claude, codex] # any of claude, codex, omp, pi; [] for none
291
341
  ```
292
342
 
293
- `canon init` writes it and never asks: `--providers a,b` (or `none`) is the
343
+ `canon init` writes it and never asks: `--harness a --harness b` (or `--no-harness`) is the
294
344
  answer; without it init takes the harnesses whose
295
345
  `.claude`, `.codex`, `.omp` or `.pi` directory exists, and with none detected
296
346
  it writes only a commented example
297
347
  and installs nothing. `.agents` alone never selects Codex. `canon skills
298
348
  install|check|doctor` follow the section; `install` prunes projected files the bundle no longer ships when their bytes match the lock (a modified one stays, reported as `kept:`), `check` exits 1 (`SKILLS_CHECK_FAILED`) naming each orphan and `doctor` prints `orphan:` lines; `canon skills install
299
- --providers=<list>` rewrites it in place. Without the section they use the
349
+ --harness <name>` (once for each name) or `--no-harness` rewrites it in place. Without the section they use the
300
350
  install lock's providers, then the detected ones; nothing undetected is ever
301
351
  added. A present section that is not this shape, or names another harness,
302
352
  fails those commands (exit `1`), and `canon init --check` reports
@@ -381,7 +431,7 @@ retry (the command exits `2` and writes no record).
381
431
  ## The repository write lock
382
432
 
383
433
  A committed destructive command (`canon purge`, `canon tier age`, `canon ledger
384
- compact`, `canon artifacts move`, `canon migrate`) recomputes its plan, checks
434
+ compact`, `canon artifacts move`, `canon artifacts prune`, `canon migrate`) recomputes its plan, checks
385
435
  its digest and then makes the effects, and nothing may change the plan in
386
436
  between. It holds an OS file lock on `.canon/repo-write.lock` for the whole
387
437
  span, from before it recomputes the plan to after its last effect; a preview
@@ -107,7 +107,7 @@ canon evidence approval-payload --scenario auth.login.01 --project root --approv
107
107
  ```
108
108
  ```text
109
109
  # Record an external evaluator's re-audit of one scenario (class `audit`; the verdict follows --audit-result; canon never runs the evaluator)
110
- usage: canon evidence audit <SCENARIO_ID> --ref <TEXT> --evaluator <ID> --evaluator-version <TEXT> --evaluator-digest <DIGEST> --audit-result <confirmed|refuted|indeterminate> [--project <PROJECT_ID>] [--summary <TEXT>] [--command-result <TEXT> (with --summary)] [--run <RUN_ID>] [--actor <ACTOR_ID>] [--role <ROLE>] [--session <SESSION_ID>] [--rev <REV>] [--artifact <PATH>]* [--report <FORMAT:PATH>]* [--report-case <NAME> (with --report)]* [--max-artifact-mib <N>] [--override-reason <TEXT>] [--promote | --no-promote] [--input]
110
+ usage: canon evidence audit <SCENARIO_ID> --ref <TEXT> --evaluator <EVALUATOR_ID> --evaluator-version <TEXT> --evaluator-digest <DIGEST> --audit-result <confirmed|refuted|indeterminate> [--project <PROJECT_ID>] [--summary <TEXT>] [--command-result <TEXT> (with --summary)] [--run <RUN_ID>] [--actor <ACTOR_ID>] [--role <ROLE>] [--session <SESSION_ID>] [--rev <REV>] [--artifact <PATH>]* [--report <FORMAT:PATH>]* [--report-case <NAME> (with --report)]* [--max-artifact-mib <N>] [--override-reason <TEXT>] [--promote | --no-promote] [--input]
111
111
  ```
112
112
  ```bash
113
113
  canon evidence audit auth.login.01 --ref audit-report.json --evaluator eval-1 --evaluator-version 2.1 --evaluator-digest 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef --audit-result confirmed --role implementer --json
@@ -156,7 +156,7 @@ canon inventory sync --json
156
156
  ```
157
157
  ```text
158
158
  # Read stored records across every storage tier
159
- usage: canon query --kind <change|task|scenario|session|run|event|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding> [--since <TIMESTAMP>] [--plugin <PLUGIN_ID> | --history] [--change <CHANGE_ID>] [--status <STATUS>] [--domain <NAME>] [--include-sensitive] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>]
159
+ usage: canon query --kind <change|task|scenario|run|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding> [--since <TIMESTAMP>] [--plugin <PLUGIN_ID> | --history] [--change <CHANGE_ID>] [--status <STATUS>] [--domain <NAME>] [--include-sensitive] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>]
160
160
  ```
161
161
  ```bash
162
162
  canon query --kind evidence --json
@@ -184,7 +184,7 @@ canon schema evidence add --json
184
184
  ```
185
185
  ```text
186
186
  # Search records, brief sections and scenario text, with each hit's neighbors in the record graph
187
- usage: canon search <TEXT> [--kind <change|task|scenario|session|run|event|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding|brief>]* [--expand <N>] [--limit <N>]
187
+ usage: canon search <TEXT> [--kind <change|task|scenario|run|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding|brief>]* [--expand <N>] [--limit <N>]
188
188
  ```
189
189
  ```bash
190
190
  canon search timeout --kind finding --json
@@ -212,7 +212,7 @@ canon task done add-login#1 --json
212
212
  ```
213
213
  ```text
214
214
  # Follow a finding's review loop in time order: review, finding, fix, re-review, evidence
215
- usage: canon trace <ID>
215
+ usage: canon trace <TRACE_ID>
216
216
  ```
217
217
  ```bash
218
218
  canon trace add-login_1_1 --json
@@ -306,7 +306,8 @@ canon evidence add --input '[{"scenario":"auth.login.01","class":"test-run","ref
306
306
  re-checks them, so the working-tree report may be gitignored. Run
307
307
  `canon artifacts verify` to ask the store yourself; it refuses, never
308
308
  passes, when an object store cannot be reached. Moving an existing store
309
- (`canon artifacts move --tier`) is the repo owner's call: do not run it.
309
+ (`canon artifacts move --tier`) and deleting the blobs no record binds
310
+ (`canon artifacts prune`) are the repo owner's call: do not run them.
310
311
  For a scenario about what users see, let the test report carry its
311
312
  screenshots: Playwright's JUnit reporter attaches, per test case, what a
312
313
  test attaches (`testInfo.attach(name, {path})`, or `screenshot: 'on'`), and
@@ -44,6 +44,14 @@ usage: canon artifacts move --tier <TIER> [--commit --plan-digest <PLAN_DIGEST>]
44
44
  canon artifacts move --tier cold --json
45
45
  ```
46
46
  ```text
47
+ # Delete the artifact blobs no record binds any more (the bare run previews; --commit --plan-digest deletes)
48
+ usage: canon artifacts prune [--keep-days <N>] [--limit <N> | --all] [--cursor <CURSOR>] [--commit --plan-digest <PLAN_DIGEST>] [--input]
49
+ # a bare run previews and prints planDigest; `--commit --plan-digest <PLAN_DIGEST>` with that digest acts
50
+ ```
51
+ ```bash
52
+ canon artifacts prune --keep-days 30 --json
53
+ ```
54
+ ```text
47
55
  # Store the bound files of existing evidence records and current reviews in the artifact store (.canon/artifacts/sha256/)
48
56
  usage: canon artifacts store [--max-artifact-mib <N>] [--dry-run] [--input]
49
57
  ```
@@ -115,7 +123,7 @@ canon demo review --json
115
123
  ```
116
124
  ```text
117
125
  # Mint a Run manifest with retrieved guidance and context/policy lineage
118
- usage: canon dispatch begin --regime <KEY> [--role <ROLE>] [--actor <ACTOR_ID>] [--session <SESSION_ID>] [--provider <NAME>] [--model <NAME>] [--skill <ID>] [--skill-digest <DIGEST> (with --skill)] [--manifest <FILE>] [--prompt-bundle <NAME@VERSION>] [--task <TASK_ID>] [--parent-run <RUN_ID>] [--input]
126
+ usage: canon dispatch begin --regime <KEY> [--role <ROLE>] [--actor <ACTOR_ID>] [--session <SESSION_ID>] [--provider <NAME>] [--model <NAME>] [--skill <SKILL_ID>] [--skill-digest <DIGEST> (with --skill)] [--manifest <FILE>] [--prompt-bundle <NAME@VERSION>] [--task <TASK_ID>] [--parent-run <RUN_ID>] [--input]
119
127
  ```
120
128
  ```bash
121
129
  canon dispatch begin --regime implementer/my-repo/api/abcdef012345 --role implementer --json
@@ -150,7 +158,7 @@ canon evidence approval-payload --scenario auth.login.01 --project root --approv
150
158
  ```
151
159
  ```text
152
160
  # Export a redacted retention manifest without deleting records
153
- usage: canon export --kind <change|task|scenario|session|run|event|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding> [--before <TIMESTAMP>] [--after <TIMESTAMP>] [--output <FILE>] [--include-sensitive] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>] [--dry-run] [--input]
161
+ usage: canon export --kind <change|task|scenario|run|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding> [--before <TIMESTAMP>] [--after <TIMESTAMP>] [--output <FILE>] [--include-sensitive] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>] [--dry-run] [--input]
154
162
  ```
155
163
  ```bash
156
164
  canon export --kind evidence --output evidence.json --json
@@ -198,15 +206,8 @@ usage: canon ingest records [--watch] [--interval-secs <N>] [--dry-run] [--run <
198
206
  canon ingest records --json
199
207
  ```
200
208
  ```text
201
- # Import agent CLI session transcripts (omp/pi, Claude Code, Codex, Hermes)
202
- usage: canon ingest sessions [--watch] [--interval-secs <N>] [--home <DIR>] [--full] [--all-workspaces] [--dry-run] [--input]
203
- ```
204
- ```bash
205
- canon ingest sessions --json
206
- ```
207
- ```text
208
209
  # Set up canon in a repo (canon.yaml, a starter policy, the AGENTS.md block, a plans home)
209
- usage: canon init [--check] [--no-agents-md | --check] [--policy <light|standard|strict> | --check | --no-policy] [--providers <LIST> | --check] [--language <TAG> | --check] [--dry-run | --check] [--input]
210
+ usage: canon init [--check] [--no-agents-md | --check] [--policy <light|standard|strict> | --check | --no-policy] [--harness <claude|codex|omp|pi> | --check | --no-harness]* [--language <TAG> | --check] [--dry-run | --check] [--input]
210
211
  ```
211
212
  ```bash
212
213
  canon init --json
@@ -264,15 +265,15 @@ canon prompt show reviewer@v1 --json
264
265
  ```
265
266
  ```text
266
267
  # Remove allowlisted records older than a cutoff
267
- usage: canon purge --kind <session|run|event|trajectory> --before <TIMESTAMP> [--commit --plan-digest <PLAN_DIGEST>] [--input]
268
+ usage: canon purge --kind <run|trajectory|session|event> --before <TIMESTAMP> [--commit --plan-digest <PLAN_DIGEST>] [--input]
268
269
  # a bare run previews and prints planDigest; `--commit --plan-digest <PLAN_DIGEST>` with that digest acts
269
270
  ```
270
271
  ```bash
271
- canon purge --kind session --before 2020-01-01T00:00:00Z --json
272
+ canon purge --kind run --before 2020-01-01T00:00:00Z --json
272
273
  ```
273
274
  ```text
274
275
  # Read stored records across every storage tier
275
- usage: canon query --kind <change|task|scenario|session|run|event|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding> [--since <TIMESTAMP>] [--plugin <PLUGIN_ID> | --history] [--change <CHANGE_ID>] [--status <STATUS>] [--domain <NAME>] [--include-sensitive] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>]
276
+ usage: canon query --kind <change|task|scenario|run|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding> [--since <TIMESTAMP>] [--plugin <PLUGIN_ID> | --history] [--change <CHANGE_ID>] [--status <STATUS>] [--domain <NAME>] [--include-sensitive] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>]
276
277
  ```
277
278
  ```bash
278
279
  canon query --kind evidence --json
@@ -321,35 +322,35 @@ canon schema evidence add --json
321
322
  ```
322
323
  ```text
323
324
  # Search records, brief sections and scenario text, with each hit's neighbors in the record graph
324
- usage: canon search <TEXT> [--kind <change|task|scenario|session|run|event|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding|brief>]* [--expand <N>] [--limit <N>]
325
+ usage: canon search <TEXT> [--kind <change|task|scenario|run|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding|brief>]* [--expand <N>] [--limit <N>]
325
326
  ```
326
327
  ```bash
327
328
  canon search timeout --kind finding --json
328
329
  ```
329
330
  ```text
330
331
  # Run canon's built-in fixture self-tests
331
- usage: canon selftest [--suite <trust-spine-gate|tiered-storage|typed-authoring-vocabulary|policy-expressions|format-authority|session-ingest|canon-context|artifact-ingest|spec-ledger-selftest|plugin-overlays|plan-import>]
332
+ usage: canon selftest [--suite <trust-spine-gate|tiered-storage|typed-authoring-vocabulary|policy-expressions|format-authority|canon-context|artifact-ingest|spec-ledger-selftest|plugin-overlays|plan-import>]
332
333
  ```
333
334
  ```bash
334
335
  canon selftest --suite trust-spine-gate --json
335
336
  ```
336
337
  ```text
337
338
  # Check canonical projections without writing; exit 1 on drift, a legacy remnant, or a lock another canon version wrote
338
- usage: canon skills check [--skills-source <DIR>] [--providers <LIST>]
339
+ usage: canon skills check [--skills-source <DIR>] [--harness <claude|codex|omp|pi> | --no-harness]*
339
340
  ```
340
341
  ```bash
341
342
  canon skills check --json
342
343
  ```
343
344
  ```text
344
- # Print diagnostics for canonical projections, the install lock's canon version, legacy remnants, canon projections for a provider that is not selected, and other skills whose description claims build work; reports only, never edits
345
- usage: canon skills doctor [--skills-source <DIR>] [--providers <LIST>]
345
+ # Print diagnostics for canonical projections, the install lock's canon version, legacy remnants, canon projections for a harness that is not selected, and other skills whose description claims build work; reports only, never edits
346
+ usage: canon skills doctor [--skills-source <DIR>] [--harness <claude|codex|omp|pi> | --no-harness]*
346
347
  ```
347
348
  ```bash
348
349
  canon skills doctor --json
349
350
  ```
350
351
  ```text
351
352
  # Install the canonical `canon` bundle or legacy developer skills
352
- usage: canon skills install [--skills-source <DIR>] [--providers <LIST>] [--dry-run] [--input]
353
+ usage: canon skills install [--skills-source <DIR>] [--harness <claude|codex|omp|pi> | --no-harness]* [--dry-run] [--input]
353
354
  ```
354
355
  ```bash
355
356
  canon skills install --json
@@ -384,7 +385,7 @@ canon strategy promote 01ARZ3NDEKTSV4RRFFQ69G5FAV --json
384
385
  ```
385
386
  ```text
386
387
  # Disable an active strategy with durable rollback provenance
387
- usage: canon strategy rollback <STRATEGY_ID> --reason <TEXT> --actor <ACTOR_ID> --signature-file <FILE> --approval-at <TIMESTAMP> [--contradicting-trajectory <ID>] [--input]
388
+ usage: canon strategy rollback <STRATEGY_ID> --reason <TEXT> --actor <ACTOR_ID> --signature-file <FILE> --approval-at <TIMESTAMP> [--contradicting-trajectory <TRAJECTORY_ID>] [--input]
388
389
  ```
389
390
  ```bash
390
391
  canon strategy rollback 01ARZ3NDEKTSV4RRFFQ69G5FAV --reason "regressed in production" --actor alice --signature-file approval.sig --approval-at 2030-01-01T00:00:00Z --json
@@ -434,7 +435,7 @@ canon tier age --json
434
435
  ```
435
436
  ```text
436
437
  # Follow a finding's review loop in time order: review, finding, fix, re-review, evidence
437
- usage: canon trace <ID>
438
+ usage: canon trace <TRACE_ID>
438
439
  ```
439
440
  ```bash
440
441
  canon trace add-login_1_1 --json
@@ -631,7 +632,7 @@ read that changed since is `PLAN_STALE` too, and `meta.next[0]` is the preview
631
632
  to run again. A commit holds the repository write lock for its whole run:
632
633
  another command that writes waits for it, and one that waited 30 seconds
633
634
  answers `REPO_LOCK_UNAVAILABLE` (exit 2, retryable): run it again. A document passed
634
- with `--input` never carries `--commit` or `--plan-digest`, and these five
635
+ with `--input` never carries `--commit` or `--plan-digest`, and these six
635
636
  leaves take one object only (`INPUT_INVALID`).
636
637
 
637
638
  ```bash
@@ -641,7 +642,11 @@ canon ledger compact
641
642
  ```
642
643
 
643
644
  `canon artifacts move --tier <tier>` moves the local artifact store to an
644
- object store and removes the local blobs, and `purge` deletes records. They
645
+ object store and removes the local blobs, `canon artifacts prune` deletes the
646
+ blobs no record binds any more and the stale `.tmp-` files a killed write left
647
+ in the store (a deleted local blob stays in git history; a deleted object of a
648
+ tier is gone for good; `canon artifacts verify` only counts the temp files), and
649
+ `purge` deletes records. They
645
650
  are the repo owner's decisions, not steps of the loop: run the preview, give
646
651
  the human the effects, and run the commit only on their answer. If the repo is
647
652
  large, the store is slow or the human has not asked for it, do not run it.