@journeykit/canon 0.27.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 +107 -69
- package/dist/skills/reference/canon-inventory.md +23 -15
- 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 +65 -39
- package/dist/skills/reference/canon-subject.md +116 -79
- 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
|
@@ -66,12 +66,17 @@ canon subject new subject-domain-loop \
|
|
|
66
66
|
- `--summary` is optional; `--owner-role` defaults to `implementer`;
|
|
67
67
|
`--actor-id` defaults to `canon`. A freshly-authored Subject with no
|
|
68
68
|
adopted changes and no tagged scenarios is a valid minimal record and
|
|
69
|
-
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`).
|
|
70
75
|
|
|
71
76
|
### 2. Retrieve subject-scoped strategy memory BEFORE working
|
|
72
77
|
|
|
73
78
|
```bash
|
|
74
|
-
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
|
|
75
80
|
```
|
|
76
81
|
|
|
77
82
|
- `--regime <key>` XOR the derived pair `--domain <d> [--subject-id <id>]`:
|
|
@@ -100,12 +105,15 @@ canon retrieve --role dev --domain dev --subject-id subject-domain-loop --k 5
|
|
|
100
105
|
### 4. Verdicts / trajectories → learn (knowledge out)
|
|
101
106
|
|
|
102
107
|
As work is reviewed, verdicts ingest under the subject-scoped regime
|
|
103
|
-
(`canon ingest
|
|
108
|
+
(`canon ingest records`), so `canon strategy` distills strategies keyed to
|
|
104
109
|
this subject and domain — the exact memory step 2 retrieves next time.
|
|
105
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
|
+
|
|
106
114
|
## Status lifecycle + the shipped evidence gate
|
|
107
115
|
|
|
108
|
-
`canon subject
|
|
116
|
+
`canon subject move <id> --to <state> [--override-reason <text>] [--reason <text>] [--actor-id <id>]`
|
|
109
117
|
performs a policy-gated transition.
|
|
110
118
|
The legal chain:
|
|
111
119
|
|
|
@@ -119,10 +127,10 @@ from anywhere). Any other transition is rejected by failure class, exits
|
|
|
119
127
|
1, and leaves the record UNCHANGED (fail closed).
|
|
120
128
|
|
|
121
129
|
```bash
|
|
122
|
-
canon subject
|
|
123
|
-
canon subject
|
|
124
|
-
canon subject
|
|
125
|
-
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
|
|
126
134
|
```
|
|
127
135
|
|
|
128
136
|
On success the status updates in place; `--json` prints the updated
|
|
@@ -154,7 +162,7 @@ unless a reviewer accepted it (`canon divergence accept`, see
|
|
|
154
162
|
closed `fixed` keeps blocking, and a chore's approval keeps the subject
|
|
155
163
|
from shipping, until every evidenced scenario has evidence recorded after
|
|
156
164
|
the close or the approval; the refusal names the scenarios and the
|
|
157
|
-
`canon evidence add --all-scenarios
|
|
165
|
+
`canon evidence add --all-scenarios` command. Each refusal prints by
|
|
158
166
|
failure class (`uncovered-cell`), carries a `hint`,
|
|
159
167
|
exits 1, and the status stays `verifying`. `retired` is not gated.
|
|
160
168
|
|
|
@@ -173,9 +181,9 @@ coverage rules gate shipping, never approval). It runs with or without
|
|
|
173
181
|
a policy. The refusal is an `unreviewed-promotion` naming the subject, and
|
|
174
182
|
says what to do:
|
|
175
183
|
|
|
176
|
-
```
|
|
177
|
-
canon subject
|
|
178
|
-
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
|
|
179
187
|
```
|
|
180
188
|
|
|
181
189
|
For an external change with no canon brief yet, the reason reads
|
|
@@ -183,12 +191,12 @@ For an external change with no canon brief yet, the reason reads
|
|
|
183
191
|
the external plan <proposal>, which canon reads and never edits, so its
|
|
184
192
|
approval lives in that canon file`` and the agent will ``create
|
|
185
193
|
.canon/changes/<c>/brief.md holding a `Source: <proposal>` line, then
|
|
186
|
-
record their words with `canon brief approve
|
|
194
|
+
record their words with `canon brief approve <c> --approver <the human> --note "<their words>"` ``.
|
|
187
195
|
|
|
188
196
|
Never record the approval without the human's answer. When there is no brief to
|
|
189
197
|
answer (no adopted change, or a newest change with neither a canon
|
|
190
198
|
`brief.md` nor an external `proposal.md`), the move is not refused: it
|
|
191
|
-
prints ``canon subject
|
|
199
|
+
prints ``canon subject move: advisory: <id>'s brief is not approved —
|
|
192
200
|
its newest adopted change `<c>` has no brief (no
|
|
193
201
|
.canon/changes/<c>/brief.md, no openspec proposal.md), so there is no
|
|
194
202
|
brief to answer and shipping is not refused`` (or `— <id> adopts no
|
|
@@ -236,8 +244,8 @@ When `.canon/policy.yaml` sets `spec_coverage.require_review` (see
|
|
|
236
244
|
`canon-review`), every status write also runs the review checks and
|
|
237
245
|
prints on stderr which it ran or skipped:
|
|
238
246
|
|
|
239
|
-
```
|
|
240
|
-
canon subject
|
|
247
|
+
```output
|
|
248
|
+
canon subject move: review guard for building → verifying (spec_coverage.require_review, scope: verifying, shipped)
|
|
241
249
|
ran unreviewed-promotion — every owned scenario needs a review by an actor, and from a session, other than its evidence's
|
|
242
250
|
ran open-blocker — 1 adopted change(s) checked for open blocker findings
|
|
243
251
|
```
|
|
@@ -253,7 +261,7 @@ also refuses a `false-success` (a scenario whose latest audit is
|
|
|
253
261
|
sampled audit; see `canon-gate`.
|
|
254
262
|
|
|
255
263
|
```bash
|
|
256
|
-
canon subject
|
|
264
|
+
canon subject move demo-subject --to verifying \
|
|
257
265
|
--override-reason "reviewer out until Monday" --actor-id lead
|
|
258
266
|
```
|
|
259
267
|
|
|
@@ -289,13 +297,13 @@ gate now misses) reopens it: reopen, add tasks to the approved change,
|
|
|
289
297
|
scenario, evidence, review, ship.
|
|
290
298
|
|
|
291
299
|
```bash
|
|
292
|
-
canon subject
|
|
300
|
+
canon subject move demo-subject --to verifying \
|
|
293
301
|
--reason "follow-up: the retry path leaks a file handle" --actor-id impl
|
|
294
302
|
```
|
|
295
303
|
|
|
296
|
-
```
|
|
297
|
-
canon subject
|
|
298
|
-
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
|
|
299
307
|
```
|
|
300
308
|
|
|
301
309
|
- `--reason "<one line>"` is required for `shipped → verifying` (exit 2
|
|
@@ -319,7 +327,7 @@ canon subject status: demo-subject → verifying — written directly; nothing t
|
|
|
319
327
|
`POLICY_APPROVAL_UNREADABLE`: see `canon-policy`) refuses the reopen and
|
|
320
328
|
the ship, and `--override-reason` does not waive it.
|
|
321
329
|
- `canon change new` on a shipped subject prints the reopen command
|
|
322
|
-
(`canon subject
|
|
330
|
+
(`canon subject move <id> --to verifying --reason "<why it reopens>"`)
|
|
323
331
|
in its output and `meta.next`.
|
|
324
332
|
- `canon status` flags a shipped subject whose gate went red (whatever
|
|
325
333
|
`verifying → shipped` would now refuse it on) and its only step is
|
|
@@ -333,20 +341,20 @@ Planning docs written outside canon become change/task records via
|
|
|
333
341
|
|
|
334
342
|
```bash
|
|
335
343
|
canon ingest plans --repo . # import → change/task rows
|
|
336
|
-
canon subject adopt subject-domain-loop
|
|
337
|
-
--
|
|
344
|
+
canon subject adopt subject-domain-loop \
|
|
345
|
+
--change-id subject-domain-loop-plan # link change → subject
|
|
338
346
|
```
|
|
339
347
|
|
|
340
348
|
A change made with `canon change new` (below) is recorded and adopted
|
|
341
349
|
already. A `tasks.md` in it is an optional work note nothing gates on
|
|
342
350
|
(`canon change new` no longer writes one); an existing one is still read:
|
|
343
|
-
`canon evidence add --task` and `canon
|
|
351
|
+
`canon evidence add --task-id` and `canon task done` read the file as it is,
|
|
344
352
|
and a flip re-imports that change itself. Run `canon ingest plans` for a
|
|
345
353
|
plan written outside canon, or when `canon query --kind task` must list
|
|
346
354
|
rows nobody has flipped yet.
|
|
347
355
|
|
|
348
356
|
`adopt` adds the subject to the change's `subject_ids` and the change to
|
|
349
|
-
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>`
|
|
350
358
|
and `canon query --kind subject` agree on the link from both ends. It
|
|
351
359
|
writes only the side that lacks the link, so rerunning it on a linked
|
|
352
360
|
pair writes nothing and exits `0`.
|
|
@@ -355,7 +363,7 @@ A change may belong to several subjects (0.18). Adopting it under a
|
|
|
355
363
|
second subject adds that subject, never re-points the change, and says
|
|
356
364
|
so:
|
|
357
365
|
|
|
358
|
-
```
|
|
366
|
+
```output
|
|
359
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
|
|
360
368
|
```
|
|
361
369
|
|
|
@@ -371,10 +379,10 @@ The two records cannot be written atomically, so the subject is written
|
|
|
371
379
|
first: a half-done adoption still has that change's open blockers
|
|
372
380
|
counted. If the change write then fails, `adopt` exits `2`, names the
|
|
373
381
|
subject that now lists the change, and prints `canon subject adopt
|
|
374
|
-
<
|
|
382
|
+
<subject_id> --change-id <change_id>` to complete it.
|
|
375
383
|
|
|
376
384
|
`canon change new <slug> --subject-id <S>` and `canon subject adopt
|
|
377
|
-
<
|
|
385
|
+
<S> --change-id <change>` print a warning on stderr, and in JSON
|
|
378
386
|
`meta.warnings`, when `<S>` is `building`, `verifying` or `shipped` and the
|
|
379
387
|
change's brief is not approved. The warning says the subject's existing
|
|
380
388
|
scenarios keep accepting evidence and the subject can still be reopened and
|
|
@@ -384,10 +392,14 @@ pending until then: the reopen and ship guards read the newest adopted change
|
|
|
384
392
|
with an `Approved:` line instead, so a shipped subject can reopen, re-verify
|
|
385
393
|
and ship again while the draft waits; `canon status` still lists it.
|
|
386
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
|
+
|
|
387
399
|
### Taking a draft change back out: `canon subject unadopt`
|
|
388
400
|
|
|
389
|
-
```
|
|
390
|
-
canon subject unadopt <
|
|
401
|
+
```text
|
|
402
|
+
canon subject unadopt <S> --change-id <change> --json
|
|
391
403
|
```
|
|
392
404
|
|
|
393
405
|
Removes the link on both records and keeps the change and its brief, so the
|
|
@@ -407,7 +419,7 @@ it adopted:
|
|
|
407
419
|
canon change new add-login --subject-id auth --title "Add login"
|
|
408
420
|
```
|
|
409
421
|
|
|
410
|
-
```
|
|
422
|
+
```output
|
|
411
423
|
canon change new: wrote .canon/changes/add-login/brief.md
|
|
412
424
|
canon change new: recorded change `add-login` adopted into subject `auth` — written directly; nothing to promote
|
|
413
425
|
```
|
|
@@ -420,7 +432,7 @@ canon change new: recorded change `add-login` adopted into subject `auth` — wr
|
|
|
420
432
|
the headings in the repo's `language:`), and a comment naming
|
|
421
433
|
`canon brief approve` as where the human's answer is recorded, so the
|
|
422
434
|
file starts unapproved. The intent section's first paragraph holds the
|
|
423
|
-
title, which imports as the change summary. `--kind chore` writes the
|
|
435
|
+
title, which imports as the change summary. `--change-kind chore` writes the
|
|
424
436
|
short chore brief instead (intent, category, invariants, checks, out of
|
|
425
437
|
scope; see `canon brief` below). No `tasks.md` is written:
|
|
426
438
|
`canon status` lists each flow step's scenarios instead.
|
|
@@ -440,7 +452,7 @@ canon change new: recorded change `add-login` adopted into subject `auth` — wr
|
|
|
440
452
|
cannot be written atomically. If the change record fails after the
|
|
441
453
|
subject record was written, the command exits `2`, keeps the change
|
|
442
454
|
dir and that one subject record, and prints the repair, `canon ingest
|
|
443
|
-
plans && canon subject adopt <
|
|
455
|
+
plans && canon subject adopt <id> --change-id <slug>`, which completes
|
|
444
456
|
the link and is safe to rerun.
|
|
445
457
|
- **Refuses** with exit `2`, writing nothing, when the subject does not
|
|
446
458
|
exist, or when the slug already has a `.canon/changes/<slug>` dir
|
|
@@ -448,8 +460,8 @@ canon change new: recorded change `add-login` adopted into subject `auth` — wr
|
|
|
448
460
|
|
|
449
461
|
A `tasks.md` is an optional work note canon never writes and nothing
|
|
450
462
|
gates on. If one exists, rows added as `- [ ] <n> <title>` are flipped with
|
|
451
|
-
`canon
|
|
452
|
-
--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
|
|
453
465
|
`canon ingest plans` run.
|
|
454
466
|
|
|
455
467
|
A change from an external plan (an openspec change listed under
|
|
@@ -461,15 +473,19 @@ points at the external document and, once the human answers, the
|
|
|
461
473
|
pointer `brief.md` is not a change of its own: the native reader skips
|
|
462
474
|
it, so the external source keeps the change, its summary and its tasks.
|
|
463
475
|
|
|
464
|
-
|
|
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`).
|
|
465
479
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
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>"
|
|
470
486
|
```
|
|
471
487
|
|
|
472
|
-
Without
|
|
488
|
+
Without the change operand, the repo's only live change is read. The brief is the
|
|
473
489
|
PRD `canon change new` writes; sections are found by their
|
|
474
490
|
`<!-- canon:section <key> role=… -->` marker, never by heading text. A
|
|
475
491
|
brief without markers (written before 0.19) checks as `brief.legacy`, an
|
|
@@ -490,7 +506,7 @@ advisory, and is read as before.
|
|
|
490
506
|
asides, dates and decision notes, stock vocabulary, Korean endings and
|
|
491
507
|
length budgets, in the normative sections plus Intent and Questions;
|
|
492
508
|
sentence, paragraph and key-sentence rules in normative sections.
|
|
493
|
-
Never an authorship verdict. `
|
|
509
|
+
Never an authorship verdict. `canon skills show brief-polish` has each rule.
|
|
494
510
|
- **Waivers**: `<!-- canon:waive <rule-id> <section-key> "<reason>" -->`,
|
|
495
511
|
one rule in one section, reason required; add `match="<text>"` to waive
|
|
496
512
|
only the findings whose matched text contains it. Listed in the output.
|
|
@@ -505,16 +521,20 @@ advisory, and is read as before.
|
|
|
505
521
|
The optional refinement passes that fix findings before the human stop are
|
|
506
522
|
listed in `role-planner.md` in this directory.
|
|
507
523
|
|
|
508
|
-
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
|
|
509
525
|
built or kept, never what it does. Its brief is intent, category,
|
|
510
526
|
invariants, checks, out of scope; it adds no scenarios, and its evidence
|
|
511
527
|
is the subject's suite run again at the chore commit with
|
|
512
|
-
`canon evidence add --all-scenarios --report <kind>:<path
|
|
528
|
+
`canon evidence add --all-scenarios --report <kind>:<path>`. That
|
|
513
529
|
supersedes the old evidence; the pinned reviews stay current while the
|
|
514
530
|
verdicts and checks are the same, so the chore itself is reviewed once with
|
|
515
|
-
`canon review
|
|
531
|
+
`canon review change <slug>` before it ships. Work that changes
|
|
516
532
|
behavior is a feature change, never a chore.
|
|
517
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
|
+
|
|
518
538
|
## Where are we: `canon status`
|
|
519
539
|
|
|
520
540
|
```bash
|
|
@@ -544,7 +564,7 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
544
564
|
the next transition will require; `N stale review(s)` and `N unsigned
|
|
545
565
|
review(s)` (printed when non-zero) count scenarios whose review went
|
|
546
566
|
stale or whose latest reviews are all `indeterminate`/`unavailable`
|
|
547
|
-
(see `canon-review`), and the `canon review
|
|
567
|
+
(see `canon-review`), and the `canon review scenario` step names both. With
|
|
548
568
|
`require_review` on, a `warning:` line counts the in-effect reviews that
|
|
549
569
|
predate 0.23 review pinning and wait for `canon migrate`.
|
|
550
570
|
- **Brief** (0.16, 0.17, 0.19) — for each `building`, `verifying` or `shipped`
|
|
@@ -573,7 +593,7 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
573
593
|
line inside an external `proposal.md` is not read. Before that canon
|
|
574
594
|
file exists, an external openspec `proposal.md` under the plan sources
|
|
575
595
|
(the first source holding the change; with no `plans:` section, the
|
|
576
|
-
`openspec` source rooted at the repo that `canon
|
|
596
|
+
`openspec` source rooted at the repo that `canon task done` also falls
|
|
577
597
|
back to) still makes the brief one to answer, and the line reads
|
|
578
598
|
``brief: not approved (.canon/changes/<c>/brief.md does not exist yet:
|
|
579
599
|
change `<c>` comes from the external plan <proposal>, which canon reads
|
|
@@ -592,15 +612,15 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
592
612
|
(owned scenarios, verdicts, required cases, audits, and, where
|
|
593
613
|
`require_review` covers `shipped`, reviews and open blockers under
|
|
594
614
|
`block_on_findings`; a gap its waiver recorded is not counted), prints
|
|
595
|
-
``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>` ``,
|
|
596
616
|
carries `red: [...]` in `--json`, and that reopen is its only `next:`
|
|
597
617
|
step. Open blockers count against every subject a change belongs to.
|
|
598
618
|
- **Unowned** — scenarios with no `@subject:` tag.
|
|
599
619
|
- **Audits** — how many scenarios are sampled for
|
|
600
620
|
`spec_coverage.require_audit`, confirmed, owed (no audit or
|
|
601
621
|
`indeterminate`) and refuted (`false-success`). An owed or
|
|
602
|
-
refuted audit adds a `next:` step suggesting `canon evidence
|
|
603
|
-
|
|
622
|
+
refuted audit adds a `next:` step suggesting `canon evidence audit`
|
|
623
|
+
(recorded from an external evaluator; canon never runs
|
|
604
624
|
one).
|
|
605
625
|
- **Brief overrides** — a `warning:` line per evidence record attested
|
|
606
626
|
with `canon evidence add --override-reason` while its subject's brief
|
|
@@ -608,7 +628,7 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
608
628
|
reason (see `canon-gate`).
|
|
609
629
|
- **`next:`** — at most five steps, each with a one-line reason; the
|
|
610
630
|
rest are counted. Rules, in order: no `canon.yaml` → `canon init`; an
|
|
611
|
-
unreadable one → `canon init --check
|
|
631
|
+
unreadable one → `canon init --check`; a scenario tagged with a
|
|
612
632
|
subject that has no record → `canon subject new <that id>`; no subject
|
|
613
633
|
at all → `canon subject new`; subjects and `.feature` scenarios but no
|
|
614
634
|
scenario records → `canon inventory sync` (status reads the index as a
|
|
@@ -617,15 +637,15 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
617
637
|
first, then building, specced, proposed, shipped: an unapproved brief
|
|
618
638
|
(building and later, and proposed once its change has a brief)
|
|
619
639
|
→ the human step below, which is then the subject's
|
|
620
|
-
only step; no scenario → `canon scenario new
|
|
640
|
+
only step; no scenario → `canon scenario new --subject-id <id>` (and, when no
|
|
621
641
|
`.feature` file holds a scenario yet, `canon feature new` first, unless
|
|
622
642
|
every subject waits on its brief); a missing case → `canon scenario new
|
|
623
643
|
<surface>.<next nn> … --case <case>`; (building and later) an
|
|
624
644
|
unevidenced or divergent scenario → `canon evidence add --scenario-id
|
|
625
645
|
…` (its reason adds "then `canon gate promote`" only under
|
|
626
|
-
`write.promote: manual`); an open blocker → `canon finding close
|
|
627
|
-
due, unreviewed, evidenced scenario → `canon review
|
|
628
|
-
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>`.
|
|
629
649
|
Last, unowned scenarios → `canon status`, after tagging them in their
|
|
630
650
|
`.feature` files (status re-indexes the edit; no sync step). With more
|
|
631
651
|
than one `specs.roots[]` entry, every suggested `canon scenario new`
|
|
@@ -633,8 +653,8 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
633
653
|
(the reason lists the roots) for a subject that owns no scenario yet.
|
|
634
654
|
- **The one human step.** Every step is the agent's to run except one,
|
|
635
655
|
and it comes only once the brief is clean: while `canon brief check
|
|
636
|
-
|
|
637
|
-
`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`
|
|
638
658
|
(`role: planner`) instead. A subject whose brief is enforced (its
|
|
639
659
|
newest change's canon
|
|
640
660
|
`brief.md` has no `Approved:` line, or it has no canon `brief.md` yet
|
|
@@ -646,16 +666,16 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
646
666
|
and the approval is never assumed: `canon evidence add` refuses <id>'s
|
|
647
667
|
scenarios and tasks until it is recorded; once the human answers,
|
|
648
668
|
<record> (one call records the brief and the policy approval)``, where
|
|
649
|
-
`<record>` is ``record their words with `canon brief approve
|
|
650
|
-
<c> --
|
|
669
|
+
`<record>` is ``record their words with `canon brief approve
|
|
670
|
+
<c> --approver <the human> --note "<their words>"` ``, or, for an external
|
|
651
671
|
change, ``create <brief> holding a `Source: <proposal>` line, then
|
|
652
|
-
record their words with `canon brief approve
|
|
672
|
+
record their words with `canon brief approve <c> --approver <the
|
|
653
673
|
human> --note "<their words>"` ``; for a brief edited after its
|
|
654
|
-
approval, ``re-approve with `canon brief approve
|
|
674
|
+
approval, ``re-approve with `canon brief approve <c>` ``.
|
|
655
675
|
It is the subject's only step, whatever its status: nothing suggests
|
|
656
676
|
`canon feature new`, `canon scenario new`, `canon evidence add`, a
|
|
657
677
|
review or a move-on for it before the human answers, and
|
|
658
|
-
`canon subject
|
|
678
|
+
`canon subject move <id> --to shipped` refuses on the same check. The
|
|
659
679
|
approval is never assumed. A subject with no brief to answer gets no human step;
|
|
660
680
|
its `brief:` line says
|
|
661
681
|
`not approved (no adopted change; advisory, nothing to approve yet)` or
|
|
@@ -663,26 +683,26 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
663
683
|
approve yet)`` and nothing is withheld (a `proposed` subject with no
|
|
664
684
|
brief, and a `specced` subject, show no `brief:` line at all). Once nothing blocks, a
|
|
665
685
|
ship-ready verifying subject gets the agent's own
|
|
666
|
-
`canon subject
|
|
686
|
+
`canon subject move <id> --to shipped`; status never asks a human to ship.
|
|
667
687
|
|
|
668
688
|
Status fails closed rather than suggest progress the gate would refuse:
|
|
669
689
|
|
|
670
690
|
- When `scenario`, `subject`, `review` or `finding` routes away from the
|
|
671
691
|
`local` rung (the only rung status and the gate read), its records
|
|
672
692
|
would read as empty. The only `next:` step is
|
|
673
|
-
`canon init --check
|
|
693
|
+
`canon init --check`, with the reason naming the
|
|
674
694
|
`routing.<kind>: local` setting to restore.
|
|
675
695
|
- When `spec_coverage` is present but unusable, `canon gate check`
|
|
676
696
|
refuses. The first `next:` step is `canon gate check`, with the reason
|
|
677
697
|
naming the section to fix, and no subject is suggested to move to its
|
|
678
698
|
next status until it parses.
|
|
679
699
|
|
|
680
|
-
`--json` prints one object:
|
|
700
|
+
`--json` prints the `{ok, data, meta}` envelope; `data` is one object:
|
|
681
701
|
|
|
682
702
|
```json
|
|
683
703
|
{
|
|
684
704
|
"statusVersion": 3,
|
|
685
|
-
"canonVersion": "0.
|
|
705
|
+
"canonVersion": "0.28.0",
|
|
686
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 } } },
|
|
687
707
|
"warnings": [],
|
|
688
708
|
"subjects": [
|
|
@@ -693,17 +713,30 @@ Status fails closed rather than suggest progress the gate would refuse:
|
|
|
693
713
|
"reviewed": 1, "staleReviews": 0, "unsignedReviews": 0, "reviewDue": true, "openBlockers": 0, "missingCases": [],
|
|
694
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" } }
|
|
695
715
|
],
|
|
696
|
-
"unowned": ["cart.promo.01"]
|
|
697
|
-
"next": [
|
|
698
|
-
{ "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" },
|
|
699
|
-
{ "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" },
|
|
700
|
-
{ "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" },
|
|
701
|
-
{ "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" }
|
|
702
|
-
],
|
|
703
|
-
"nextOmitted": 0
|
|
716
|
+
"unowned": ["cart.promo.01"]
|
|
704
717
|
}
|
|
705
718
|
```
|
|
706
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
|
+
|
|
707
740
|
Each `missingCases` entry is `{ "projectId", "surface", "case" }`: the
|
|
708
741
|
spec root, the `<area>.<surface>`, and the required case it lacks.
|
|
709
742
|
|
|
@@ -726,7 +759,7 @@ that the `Approved:` line carries no digest, `findings` is
|
|
|
726
759
|
only), and `flow` lists each flow step as `{ "id", "change",
|
|
727
760
|
"scenarios": [{ id, title, failure, evidenced, review }], "gaps" }`.
|
|
728
761
|
|
|
729
|
-
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
|
|
730
763
|
line) or `human` (its `command` says what to get from the human).
|
|
731
764
|
|
|
732
765
|
`policy.spec_coverage` has the shape `canon context --json` prints
|
|
@@ -737,15 +770,19 @@ in 0.16, when `next[].command` stopped always being a command line
|
|
|
737
770
|
0.17, when `brief.proposal` was removed: the canon `brief.md` is
|
|
738
771
|
`brief.brief`, with `briefExists` and `source`.
|
|
739
772
|
|
|
740
|
-
`subject new`, `adopt` and `
|
|
773
|
+
`subject new`, `adopt`, `unadopt` and `move` write their records directly; the
|
|
741
774
|
human-readable success line ends `— written directly; nothing to
|
|
742
775
|
promote` (`--json` prints the record and nothing else).
|
|
743
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
|
+
|
|
744
781
|
## Reading the per-domain management view
|
|
745
782
|
|
|
746
783
|
```bash
|
|
747
784
|
canon query --kind subject --domain dev --status building
|
|
748
|
-
canon report --repo .
|
|
785
|
+
canon report build --repo . # renders the "Subjects" panel
|
|
749
786
|
```
|
|
750
787
|
|
|
751
788
|
- `canon query --kind subject [--domain <d>] [--status <s>]` — the
|
|
@@ -756,4 +793,4 @@ canon report --repo . # renders the "Subjects" panel
|
|
|
756
793
|
`covered_scenarios`), where `covered_scenarios` counts linked scenarios
|
|
757
794
|
carrying a latest non-`Divergent` verdict — the same coverage the
|
|
758
795
|
shipped gate enforces, surfaced read-only. Also exported by `canon
|
|
759
|
-
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
|