@journeykit/canon 0.26.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/skills/SKILL.src.md +245 -89
- package/dist/skills/reference/brief-align.md +4 -2
- package/dist/skills/reference/brief-clarify.md +7 -5
- package/dist/skills/reference/brief-harden.md +4 -2
- package/dist/skills/reference/brief-polish.md +7 -5
- package/dist/skills/reference/brief-shape.md +4 -2
- package/dist/skills/reference/canon-artifact-ingest.md +11 -7
- package/dist/skills/reference/canon-authoring.md +16 -2
- package/dist/skills/reference/canon-context.md +21 -11
- package/dist/skills/reference/canon-fmt.md +10 -2
- package/dist/skills/reference/canon-gate.md +119 -83
- package/dist/skills/reference/canon-inventory.md +34 -22
- package/dist/skills/reference/canon-learn.md +23 -19
- package/dist/skills/reference/canon-plan-import.md +10 -7
- package/dist/skills/reference/canon-plugins.md +15 -8
- package/dist/skills/reference/canon-policy.md +20 -16
- package/dist/skills/reference/canon-report-dashboard.md +30 -19
- package/dist/skills/reference/canon-retrieve.md +13 -10
- package/dist/skills/reference/canon-review.md +96 -68
- package/dist/skills/reference/canon-session-ingest.md +7 -3
- package/dist/skills/reference/canon-storage.md +82 -51
- package/dist/skills/reference/canon-subject.md +123 -84
- package/dist/skills/reference/canon-vocab.md +1 -1
- package/dist/skills/reference/role-implementer.md +295 -64
- package/dist/skills/reference/role-orchestrator.md +547 -55
- package/dist/skills/reference/role-planner.md +189 -32
- package/dist/skills/reference/role-reviewer.md +257 -58
- package/dist/skills/scripts/canon-retrieve-pre-dispatch.sh +10 -5
- package/man/canon-adapter-authorize.1 +44 -0
- package/man/canon-adapter-validate.1 +44 -0
- package/man/canon-adapter.1 +46 -0
- package/man/canon-artifacts-move.1 +63 -0
- package/man/canon-artifacts-store.1 +54 -0
- package/man/canon-artifacts-verify.1 +48 -0
- package/man/canon-artifacts.1 +45 -0
- package/man/canon-brief-approve.1 +62 -0
- package/man/canon-brief-check.1 +44 -0
- package/man/canon-brief-show.1 +50 -0
- package/man/canon-brief.1 +63 -0
- package/man/canon-change-new.1 +66 -0
- package/man/canon-change.1 +42 -0
- package/man/canon-completion.1 +60 -0
- package/man/canon-context-pack-add.1 +47 -0
- package/man/canon-context-pack-show.1 +44 -0
- package/man/canon-context-pack-verify.1 +44 -0
- package/man/canon-context-pack.1 +50 -0
- package/man/canon-context.1 +44 -0
- package/man/canon-dashboard.1 +50 -0
- package/man/canon-demo-init.1 +44 -0
- package/man/canon-demo-review.1 +44 -0
- package/man/canon-demo.1 +47 -0
- package/man/canon-dispatch-begin.1 +80 -0
- package/man/canon-dispatch-diff.1 +41 -0
- package/man/canon-dispatch-end.1 +60 -0
- package/man/canon-dispatch.1 +45 -0
- package/man/canon-divergence-accept.1 +68 -0
- package/man/canon-divergence-add.1 +97 -0
- package/man/canon-divergence-defer.1 +71 -0
- package/man/canon-divergence-list.1 +56 -0
- package/man/canon-divergence-resolve.1 +68 -0
- package/man/canon-divergence.1 +51 -0
- package/man/canon-evidence-add.1 +168 -0
- package/man/canon-evidence-approval-payload.1 +65 -0
- package/man/canon-evidence-audit.1 +121 -0
- package/man/canon-evidence.1 +57 -0
- package/man/canon-export.1 +108 -0
- package/man/canon-feature-new.1 +62 -0
- package/man/canon-feature.1 +39 -0
- package/man/canon-finding-add.1 +196 -0
- package/man/canon-finding-close.1 +117 -0
- package/man/canon-finding-list.1 +59 -0
- package/man/canon-finding.1 +67 -0
- package/man/canon-format.1 +49 -0
- package/man/canon-gate-check.1 +44 -0
- package/man/canon-gate-install-hooks.1 +59 -0
- package/man/canon-gate-promote.1 +62 -0
- package/man/canon-gate.1 +50 -0
- package/man/canon-ingest-plans.1 +53 -0
- package/man/canon-ingest-records.1 +56 -0
- package/man/canon-ingest-sessions.1 +62 -0
- package/man/canon-ingest.1 +50 -0
- package/man/canon-init.1 +98 -0
- package/man/canon-inventory-sync.1 +50 -0
- package/man/canon-inventory.1 +39 -0
- package/man/canon-ledger-compact.1 +50 -0
- package/man/canon-ledger.1 +54 -0
- package/man/canon-migrate.1 +89 -0
- package/man/canon-plugin-sync.1 +53 -0
- package/man/canon-plugin.1 +39 -0
- package/man/canon-policy-approve.1 +50 -0
- package/man/canon-policy-show.1 +41 -0
- package/man/canon-policy.1 +52 -0
- package/man/canon-prompt-add.1 +47 -0
- package/man/canon-prompt-show.1 +41 -0
- package/man/canon-prompt.1 +43 -0
- package/man/canon-purge.1 +70 -0
- package/man/canon-query.1 +111 -0
- package/man/canon-regime-show.1 +50 -0
- package/man/canon-regime.1 +39 -0
- package/man/canon-report-build.1 +44 -0
- package/man/canon-report-check.1 +41 -0
- package/man/canon-report-snapshot.1 +47 -0
- package/man/canon-report.1 +45 -0
- package/man/canon-retrieve.1 +56 -0
- package/man/canon-review-change.1 +98 -0
- package/man/canon-review-scenario.1 +98 -0
- package/man/canon-review.1 +42 -0
- package/man/canon-scenario-new.1 +80 -0
- package/man/canon-scenario.1 +39 -0
- package/man/canon-schema.1 +63 -0
- package/man/canon-selftest.1 +69 -0
- package/man/canon-skills-check.1 +47 -0
- package/man/canon-skills-doctor.1 +47 -0
- package/man/canon-skills-install.1 +53 -0
- package/man/canon-skills-show.1 +104 -0
- package/man/canon-skills.1 +48 -0
- package/man/canon-status.1 +51 -0
- package/man/canon-strategy-approval-payload.1 +53 -0
- package/man/canon-strategy-promote.1 +59 -0
- package/man/canon-strategy-rollback.1 +62 -0
- package/man/canon-strategy.1 +45 -0
- package/man/canon-subject-adopt.1 +53 -0
- package/man/canon-subject-move.1 +80 -0
- package/man/canon-subject-new.1 +65 -0
- package/man/canon-subject-show.1 +44 -0
- package/man/canon-subject-unadopt.1 +63 -0
- package/man/canon-subject.1 +51 -0
- package/man/canon-task-done.1 +47 -0
- package/man/canon-task.1 +42 -0
- package/man/canon-tier-age.1 +50 -0
- package/man/canon-tier.1 +39 -0
- package/man/canon.1 +169 -0
- package/package.json +9 -5
|
@@ -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
|
|
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`
|
|
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 --
|
|
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
|
|
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
|
|
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
|
|
121
|
-
canon subject
|
|
122
|
-
canon subject
|
|
123
|
-
canon subject
|
|
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
|
|
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
|
|
176
|
-
canon 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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
296
|
-
canon subject
|
|
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
|
|
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
|
|
335
|
-
--
|
|
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
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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
|
-
```
|
|
388
|
-
canon subject unadopt <
|
|
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 <
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
canon brief
|
|
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
|
|
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. `
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
601
|
-
|
|
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
|
|
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
|
|
613
|
-
|
|
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
|
|
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
|
|
625
|
-
due, unreviewed, evidenced scenario → `canon review
|
|
626
|
-
session; none of these → `canon subject
|
|
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
|
-
|
|
635
|
-
`write the brief: canon brief check
|
|
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
|
|
648
|
-
<c> --
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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 `
|
|
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 .
|
|
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
|
|
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
|