@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.
Files changed (133) hide show
  1. package/dist/skills/SKILL.src.md +245 -89
  2. package/dist/skills/reference/brief-align.md +4 -2
  3. package/dist/skills/reference/brief-clarify.md +7 -5
  4. package/dist/skills/reference/brief-harden.md +4 -2
  5. package/dist/skills/reference/brief-polish.md +7 -5
  6. package/dist/skills/reference/brief-shape.md +4 -2
  7. package/dist/skills/reference/canon-artifact-ingest.md +11 -7
  8. package/dist/skills/reference/canon-authoring.md +16 -2
  9. package/dist/skills/reference/canon-context.md +21 -11
  10. package/dist/skills/reference/canon-fmt.md +10 -2
  11. package/dist/skills/reference/canon-gate.md +119 -83
  12. package/dist/skills/reference/canon-inventory.md +34 -22
  13. package/dist/skills/reference/canon-learn.md +23 -19
  14. package/dist/skills/reference/canon-plan-import.md +10 -7
  15. package/dist/skills/reference/canon-plugins.md +15 -8
  16. package/dist/skills/reference/canon-policy.md +20 -16
  17. package/dist/skills/reference/canon-report-dashboard.md +30 -19
  18. package/dist/skills/reference/canon-retrieve.md +13 -10
  19. package/dist/skills/reference/canon-review.md +96 -68
  20. package/dist/skills/reference/canon-session-ingest.md +7 -3
  21. package/dist/skills/reference/canon-storage.md +82 -51
  22. package/dist/skills/reference/canon-subject.md +123 -84
  23. package/dist/skills/reference/canon-vocab.md +1 -1
  24. package/dist/skills/reference/role-implementer.md +295 -64
  25. package/dist/skills/reference/role-orchestrator.md +547 -55
  26. package/dist/skills/reference/role-planner.md +189 -32
  27. package/dist/skills/reference/role-reviewer.md +257 -58
  28. package/dist/skills/scripts/canon-retrieve-pre-dispatch.sh +10 -5
  29. package/man/canon-adapter-authorize.1 +44 -0
  30. package/man/canon-adapter-validate.1 +44 -0
  31. package/man/canon-adapter.1 +46 -0
  32. package/man/canon-artifacts-move.1 +63 -0
  33. package/man/canon-artifacts-store.1 +54 -0
  34. package/man/canon-artifacts-verify.1 +48 -0
  35. package/man/canon-artifacts.1 +45 -0
  36. package/man/canon-brief-approve.1 +62 -0
  37. package/man/canon-brief-check.1 +44 -0
  38. package/man/canon-brief-show.1 +50 -0
  39. package/man/canon-brief.1 +63 -0
  40. package/man/canon-change-new.1 +66 -0
  41. package/man/canon-change.1 +42 -0
  42. package/man/canon-completion.1 +60 -0
  43. package/man/canon-context-pack-add.1 +47 -0
  44. package/man/canon-context-pack-show.1 +44 -0
  45. package/man/canon-context-pack-verify.1 +44 -0
  46. package/man/canon-context-pack.1 +50 -0
  47. package/man/canon-context.1 +44 -0
  48. package/man/canon-dashboard.1 +50 -0
  49. package/man/canon-demo-init.1 +44 -0
  50. package/man/canon-demo-review.1 +44 -0
  51. package/man/canon-demo.1 +47 -0
  52. package/man/canon-dispatch-begin.1 +80 -0
  53. package/man/canon-dispatch-diff.1 +41 -0
  54. package/man/canon-dispatch-end.1 +60 -0
  55. package/man/canon-dispatch.1 +45 -0
  56. package/man/canon-divergence-accept.1 +68 -0
  57. package/man/canon-divergence-add.1 +97 -0
  58. package/man/canon-divergence-defer.1 +71 -0
  59. package/man/canon-divergence-list.1 +56 -0
  60. package/man/canon-divergence-resolve.1 +68 -0
  61. package/man/canon-divergence.1 +51 -0
  62. package/man/canon-evidence-add.1 +168 -0
  63. package/man/canon-evidence-approval-payload.1 +65 -0
  64. package/man/canon-evidence-audit.1 +121 -0
  65. package/man/canon-evidence.1 +57 -0
  66. package/man/canon-export.1 +108 -0
  67. package/man/canon-feature-new.1 +62 -0
  68. package/man/canon-feature.1 +39 -0
  69. package/man/canon-finding-add.1 +196 -0
  70. package/man/canon-finding-close.1 +117 -0
  71. package/man/canon-finding-list.1 +59 -0
  72. package/man/canon-finding.1 +67 -0
  73. package/man/canon-format.1 +49 -0
  74. package/man/canon-gate-check.1 +44 -0
  75. package/man/canon-gate-install-hooks.1 +59 -0
  76. package/man/canon-gate-promote.1 +62 -0
  77. package/man/canon-gate.1 +50 -0
  78. package/man/canon-ingest-plans.1 +53 -0
  79. package/man/canon-ingest-records.1 +56 -0
  80. package/man/canon-ingest-sessions.1 +62 -0
  81. package/man/canon-ingest.1 +50 -0
  82. package/man/canon-init.1 +98 -0
  83. package/man/canon-inventory-sync.1 +50 -0
  84. package/man/canon-inventory.1 +39 -0
  85. package/man/canon-ledger-compact.1 +50 -0
  86. package/man/canon-ledger.1 +54 -0
  87. package/man/canon-migrate.1 +89 -0
  88. package/man/canon-plugin-sync.1 +53 -0
  89. package/man/canon-plugin.1 +39 -0
  90. package/man/canon-policy-approve.1 +50 -0
  91. package/man/canon-policy-show.1 +41 -0
  92. package/man/canon-policy.1 +52 -0
  93. package/man/canon-prompt-add.1 +47 -0
  94. package/man/canon-prompt-show.1 +41 -0
  95. package/man/canon-prompt.1 +43 -0
  96. package/man/canon-purge.1 +70 -0
  97. package/man/canon-query.1 +111 -0
  98. package/man/canon-regime-show.1 +50 -0
  99. package/man/canon-regime.1 +39 -0
  100. package/man/canon-report-build.1 +44 -0
  101. package/man/canon-report-check.1 +41 -0
  102. package/man/canon-report-snapshot.1 +47 -0
  103. package/man/canon-report.1 +45 -0
  104. package/man/canon-retrieve.1 +56 -0
  105. package/man/canon-review-change.1 +98 -0
  106. package/man/canon-review-scenario.1 +98 -0
  107. package/man/canon-review.1 +42 -0
  108. package/man/canon-scenario-new.1 +80 -0
  109. package/man/canon-scenario.1 +39 -0
  110. package/man/canon-schema.1 +63 -0
  111. package/man/canon-selftest.1 +69 -0
  112. package/man/canon-skills-check.1 +47 -0
  113. package/man/canon-skills-doctor.1 +47 -0
  114. package/man/canon-skills-install.1 +53 -0
  115. package/man/canon-skills-show.1 +104 -0
  116. package/man/canon-skills.1 +48 -0
  117. package/man/canon-status.1 +51 -0
  118. package/man/canon-strategy-approval-payload.1 +53 -0
  119. package/man/canon-strategy-promote.1 +59 -0
  120. package/man/canon-strategy-rollback.1 +62 -0
  121. package/man/canon-strategy.1 +45 -0
  122. package/man/canon-subject-adopt.1 +53 -0
  123. package/man/canon-subject-move.1 +80 -0
  124. package/man/canon-subject-new.1 +65 -0
  125. package/man/canon-subject-show.1 +44 -0
  126. package/man/canon-subject-unadopt.1 +63 -0
  127. package/man/canon-subject.1 +51 -0
  128. package/man/canon-task-done.1 +47 -0
  129. package/man/canon-task.1 +42 -0
  130. package/man/canon-tier-age.1 +50 -0
  131. package/man/canon-tier.1 +39 -0
  132. package/man/canon.1 +169 -0
  133. package/package.json +9 -5
@@ -21,11 +21,13 @@ authored in one place:
21
21
  adopt`.
22
22
  - **Scenarios**: the `@subject:<id>` tag on each Gherkin scenario,
23
23
  indexed onto `Scenario.subject_id` by the scenario index (rebuilt by
24
- `canon inventory sync`, and refreshed by every command that reads it).
24
+ `canon inventory sync`, and refreshed on disk by the commands that write
25
+ records; `canon status` and `canon gate check` read it as the refresh
26
+ would leave it, without writing).
25
27
  The Subject record carries no scenario list — the spec corpus is the
26
28
  only source, and the Subjects report panel, `spec_coverage.scope`, and
27
29
  the shipped gate all read it from there. To link a scenario, tag it;
28
- the next `canon status` or `canon gate check` indexes the tag. There is
30
+ the next `canon status` or `canon gate check` reads the tag. There is
29
31
  no subject-side command for it.
30
32
 
31
33
  ## The 4-step loop
@@ -64,12 +66,17 @@ canon subject new subject-domain-loop \
64
66
  - `--summary` is optional; `--owner-role` defaults to `implementer`;
65
67
  `--actor-id` defaults to `canon`. A freshly-authored Subject with no
66
68
  adopted changes and no tagged scenarios is a valid minimal record and
67
- starts at status `proposed`. `--json` prints the written record.
69
+ starts at status `proposed`. `--json` prints the written record. Several
70
+ subjects at once: `--input` takes inline JSON, a file or `-`; an array (or
71
+ NDJSON) is a batch validated before any write, with `operands` holding the
72
+ id and the other keys the option names in camelCase (`canon schema subject
73
+ new --json` shows the schema and an example). Writing an identical subject
74
+ again is a no-op reported `unchanged` (`meta.unchanged`).
68
75
 
69
76
  ### 2. Retrieve subject-scoped strategy memory BEFORE working
70
77
 
71
78
  ```bash
72
- canon retrieve --role dev --domain dev --subject-id subject-domain-loop --k 5
79
+ canon retrieve --for-role dev --domain dev --subject-id subject-domain-loop --limit 5
73
80
  ```
74
81
 
75
82
  - `--regime <key>` XOR the derived pair `--domain <d> [--subject-id <id>]`:
@@ -98,12 +105,15 @@ canon retrieve --role dev --domain dev --subject-id subject-domain-loop --k 5
98
105
  ### 4. Verdicts / trajectories → learn (knowledge out)
99
106
 
100
107
  As work is reviewed, verdicts ingest under the subject-scoped regime
101
- (`canon ingest artifacts`), so `canon learn` distills strategies keyed to
108
+ (`canon ingest records`), so `canon strategy` distills strategies keyed to
102
109
  this subject and domain — the exact memory step 2 retrieves next time.
103
110
 
111
+ **Done when:** `canon subject show <id>` reports the status you moved it to
112
+ (`shipped` is the end of the loop) and `canon gate check` exits `0`.
113
+
104
114
  ## Status lifecycle + the shipped evidence gate
105
115
 
106
- `canon subject status <id> --to <state> [--override-reason <text>] [--reason <text>] [--actor-id <id>]`
116
+ `canon subject move <id> --to <state> [--override-reason <text>] [--reason <text>] [--actor-id <id>]`
107
117
  performs a policy-gated transition.
108
118
  The legal chain:
109
119
 
@@ -117,10 +127,10 @@ from anywhere). Any other transition is rejected by failure class, exits
117
127
  1, and leaves the record UNCHANGED (fail closed).
118
128
 
119
129
  ```bash
120
- canon subject status subject-domain-loop --to specced
121
- canon subject status subject-domain-loop --to building
122
- canon subject status subject-domain-loop --to verifying
123
- canon subject status subject-domain-loop --to shipped # gated — see below
130
+ canon subject move subject-domain-loop --to specced
131
+ canon subject move subject-domain-loop --to building
132
+ canon subject move subject-domain-loop --to verifying
133
+ canon subject move subject-domain-loop --to shipped # gated — see below
124
134
  ```
125
135
 
126
136
  On success the status updates in place; `--json` prints the updated
@@ -152,7 +162,7 @@ unless a reviewer accepted it (`canon divergence accept`, see
152
162
  closed `fixed` keeps blocking, and a chore's approval keeps the subject
153
163
  from shipping, until every evidenced scenario has evidence recorded after
154
164
  the close or the approval; the refusal names the scenarios and the
155
- `canon evidence add --all-scenarios …` command. Each refusal prints by
165
+ `canon evidence add --all-scenarios` command. Each refusal prints by
156
166
  failure class (`uncovered-cell`), carries a `hint`,
157
167
  exits 1, and the status stays `verifying`. `retired` is not gated.
158
168
 
@@ -171,9 +181,9 @@ coverage rules gate shipping, never approval). It runs with or without
171
181
  a policy. The refusal is an `unreviewed-promotion` naming the subject, and
172
182
  says what to do:
173
183
 
174
- ```
175
- canon subject status: unreviewed-promotion demo-subject — verifying → shipped: brief not approved — .canon/changes/c-demo/brief.md has no `Approved:` line; a human must answer the brief, and only from that answer the agent will record their words with `canon brief approve --change-id c-demo --by <the human> --note "<their words>"`
176
- canon subject status: refused — get the human's answer to the brief and record it with `canon brief approve`, or pass --override-reason <text> to move anyway; the waiver is recorded on the subject
184
+ ```output
185
+ canon subject move: SUBJECT_GATE_VIOLATION — unreviewed-promotion demo-subject — verifying → shipped: brief not approved — .canon/changes/c-demo/brief.md has no `Approved:` line; a human must answer the brief, and only from that answer the agent will record their words with `canon brief approve c-demo --approver <the human> --note "<their words>"`
186
+ canon subject move: refused — get the human's answer to the brief and record it with `canon brief approve`, or pass --override-reason <text> to move anyway; the waiver is recorded on the subject
177
187
  ```
178
188
 
179
189
  For an external change with no canon brief yet, the reason reads
@@ -181,12 +191,12 @@ For an external change with no canon brief yet, the reason reads
181
191
  the external plan <proposal>, which canon reads and never edits, so its
182
192
  approval lives in that canon file`` and the agent will ``create
183
193
  .canon/changes/<c>/brief.md holding a `Source: <proposal>` line, then
184
- record their words with `canon brief approve --change-id <c> --by <the human> --note "<their words>"` ``.
194
+ record their words with `canon brief approve <c> --approver <the human> --note "<their words>"` ``.
185
195
 
186
196
  Never record the approval without the human's answer. When there is no brief to
187
197
  answer (no adopted change, or a newest change with neither a canon
188
198
  `brief.md` nor an external `proposal.md`), the move is not refused: it
189
- prints ``canon subject status: advisory: <id>'s brief is not approved —
199
+ prints ``canon subject move: advisory: <id>'s brief is not approved —
190
200
  its newest adopted change `<c>` has no brief (no
191
201
  .canon/changes/<c>/brief.md, no openspec proposal.md), so there is no
192
202
  brief to answer and shipping is not refused`` (or `— <id> adopts no
@@ -234,8 +244,8 @@ When `.canon/policy.yaml` sets `spec_coverage.require_review` (see
234
244
  `canon-review`), every status write also runs the review checks and
235
245
  prints on stderr which it ran or skipped:
236
246
 
237
- ```
238
- canon subject status: review guard for building → verifying (spec_coverage.require_review, scope: verifying, shipped)
247
+ ```output
248
+ canon subject move: review guard for building → verifying (spec_coverage.require_review, scope: verifying, shipped)
239
249
  ran unreviewed-promotion — every owned scenario needs a review by an actor, and from a session, other than its evidence's
240
250
  ran open-blocker — 1 adopted change(s) checked for open blocker findings
241
251
  ```
@@ -251,7 +261,7 @@ also refuses a `false-success` (a scenario whose latest audit is
251
261
  sampled audit; see `canon-gate`.
252
262
 
253
263
  ```bash
254
- canon subject status demo-subject --to verifying \
264
+ canon subject move demo-subject --to verifying \
255
265
  --override-reason "reviewer out until Monday" --actor-id lead
256
266
  ```
257
267
 
@@ -287,13 +297,13 @@ gate now misses) reopens it: reopen, add tasks to the approved change,
287
297
  scenario, evidence, review, ship.
288
298
 
289
299
  ```bash
290
- canon subject status demo-subject --to verifying \
300
+ canon subject move demo-subject --to verifying \
291
301
  --reason "follow-up: the retry path leaks a file handle" --actor-id impl
292
302
  ```
293
303
 
294
- ```
295
- canon subject status: reopened `demo-subject` from shipped, recorded by `impl`: follow-up: the retry path leaks a file handle; keep the follow-up in its approved change `c-demo`, then scenario, evidence and review; shipping again runs every guard
296
- canon subject status: demo-subject → verifying — written directly; nothing to promote
304
+ ```output
305
+ canon subject move: reopened `demo-subject` from shipped, recorded by `impl`: follow-up: the retry path leaks a file handle; keep the follow-up in its approved change `c-demo`, then scenario, evidence and review; shipping again runs every guard
306
+ canon subject move: demo-subject → verifying — written directly; nothing to promote
297
307
  ```
298
308
 
299
309
  - `--reason "<one line>"` is required for `shipped → verifying` (exit 2
@@ -317,7 +327,7 @@ canon subject status: demo-subject → verifying — written directly; nothing t
317
327
  `POLICY_APPROVAL_UNREADABLE`: see `canon-policy`) refuses the reopen and
318
328
  the ship, and `--override-reason` does not waive it.
319
329
  - `canon change new` on a shipped subject prints the reopen command
320
- (`canon subject status <id> --to verifying --reason "<why it reopens>"`)
330
+ (`canon subject move <id> --to verifying --reason "<why it reopens>"`)
321
331
  in its output and `meta.next`.
322
332
  - `canon status` flags a shipped subject whose gate went red (whatever
323
333
  `verifying → shipped` would now refuse it on) and its only step is
@@ -331,20 +341,20 @@ Planning docs written outside canon become change/task records via
331
341
 
332
342
  ```bash
333
343
  canon ingest plans --repo . # import → change/task rows
334
- canon subject adopt subject-domain-loop-plan \
335
- --subject-id subject-domain-loop # link change → subject
344
+ canon subject adopt subject-domain-loop \
345
+ --change-id subject-domain-loop-plan # link change → subject
336
346
  ```
337
347
 
338
348
  A change made with `canon change new` (below) is recorded and adopted
339
349
  already. A `tasks.md` in it is an optional work note nothing gates on
340
350
  (`canon change new` no longer writes one); an existing one is still read:
341
- `canon evidence add --task` and `canon gate task` read the file as it is,
351
+ `canon evidence add --task-id` and `canon task done` read the file as it is,
342
352
  and a flip re-imports that change itself. Run `canon ingest plans` for a
343
353
  plan written outside canon, or when `canon query --kind task` must list
344
354
  rows nobody has flipped yet.
345
355
 
346
356
  `adopt` adds the subject to the change's `subject_ids` and the change to
347
- the Subject's `change_ids`, so `canon query --kind change --change-id …`
357
+ the Subject's `change_ids`, so `canon query --kind change --change-id <id>`
348
358
  and `canon query --kind subject` agree on the link from both ends. It
349
359
  writes only the side that lacks the link, so rerunning it on a linked
350
360
  pair writes nothing and exits `0`.
@@ -353,7 +363,7 @@ A change may belong to several subjects (0.18). Adopting it under a
353
363
  second subject adds that subject, never re-points the change, and says
354
364
  so:
355
365
 
356
- ```
366
+ ```output
357
367
  canon subject adopt: linked change `refactor-core` to subject `editing` as well; the change now belongs to `perception` and `editing` — written directly; nothing to promote
358
368
  ```
359
369
 
@@ -369,10 +379,10 @@ The two records cannot be written atomically, so the subject is written
369
379
  first: a half-done adoption still has that change's open blockers
370
380
  counted. If the change write then fails, `adopt` exits `2`, names the
371
381
  subject that now lists the change, and prints `canon subject adopt
372
- <change_id> --subject-id <id>` to complete it.
382
+ <subject_id> --change-id <change_id>` to complete it.
373
383
 
374
384
  `canon change new <slug> --subject-id <S>` and `canon subject adopt
375
- <change> --subject-id <S>` print a warning on stderr, and in JSON
385
+ <S> --change-id <change>` print a warning on stderr, and in JSON
376
386
  `meta.warnings`, when `<S>` is `building`, `verifying` or `shipped` and the
377
387
  change's brief is not approved. The warning says the subject's existing
378
388
  scenarios keep accepting evidence and the subject can still be reopened and
@@ -382,10 +392,14 @@ pending until then: the reopen and ship guards read the newest adopted change
382
392
  with an `Approved:` line instead, so a shipped subject can reopen, re-verify
383
393
  and ship again while the draft waits; `canon status` still lists it.
384
394
 
395
+ **Done when:** `canon subject show <id>` lists the change in the subject's
396
+ `change_ids` and `canon query --kind change --change-id <change>` lists the
397
+ subject in the change's `subject_ids`.
398
+
385
399
  ### Taking a draft change back out: `canon subject unadopt`
386
400
 
387
- ```bash
388
- canon subject unadopt <change> --subject-id <S> --as planner --json
401
+ ```text
402
+ canon subject unadopt <S> --change-id <change> --json
389
403
  ```
390
404
 
391
405
  Removes the link on both records and keeps the change and its brief, so the
@@ -405,7 +419,7 @@ it adopted:
405
419
  canon change new add-login --subject-id auth --title "Add login"
406
420
  ```
407
421
 
408
- ```
422
+ ```output
409
423
  canon change new: wrote .canon/changes/add-login/brief.md
410
424
  canon change new: recorded change `add-login` adopted into subject `auth` — written directly; nothing to promote
411
425
  ```
@@ -418,7 +432,7 @@ canon change new: recorded change `add-login` adopted into subject `auth` — wr
418
432
  the headings in the repo's `language:`), and a comment naming
419
433
  `canon brief approve` as where the human's answer is recorded, so the
420
434
  file starts unapproved. The intent section's first paragraph holds the
421
- title, which imports as the change summary. `--kind chore` writes the
435
+ title, which imports as the change summary. `--change-kind chore` writes the
422
436
  short chore brief instead (intent, category, invariants, checks, out of
423
437
  scope; see `canon brief` below). No `tasks.md` is written:
424
438
  `canon status` lists each flow step's scenarios instead.
@@ -438,7 +452,7 @@ canon change new: recorded change `add-login` adopted into subject `auth` — wr
438
452
  cannot be written atomically. If the change record fails after the
439
453
  subject record was written, the command exits `2`, keeps the change
440
454
  dir and that one subject record, and prints the repair, `canon ingest
441
- plans && canon subject adopt <slug> --subject-id <id>`, which completes
455
+ plans && canon subject adopt <id> --change-id <slug>`, which completes
442
456
  the link and is safe to rerun.
443
457
  - **Refuses** with exit `2`, writing nothing, when the subject does not
444
458
  exist, or when the slug already has a `.canon/changes/<slug>` dir
@@ -446,8 +460,8 @@ canon change new: recorded change `add-login` adopted into subject `auth` — wr
446
460
 
447
461
  A `tasks.md` is an optional work note canon never writes and nothing
448
462
  gates on. If one exists, rows added as `- [ ] <n> <title>` are flipped with
449
- `canon gate task <slug>#<n>` once evidence exists; `canon evidence add
450
- --task` and the flip read the file as it is, so a new row needs no
463
+ `canon task done <slug>#<n>` once evidence exists; `canon evidence add
464
+ --task-id` and the flip read the file as it is, so a new row needs no
451
465
  `canon ingest plans` run.
452
466
 
453
467
  A change from an external plan (an openspec change listed under
@@ -459,15 +473,19 @@ points at the external document and, once the human answers, the
459
473
  pointer `brief.md` is not a change of its own: the native reader skips
460
474
  it, so the external source keeps the change, its summary and its tasks.
461
475
 
462
- ### The brief: `canon brief`, `canon brief check`, `canon brief approve`
476
+ **Done when:** `canon subject show <id>` lists the new change in its
477
+ `change_ids`, and `canon brief show <slug>` names the next step on its
478
+ brief (`data.next`, `meta.next`).
463
479
 
464
- ```bash
465
- canon brief [--change-id <slug>] # state and the next one to three steps; never edits
466
- canon brief check [--change-id <slug>] [--json] # findings; exit 0 clean, 2 blockers, 1 error
467
- canon brief approve --change-id <slug> --by <the human> --note "<their words>"
480
+ ### The brief: `canon brief show`, `canon brief check`, `canon brief approve`
481
+
482
+ ```text
483
+ canon brief show [<slug>] # state and the next one to three steps; never edits
484
+ canon brief check [<slug>] [--json] # findings; exit 0 clean, 2 blockers, 1 error
485
+ canon brief approve <slug> --approver <the human> --note "<their words>"
468
486
  ```
469
487
 
470
- Without `--change-id`, the repo's only live change is read. The brief is the
488
+ Without the change operand, the repo's only live change is read. The brief is the
471
489
  PRD `canon change new` writes; sections are found by their
472
490
  `<!-- canon:section <key> role=… -->` marker, never by heading text. A
473
491
  brief without markers (written before 0.19) checks as `brief.legacy`, an
@@ -488,7 +506,7 @@ advisory, and is read as before.
488
506
  asides, dates and decision notes, stock vocabulary, Korean endings and
489
507
  length budgets, in the normative sections plus Intent and Questions;
490
508
  sentence, paragraph and key-sentence rules in normative sections.
491
- Never an authorship verdict. `reference/brief-polish.md` has each rule.
509
+ Never an authorship verdict. `canon skills show brief-polish` has each rule.
492
510
  - **Waivers**: `<!-- canon:waive <rule-id> <section-key> "<reason>" -->`,
493
511
  one rule in one section, reason required; add `match="<text>"` to waive
494
512
  only the findings whose matched text contains it. Listed in the output.
@@ -503,16 +521,20 @@ advisory, and is read as before.
503
521
  The optional refinement passes that fix findings before the human stop are
504
522
  listed in `role-planner.md` in this directory.
505
523
 
506
- A **chore** (`canon change new --kind chore`) changes how the subject is
524
+ A **chore** (`canon change new --change-kind chore`) changes how the subject is
507
525
  built or kept, never what it does. Its brief is intent, category,
508
526
  invariants, checks, out of scope; it adds no scenarios, and its evidence
509
527
  is the subject's suite run again at the chore commit with
510
- `canon evidence add --all-scenarios --report <kind>:<path> …`. That
528
+ `canon evidence add --all-scenarios --report <kind>:<path>`. That
511
529
  supersedes the old evidence; the pinned reviews stay current while the
512
530
  verdicts and checks are the same, so the chore itself is reviewed once with
513
- `canon review add --change-id <slug> …` before it ships. Work that changes
531
+ `canon review change <slug>` before it ships. Work that changes
514
532
  behavior is a feature change, never a chore.
515
533
 
534
+ **Done when:** `canon brief show <slug>` reports the brief approved and
535
+ unchanged since its approval; the human's `canon brief approve` is the only
536
+ step that writes it.
537
+
516
538
  ## Where are we: `canon status`
517
539
 
518
540
  ```bash
@@ -542,7 +564,7 @@ uses, so status and the gate cannot disagree about a gap:
542
564
  the next transition will require; `N stale review(s)` and `N unsigned
543
565
  review(s)` (printed when non-zero) count scenarios whose review went
544
566
  stale or whose latest reviews are all `indeterminate`/`unavailable`
545
- (see `canon-review`), and the `canon review add` step names both. With
567
+ (see `canon-review`), and the `canon review scenario` step names both. With
546
568
  `require_review` on, a `warning:` line counts the in-effect reviews that
547
569
  predate 0.23 review pinning and wait for `canon migrate`.
548
570
  - **Brief** (0.16, 0.17, 0.19) — for each `building`, `verifying` or `shipped`
@@ -571,7 +593,7 @@ uses, so status and the gate cannot disagree about a gap:
571
593
  line inside an external `proposal.md` is not read. Before that canon
572
594
  file exists, an external openspec `proposal.md` under the plan sources
573
595
  (the first source holding the change; with no `plans:` section, the
574
- `openspec` source rooted at the repo that `canon gate task` also falls
596
+ `openspec` source rooted at the repo that `canon task done` also falls
575
597
  back to) still makes the brief one to answer, and the line reads
576
598
  ``brief: not approved (.canon/changes/<c>/brief.md does not exist yet:
577
599
  change `<c>` comes from the external plan <proposal>, which canon reads
@@ -590,15 +612,15 @@ uses, so status and the gate cannot disagree about a gap:
590
612
  (owned scenarios, verdicts, required cases, audits, and, where
591
613
  `require_review` covers `shipped`, reviews and open blockers under
592
614
  `block_on_findings`; a gap its waiver recorded is not counted), prints
593
- ``gate: red — <n> <class> (first: <subject>), …; reopen with `canon subject status <id> --to verifying --reason "<why it reopens>" --actor-id <unit>` ``,
615
+ ``gate: red — <n> <class> (first: <subject>), …; reopen with `canon subject move <id> --to verifying --reason "<why it reopens>" --actor-id <unit>` ``,
594
616
  carries `red: [...]` in `--json`, and that reopen is its only `next:`
595
617
  step. Open blockers count against every subject a change belongs to.
596
618
  - **Unowned** — scenarios with no `@subject:` tag.
597
619
  - **Audits** — how many scenarios are sampled for
598
620
  `spec_coverage.require_audit`, confirmed, owed (no audit or
599
621
  `indeterminate`) and refuted (`false-success`). An owed or
600
- refuted audit adds a `next:` step suggesting `canon evidence add
601
- --kind audit …` (recorded from an external evaluator; canon never runs
622
+ refuted audit adds a `next:` step suggesting `canon evidence audit`
623
+ (recorded from an external evaluator; canon never runs
602
624
  one).
603
625
  - **Brief overrides** — a `warning:` line per evidence record attested
604
626
  with `canon evidence add --override-reason` while its subject's brief
@@ -606,24 +628,24 @@ uses, so status and the gate cannot disagree about a gap:
606
628
  reason (see `canon-gate`).
607
629
  - **`next:`** — at most five steps, each with a one-line reason; the
608
630
  rest are counted. Rules, in order: no `canon.yaml` → `canon init`; an
609
- unreadable one → `canon init --check-config`; a scenario tagged with a
631
+ unreadable one → `canon init --check`; a scenario tagged with a
610
632
  subject that has no record → `canon subject new <that id>`; no subject
611
633
  at all → `canon subject new`; subjects and `.feature` scenarios but no
612
- scenario records → `canon inventory sync` (status refreshes the index
613
- itself first, so this means the refresh refused on a format violation
614
- or a duplicate id, which the sync names). Then per subject, verifying
634
+ scenario records → `canon inventory sync` (status reads the index as a
635
+ refresh would leave it, so this means the refresh would be refused on a
636
+ format violation or a duplicate id, which the sync names). Then per subject, verifying
615
637
  first, then building, specced, proposed, shipped: an unapproved brief
616
638
  (building and later, and proposed once its change has a brief)
617
639
  → the human step below, which is then the subject's
618
- only step; no scenario → `canon scenario new … --subject-id <id>` (and, when no
640
+ only step; no scenario → `canon scenario new --subject-id <id>` (and, when no
619
641
  `.feature` file holds a scenario yet, `canon feature new` first, unless
620
642
  every subject waits on its brief); a missing case → `canon scenario new
621
643
  <surface>.<next nn> … --case <case>`; (building and later) an
622
644
  unevidenced or divergent scenario → `canon evidence add --scenario-id
623
645
  …` (its reason adds "then `canon gate promote`" only under
624
- `write.promote: manual`); an open blocker → `canon finding close …`; a
625
- due, unreviewed, evidenced scenario → `canon review add …` from another
626
- session; none of these → `canon subject status <id> --to <next status>`.
646
+ `write.promote: manual`); an open blocker → `canon finding close <change>`; a
647
+ due, unreviewed, evidenced scenario → `canon review scenario <id>` from another
648
+ session; none of these → `canon subject move <id> --to <next status>`.
627
649
  Last, unowned scenarios → `canon status`, after tagging them in their
628
650
  `.feature` files (status re-indexes the edit; no sync step). With more
629
651
  than one `specs.roots[]` entry, every suggested `canon scenario new`
@@ -631,8 +653,8 @@ uses, so status and the gate cannot disagree about a gap:
631
653
  (the reason lists the roots) for a subject that owns no scenario yet.
632
654
  - **The one human step.** Every step is the agent's to run except one,
633
655
  and it comes only once the brief is clean: while `canon brief check
634
- --change-id <slug>` has blockers, the subject gets the planner step
635
- `write the brief: canon brief check --change-id <slug> lists N blockers`
656
+ <slug>` has blockers, the subject gets the planner step
657
+ `write the brief: canon brief check <slug> lists N blockers`
636
658
  (`role: planner`) instead. A subject whose brief is enforced (its
637
659
  newest change's canon
638
660
  `brief.md` has no `Approved:` line, or it has no canon `brief.md` yet
@@ -644,16 +666,16 @@ uses, so status and the gate cannot disagree about a gap:
644
666
  and the approval is never assumed: `canon evidence add` refuses <id>'s
645
667
  scenarios and tasks until it is recorded; once the human answers,
646
668
  <record> (one call records the brief and the policy approval)``, where
647
- `<record>` is ``record their words with `canon brief approve --change-id
648
- <c> --by <the human> --note "<their words>"` ``, or, for an external
669
+ `<record>` is ``record their words with `canon brief approve
670
+ <c> --approver <the human> --note "<their words>"` ``, or, for an external
649
671
  change, ``create <brief> holding a `Source: <proposal>` line, then
650
- record their words with `canon brief approve --change-id <c> --by <the
672
+ record their words with `canon brief approve <c> --approver <the
651
673
  human> --note "<their words>"` ``; for a brief edited after its
652
- approval, ``re-approve with `canon brief approve …` ``.
674
+ approval, ``re-approve with `canon brief approve <c>` ``.
653
675
  It is the subject's only step, whatever its status: nothing suggests
654
676
  `canon feature new`, `canon scenario new`, `canon evidence add`, a
655
677
  review or a move-on for it before the human answers, and
656
- `canon subject status <id> --to shipped` refuses on the same check. The
678
+ `canon subject move <id> --to shipped` refuses on the same check. The
657
679
  approval is never assumed. A subject with no brief to answer gets no human step;
658
680
  its `brief:` line says
659
681
  `not approved (no adopted change; advisory, nothing to approve yet)` or
@@ -661,26 +683,26 @@ uses, so status and the gate cannot disagree about a gap:
661
683
  approve yet)`` and nothing is withheld (a `proposed` subject with no
662
684
  brief, and a `specced` subject, show no `brief:` line at all). Once nothing blocks, a
663
685
  ship-ready verifying subject gets the agent's own
664
- `canon subject status <id> --to shipped`; status never asks a human to ship.
686
+ `canon subject move <id> --to shipped`; status never asks a human to ship.
665
687
 
666
688
  Status fails closed rather than suggest progress the gate would refuse:
667
689
 
668
690
  - When `scenario`, `subject`, `review` or `finding` routes away from the
669
691
  `local` rung (the only rung status and the gate read), its records
670
692
  would read as empty. The only `next:` step is
671
- `canon init --check-config`, with the reason naming the
693
+ `canon init --check`, with the reason naming the
672
694
  `routing.<kind>: local` setting to restore.
673
695
  - When `spec_coverage` is present but unusable, `canon gate check`
674
696
  refuses. The first `next:` step is `canon gate check`, with the reason
675
697
  naming the section to fix, and no subject is suggested to move to its
676
698
  next status until it parses.
677
699
 
678
- `--json` prints one object:
700
+ `--json` prints the `{ok, data, meta}` envelope; `data` is one object:
679
701
 
680
702
  ```json
681
703
  {
682
704
  "statusVersion": 3,
683
- "canonVersion": "0.17.0",
705
+ "canonVersion": "0.28.0",
684
706
  "policy": { "present": true, "spec_coverage": { "require_evidence": true, "scope": [], "exclude_lanes": [], "require_cases": ["failure"], "require_review": { "scope": ["verifying", "shipped"], "distinct_actor": true, "block_on_findings": true } } },
685
707
  "warnings": [],
686
708
  "subjects": [
@@ -691,17 +713,30 @@ Status fails closed rather than suggest progress the gate would refuse:
691
713
  "reviewed": 1, "staleReviews": 0, "unsignedReviews": 0, "reviewDue": true, "openBlockers": 0, "missingCases": [],
692
714
  "brief": { "approved": false, "enforced": true, "change": "c-promo", "brief": ".canon/changes/c-promo/brief.md", "briefExists": false, "source": "openspec/changes/c-promo/proposal.md" } }
693
715
  ],
694
- "unowned": ["cart.promo.01"],
695
- "next": [
696
- { "command": "stop and report the brief in openspec/changes/c-promo/proposal.md; build and attest nothing for promo until the human answers (one answer approves brief and policy)", "why": "promo: .canon/changes/c-promo/brief.md does not exist yet: change `c-promo` comes from the external plan openspec/changes/c-promo/proposal.md, which canon reads and never edits, so its approval lives in that canon file (an older change's approval does not cover a new scope), and the approval is never assumed: … once the human answers, create .canon/changes/c-promo/brief.md holding a `Source: openspec/changes/c-promo/proposal.md` line, then record their words with `canon brief approve --change-id c-promo --by <the human> --note \"<their words>\"` (one call records the brief and the policy approval)", "actor": "human" },
697
- { "command": "canon finding close --change-id c-cart --round 1 --seq 1 --disposition fixed --resolution-sha <sha> --actor-id <unit> --session-id <session>", "why": "cart: 1 open blocker finding(s) (first: …); fix it, commit, then close it", "actor": "agent" },
698
- { "command": "canon review add --project-id root --scenario-id cart.add.02 --reviewer <reviewer> --actor-id <reviewer> --session-id <review-session> --role reviewer --pin <sha> --original-spec-ref \"<feature file>\"", "why": "cart: 1 of 2 scenario(s) lack a qualifying review; …", "actor": "agent" },
699
- { "command": "canon status", "why": "1 scenario(s) carry no @subject tag (first: cart.promo.01); add `@subject:<id>` above each in its .feature file, then check again: …", "actor": "agent" }
700
- ],
701
- "nextOmitted": 0
716
+ "unowned": ["cart.promo.01"]
702
717
  }
703
718
  ```
704
719
 
720
+ The steps that follow are not in `data`: they are `meta.next`, most useful
721
+ first, with `meta.nextOmitted` counting what was cut and `meta.waitingOn`
722
+ (with a declared role, `--as`) counting the steps each other owner holds:
723
+
724
+ ```json
725
+ "next": [
726
+ { "command": "stop and report the brief in openspec/changes/c-promo/proposal.md; build and attest nothing for promo until the human answers; then record their words with `canon brief approve c-promo --approver <the human> --note \"<their words>\"`", "argv": [], "why": "promo: the brief is not approved", "actor": "human", "role": null },
727
+ { "command": "canon finding close c-cart --round 1 --seq 1 --disposition fixed --actor-id <unit> --session-id <session>", "argv": [], "why": "cart: 1 open blocker finding(s); fix it, commit, then close it", "actor": "agent", "role": "implementer" },
728
+ { "command": "canon status", "argv": ["canon", "status"], "why": "1 scenario(s) carry no @subject tag (first: cart.promo.01); add `@subject:<id>` above each in its .feature file, then check again", "actor": "agent", "role": "planner" }
729
+ ]
730
+ ```
731
+
732
+ `argv` is the command split into words, and is empty when the command still
733
+ holds a `<placeholder>` for what only the agent knows (or is not a canon
734
+ command at all). On a repository that still holds 0.27 canon state,
735
+ `canon status` warns (`data.warnings`, `meta.warnings`) and puts `canon
736
+ migrate --json` first in `meta.next`: run `canon migrate`, then `canon
737
+ migrate --commit --plan-digest <digest from the preview>`, then `canon
738
+ skills install`.
739
+
705
740
  Each `missingCases` entry is `{ "projectId", "surface", "case" }`: the
706
741
  spec root, the `<area>.<surface>`, and the required case it lacks.
707
742
 
@@ -724,7 +759,7 @@ that the `Approved:` line carries no digest, `findings` is
724
759
  only), and `flow` lists each flow step as `{ "id", "change",
725
760
  "scenarios": [{ id, title, failure, evidenced, review }], "gaps" }`.
726
761
 
727
- Each `next` entry's `actor` is `agent` (its `command` is a canon command
762
+ Each `meta.next` entry's `actor` is `agent` (its `command` is a canon command
728
763
  line) or `human` (its `command` says what to get from the human).
729
764
 
730
765
  `policy.spec_coverage` has the shape `canon context --json` prints
@@ -735,15 +770,19 @@ in 0.16, when `next[].command` stopped always being a command line
735
770
  0.17, when `brief.proposal` was removed: the canon `brief.md` is
736
771
  `brief.brief`, with `briefExists` and `source`.
737
772
 
738
- `subject new`, `adopt` and `status` write their records directly; the
773
+ `subject new`, `adopt`, `unadopt` and `move` write their records directly; the
739
774
  human-readable success line ends `— written directly; nothing to
740
775
  promote` (`--json` prints the record and nothing else).
741
776
 
777
+ **Done when:** `canon status` lists no gap for the subject you worked on
778
+ and `canon gate check` exits `0`; read `data.subjects[]` for the counts and
779
+ `meta.next` for what is left.
780
+
742
781
  ## Reading the per-domain management view
743
782
 
744
783
  ```bash
745
784
  canon query --kind subject --domain dev --status building
746
- canon report --repo . # renders the "Subjects" panel
785
+ canon report build --repo . # renders the "Subjects" panel
747
786
  ```
748
787
 
749
788
  - `canon query --kind subject [--domain <d>] [--status <s>]` — the
@@ -754,4 +793,4 @@ canon report --repo . # renders the "Subjects" panel
754
793
  `covered_scenarios`), where `covered_scenarios` counts linked scenarios
755
794
  carrying a latest non-`Divergent` verdict — the same coverage the
756
795
  shipped gate enforces, surfaced read-only. Also exported by `canon
757
- report --snapshot` (see `canon-report-dashboard`).
796
+ report snapshot` (see `canon-report-dashboard`).
@@ -8,7 +8,7 @@ that the checker validates against it.
8
8
 
9
9
  ## Run `canon context` FIRST
10
10
 
11
- Before authoring any atom, run `canon context` (or `--json`) and read its
11
+ Before authoring any atom, run `canon context --fields vocab` (or `--json`) and read its
12
12
  `vocab` section: it lists every declarable directive + enum for the repo
13
13
  plus a content-hash version. Authoring against a directive/enum
14
14
  `canon context` does not list means the checker will reject it — the