@journeykit/canon 0.35.0 → 0.36.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 +29 -19
- package/dist/skills/reference/canon-authoring.md +3 -2
- package/dist/skills/reference/canon-gate.md +18 -14
- package/dist/skills/reference/canon-inventory.md +3 -1
- package/dist/skills/reference/canon-policy.md +3 -3
- package/dist/skills/reference/canon-report-dashboard.md +5 -5
- package/dist/skills/reference/canon-review.md +7 -6
- package/dist/skills/reference/canon-storage.md +2 -2
- package/dist/skills/reference/canon-subject.md +20 -19
- package/dist/skills/reference/role-implementer.md +5 -5
- package/dist/skills/reference/role-orchestrator.md +22 -21
- package/dist/skills/reference/role-planner.md +7 -7
- package/dist/skills/reference/role-reviewer.md +7 -7
- package/man/canon-adapter-authorize.1 +2 -2
- package/man/canon-adapter-validate.1 +2 -2
- package/man/canon-adapter.1 +2 -2
- package/man/canon-artifacts-move.1 +6 -6
- package/man/canon-artifacts-store.1 +2 -2
- package/man/canon-artifacts-verify.1 +2 -2
- package/man/canon-artifacts.1 +2 -2
- package/man/canon-brief-approve.1 +5 -4
- package/man/canon-brief-check.1 +2 -2
- package/man/canon-brief-show.1 +2 -2
- package/man/canon-brief.1 +2 -2
- package/man/canon-change-new.1 +2 -2
- package/man/canon-change.1 +2 -2
- package/man/canon-completion.1 +2 -2
- package/man/canon-context-pack-add.1 +2 -2
- package/man/canon-context-pack-show.1 +2 -2
- package/man/canon-context-pack-verify.1 +2 -2
- package/man/canon-context-pack.1 +2 -2
- package/man/canon-context.1 +2 -2
- package/man/canon-dashboard.1 +2 -2
- package/man/canon-demo-init.1 +2 -2
- package/man/canon-demo-review.1 +2 -2
- package/man/canon-demo.1 +2 -2
- package/man/canon-dispatch-begin.1 +2 -2
- package/man/canon-dispatch-diff.1 +2 -2
- package/man/canon-dispatch-end.1 +2 -2
- package/man/canon-dispatch.1 +2 -2
- package/man/canon-divergence-accept.1 +2 -2
- package/man/canon-divergence-add.1 +3 -3
- package/man/canon-divergence-defer.1 +3 -3
- package/man/canon-divergence-list.1 +2 -2
- package/man/canon-divergence-resolve.1 +3 -3
- package/man/canon-divergence.1 +2 -2
- package/man/canon-evidence-add.1 +5 -5
- package/man/canon-evidence-approval-payload.1 +3 -3
- package/man/canon-evidence-audit.1 +4 -4
- package/man/canon-evidence.1 +2 -2
- package/man/canon-export.1 +2 -2
- package/man/canon-feature-new.1 +2 -2
- package/man/canon-feature.1 +2 -2
- package/man/canon-finding-add.1 +3 -3
- package/man/canon-finding-close.1 +2 -2
- package/man/canon-finding-list.1 +2 -2
- package/man/canon-finding.1 +2 -2
- package/man/canon-format.1 +2 -2
- package/man/canon-gate-check.1 +2 -2
- package/man/canon-gate-install-hooks.1 +2 -2
- package/man/canon-gate-promote.1 +2 -2
- package/man/canon-gate.1 +2 -2
- package/man/canon-ingest-plans.1 +2 -2
- package/man/canon-ingest-records.1 +2 -2
- package/man/canon-ingest-sessions.1 +2 -2
- package/man/canon-ingest.1 +2 -2
- package/man/canon-init.1 +2 -2
- package/man/canon-inventory-sync.1 +2 -2
- package/man/canon-inventory.1 +2 -2
- package/man/canon-ledger-compact.1 +5 -5
- package/man/canon-ledger.1 +3 -3
- package/man/canon-migrate.1 +8 -8
- package/man/canon-plugin-sync.1 +2 -2
- package/man/canon-plugin.1 +2 -2
- package/man/canon-policy-approve.1 +2 -2
- package/man/canon-policy-show.1 +2 -2
- package/man/canon-policy.1 +2 -2
- package/man/canon-prompt-add.1 +2 -2
- package/man/canon-prompt-show.1 +2 -2
- package/man/canon-prompt.1 +2 -2
- package/man/canon-purge.1 +7 -7
- package/man/canon-query.1 +2 -2
- package/man/canon-regime-show.1 +2 -2
- package/man/canon-regime.1 +2 -2
- package/man/canon-report-build.1 +2 -2
- package/man/canon-report-check.1 +2 -2
- package/man/canon-report-snapshot.1 +2 -2
- package/man/canon-report.1 +2 -2
- package/man/canon-retrieve.1 +2 -2
- package/man/canon-review-change.1 +3 -3
- package/man/canon-review-scenario.1 +3 -3
- package/man/canon-review.1 +2 -2
- package/man/canon-scenario-new.1 +2 -2
- package/man/canon-scenario.1 +2 -2
- package/man/canon-schema.1 +10 -4
- package/man/canon-search.1 +2 -2
- package/man/canon-selftest.1 +2 -2
- package/man/canon-skills-check.1 +2 -2
- package/man/canon-skills-doctor.1 +2 -2
- package/man/canon-skills-install.1 +2 -2
- package/man/canon-skills-show.1 +2 -2
- package/man/canon-skills.1 +2 -2
- package/man/canon-status.1 +2 -2
- package/man/canon-strategy-approval-payload.1 +2 -2
- package/man/canon-strategy-promote.1 +2 -2
- package/man/canon-strategy-rollback.1 +2 -2
- package/man/canon-strategy.1 +2 -2
- package/man/canon-subject-adopt.1 +2 -2
- package/man/canon-subject-move.1 +2 -2
- package/man/canon-subject-new.1 +2 -2
- package/man/canon-subject-show.1 +2 -2
- package/man/canon-subject-unadopt.1 +3 -3
- package/man/canon-subject.1 +2 -2
- package/man/canon-task-done.1 +2 -2
- package/man/canon-task.1 +2 -2
- package/man/canon-tier-age.1 +5 -5
- package/man/canon-tier.1 +2 -2
- package/man/canon-trace.1 +2 -2
- package/man/canon.1 +3 -3
- package/package.json +4 -4
package/dist/skills/SKILL.src.md
CHANGED
|
@@ -49,15 +49,15 @@ a feature, a one-line request included. A human is needed once per scope:
|
|
|
49
49
|
`canon brief approve <slug> <slug> --approver <their name> --note "<their words>" --relayed-via <ask|AskUserQuestion|chat> --actor <your actor id> --digest <slug>=<digest shown>`
|
|
50
50
|
(one or more slugs, each with its own `--digest`, one answer for all, nothing written if any is refused).
|
|
51
51
|
The `Approved:` line then carries `(relayed by <role> <actor> via <tool>)`.
|
|
52
|
-
A digest that no longer matches the brief is `
|
|
53
|
-
it again. Without `--relayed-via` an agent role gets `
|
|
52
|
+
A digest that no longer matches the brief is `RELAY_DIGEST_STALE`: show
|
|
53
|
+
it again. Without `--relayed-via` an agent role gets `ACTOR_DENIED`, and so
|
|
54
54
|
does a repo whose `canon.yaml` says `approval: { relay: deny }`: then the
|
|
55
55
|
human runs the call themselves. Never remove or unset your role
|
|
56
56
|
(`env -u CANON_ROLE`, dropping `--as`) to run it yourself.
|
|
57
57
|
Never edit the policy to make the gate pass: a policy that differs from
|
|
58
|
-
the approved one fails closed (`
|
|
58
|
+
the approved one fails closed (`POLICY_APPROVAL_STALE`, not
|
|
59
59
|
waivable); stop and ask the human. A brief edited after its
|
|
60
|
-
approval is not approved (`
|
|
60
|
+
approval is not approved (`BRIEF_APPROVAL_STALE`): it needs a new
|
|
61
61
|
answer. The ship guard and `canon evidence add` refuse an unapproved or
|
|
62
62
|
edited brief, but those are backstops: the stop itself is at step 1.
|
|
63
63
|
- **Approval is scoped.** Evidence for a scenario tagged `@flow:<change>.<F-id>`
|
|
@@ -120,7 +120,7 @@ the record carries, so a review of a working tree survives the commit made
|
|
|
120
120
|
from it; a review is judged by what it pins (the scenario and what its
|
|
121
121
|
evidence says), never by the commit or the code tree. Outside a git work
|
|
122
122
|
tree, or in a repo with no commits, a command that needs a commit refuses
|
|
123
|
-
`
|
|
123
|
+
`COMMIT_REQUIRED`.
|
|
124
124
|
|
|
125
125
|
### Evidence follows the code
|
|
126
126
|
|
|
@@ -181,7 +181,7 @@ names the stores not read.
|
|
|
181
181
|
|
|
182
182
|
canon cannot detect a role; you declare it. Pass `--as <role>` or set
|
|
183
183
|
`CANON_ROLE=planner|implementer|reviewer|orchestrator`; a flag wins over the
|
|
184
|
-
variable, and an unknown value is refused (`
|
|
184
|
+
variable, and an unknown value is refused (`ROLE_INVALID`).
|
|
185
185
|
|
|
186
186
|
- **A role is set, or you were spawned as one:** load only
|
|
187
187
|
`canon skills show role-<role>` and do that role's steps. `canon status`
|
|
@@ -211,17 +211,27 @@ A role is guidance, not enforcement: `--role` on `evidence add` and
|
|
|
211
211
|
your complete command set, every option of every leaf included. Run `canon schema <command> --json` only for a
|
|
212
212
|
command it does not list, or after a `USAGE` refusal (read `error.field`
|
|
213
213
|
and `error.expected` first). `canon schema --json` is the tree of every group and command
|
|
214
|
-
with its `effect` and `x-canon.roles` (`--as <role>` lists one role's, and `x-canon.as` names it);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
214
|
+
with its `effect` and `x-canon.roles` (`--as <role>` lists one role's, and `x-canon.as` names it);
|
|
215
|
+
its `options` define once the options that two or more commands share (`--repo`, `--as`, `--actor`, …)
|
|
216
|
+
and a command names them. `canon schema <group> --json` lists a group's
|
|
217
|
+
commands; `canon schema <command> --json` is the call surface of one command and nothing
|
|
218
|
+
else: `options` (each name of a tree option, or an object with `valueType`, a typed
|
|
219
|
+
`default`, `possibleValues`, `env`, `flagOnly`), `operands`, `constraints`, `validators`, `errors`,
|
|
220
|
+
`outputs`, `input` (what one `--input` document is and a complete `example`) and `examples`.
|
|
221
|
+
A member at its default is absent. `--json` is always accepted, `--input` when the command
|
|
222
|
+
has `input`, `--fields` when an output has `fields`, and the codes `USAGE` (with canon's
|
|
223
|
+
finer `*_INVALID`/`*_REQUIRED` argument codes), `INTERNAL`, `INPUT_*`, `BATCH_INCOMPLETE`,
|
|
224
|
+
`PLAN_STALE` (with `--commit`) and `CURSOR_INVALID` (with `--cursor`) can come without
|
|
225
|
+
being listed. `--commit` and `--plan-digest` are listed on exactly the commands that offer
|
|
226
|
+
them: a command that lists `commit` previews on a bare run. `canon schema <command> --schemas --json`
|
|
227
|
+
gives the JSON Schema of each report in `schemas`, `Input` (the schema of one `--input`
|
|
228
|
+
document) and `rejects` (what each validator refuses, in order); `#/schemas/<Name>` in
|
|
229
|
+
the command document resolves there. The first line of every `--help` points at it.
|
|
220
230
|
- Pass `--json` and read stdout as one document, nothing on stderr. Success is
|
|
221
231
|
`{"ok":true,"data":…,"meta":…}`; failure is
|
|
222
232
|
`{"ok":false,"error":{…},"meta":…}` (a check that fails keeps its report in
|
|
223
233
|
`data`). `meta` carries `tool`, `toolVersion`, `contract` (`atip/1`),
|
|
224
|
-
`contractVersion` (`1.
|
|
234
|
+
`contractVersion` (`1.4`), `schemaVersion`,
|
|
225
235
|
`command`, and when present `next`, `warnings` (`[{code, message}]`) and
|
|
226
236
|
`page`; a repeated write that changed nothing reports `data.unchanged: true`.
|
|
227
237
|
Absent members are omitted, never `null` or `[]` (a value you sent empty comes back as `received: ""`).
|
|
@@ -243,7 +253,7 @@ A role is guidance, not enforcement: `--role` on `evidence add` and
|
|
|
243
253
|
- **Exit codes:** only 0, 1 and 2 exist: 0 ok; 1 the command ran and its answer
|
|
244
254
|
is negative or incomplete (a failed check, a violation, `unverifiable` when
|
|
245
255
|
nothing was examined, a partly failed batch); 2 refused to run (usage,
|
|
246
|
-
`
|
|
256
|
+
`CONFIG_REQUIRED`, an id or file that does not exist, an invalid argument).
|
|
247
257
|
A refusal leaves the tree unchanged.
|
|
248
258
|
- Repeating a write is safe: a record that already exists with identical
|
|
249
259
|
content is reported `unchanged` (`data.unchanged`), not duplicated.
|
|
@@ -258,13 +268,13 @@ A role is guidance, not enforcement: `--role` on `evidence add` and
|
|
|
258
268
|
has blockers; the approval step appears only when the brief is clean and
|
|
259
269
|
unapproved.
|
|
260
270
|
- Page long lists with `--limit <n>` and `--cursor <nextCursor>` (`--all`
|
|
261
|
-
for everything); a cursor holds only for the call that issued it, so change nothing but `--limit`, `--all`, `--fields` and `--json`, and keep `CANON_ROLE` as it was (`CURSOR_INVALID` with `error.reason` `ARGUMENTS_CHANGED`
|
|
271
|
+
for everything); a cursor holds only for the call that issued it, so change nothing but `--limit`, `--all`, `--fields` and `--json`, and keep `CANON_ROLE` as it was; the next call is `meta.next[0].argv` as it stands (the arguments you gave and the cursor, never a default). An argument you add is a change even when it states the default (`--repo .`): canon binds an explicit default to the cursor (`CURSOR_INVALID` with `error.reason` `ARGUMENTS_CHANGED`, `error.field` `--cursor`; `FOREIGN` for a cursor of another command or another canon version: start again from the first page). `--limit`, `--cursor`, `--all` and `--fields` are flags: an `--input` document key of that name is `INPUT_INVALID` with `reason` `FLAG_ONLY_KEY`. Project fields with `--fields a,b`
|
|
262
272
|
(`status`, `export`, `query`, `finding list`, `divergence list`, `context`): the paths `canon schema <command> --json` lists under `outputs[].fields`, spelled as the answer spells them; `meta.fields` lists what was kept.
|
|
263
273
|
- `--override-reason <text>` is the only way to proceed past a waivable
|
|
264
274
|
refusal; it is recorded, echoed in `data.overrides[]` and listed by `status`
|
|
265
275
|
for the human. There is no `--force`. `brief approve`, `policy approve`,
|
|
266
276
|
`divergence accept` and the `migrate --commit` that re-binds `Approved:`
|
|
267
|
-
lines record a human's decision and refuse every agent role (`
|
|
277
|
+
lines record a human's decision and refuse every agent role (`ACTOR_DENIED`)
|
|
268
278
|
unless they record the explicit answer the human gave you, with
|
|
269
279
|
`--relayed-via <tool>` (show, ask, record, as for the brief; `canon skills
|
|
270
280
|
show role-planner`); never unset your role to run one.
|
|
@@ -281,8 +291,8 @@ before anything is written, and that check reads no state: an invalid element wr
|
|
|
281
291
|
its own code, `error.field` pointing at `/<i>/<key>` and no `data`. An element that fails when it runs (the object
|
|
282
292
|
it names does not exist) stops the batch: exit 1, `BATCH_INCOMPLETE`, `error.field` exactly `/<i>`, the element
|
|
283
293
|
`failed` with its own `error` (no `data`), the later ones `skipped`, and the earlier ones done (not undone). Re-running the same batch reports the finished elements
|
|
284
|
-
`unchanged`. A typo in a key is refused (`INPUT_INVALID`, `field` naming the key), never dropped; a document with several problems reports them all, the first as the error and every one in `error.details` in the order the document wrote its keys, and a value outside a closed set is `INPUT_INVALID` too (`reason` `INVALID_VALUE`, `field` the key), not `USAGE`. Every non-empty line of an NDJSON file is a document (a `#` line is not a comment). Integers compare by number: `1`, `"1"` and `--round +1` are one value,
|
|
285
|
-
`canon schema <command> --json` shows the leaf's `input
|
|
294
|
+
`unchanged`. A typo in a key is refused (`INPUT_INVALID`, `field` naming the key), never dropped; a document with several problems reports them all, the first as the error (`field` is the first `error.details` entry's) and every one in `error.details` in the order the document wrote its keys, and a value outside a closed set is `INPUT_INVALID` too (`reason` `INVALID_VALUE`, `field` the key), not `USAGE`. Every non-empty line of an NDJSON file is a document (a `#` line is not a comment). Integers compare by number: `1`, `"1"` and `--round +1` are one value, `"+1"`, `"0x1"` and `1.0` in a document are `INVALID_VALUE`, and an integer beyond ±9007199254740991 is refused as a number and as a string, in a document (`INVALID_VALUE`, `field` its pointer) and on the command line (`USAGE`). `--input` may give a required option and the command line only the operand; an option given in both with different values is `INPUT_CONFLICT` at the key's pointer. A repeatable option's none is the key left out: `[]` is refused (`INPUT_INVALID`, `reason` `INVALID_VALUE`, `field` the key's pointer), as is `[]` for any other option and for `operands`.
|
|
295
|
+
`canon schema <command> --json` shows the leaf's `input` (what one document is, and a complete `example`); `canon schema <command> --schemas --json` gives `Input`, the JSON Schema of one document.
|
|
286
296
|
|
|
287
297
|
```text
|
|
288
298
|
canon scenario new --input '[{"operands":["auth.login.01"],"title":"Logs in","case":"happy"},{"operands":["auth.login.02"],"title":"Wrong password","case":"failure"}]'
|
|
@@ -338,7 +348,7 @@ canon init --providers=claude,codex
|
|
|
338
348
|
canon skills install
|
|
339
349
|
# any subset or none; rewrites skills.providers
|
|
340
350
|
canon skills install --providers=claude,codex,omp,pi
|
|
341
|
-
# read-only drift check; exit 1 (
|
|
351
|
+
# read-only drift check; exit 1 (SKILLS_CHECK_FAILED) names each orphan, a projected file the bundle no longer ships
|
|
342
352
|
canon skills check
|
|
343
353
|
# diagnostics, incl. a stray canon projection for an unselected provider and a projection a formatter rewrote, and `orphan:` lines for projected files the bundle no longer ships; never deletes user files
|
|
344
354
|
canon skills doctor
|
|
@@ -114,8 +114,9 @@ Fix it and the next command indexes the files (see `canon-inventory`).
|
|
|
114
114
|
Many scenarios at once: `--input` takes inline JSON, a file or `-`. An
|
|
115
115
|
array (or NDJSON) is a batch, validated whole before anything is written;
|
|
116
116
|
each element holds `operands` (the scenario tag) and the other options as
|
|
117
|
-
camelCase keys. `canon schema scenario new --json` shows `input
|
|
118
|
-
|
|
117
|
+
camelCase keys. `canon schema scenario new --json` shows `input` (its limits and a complete
|
|
118
|
+
`example`); `canon schema scenario new --schemas --json` gives `Input`, the schema of one
|
|
119
|
+
document. There is no `--from`.
|
|
119
120
|
|
|
120
121
|
```text
|
|
121
122
|
canon scenario new --input '[{"operands":["checkout.cart.01"],"title":"Adding an item raises the count","subject":"checkout-core","lane":"behavior","case":"happy"},{"operands":["checkout.cart.04"],"title":"Adding an out-of-stock item is refused","subject":"checkout-core","lane":"behavior","case":"failure"}]'
|
|
@@ -28,7 +28,7 @@ Every violation carries one of these stable, grep-able strings:
|
|
|
28
28
|
| `malformed-evidence` | A candidate record doesn't parse, is misfiled, or carries an unparseable interim tag. Malformed evidence is no evidence. |
|
|
29
29
|
| `flagged` | The human-only `flagged` overlay is set — never green regardless of passing evidence. |
|
|
30
30
|
| `unevidenced-flip` | `canon task done <task_id>` was asked to flip a checkbox with no matching, non-`Divergent` evidence record. |
|
|
31
|
-
| `fabricated-evidence` | An evidence note contains a blocklisted marker (`"would pass"`, `"TBD"`, `"n/a"`) standing as a whole word — never inside a path, a file name, a URL or a longer word, so `pack.json/atlas` is not `n/a` — or a bare `verified` claim with no attached command result. `canon evidence add` refuses such a note before writing (refused with `fabricated-evidence`, exit
|
|
31
|
+
| `fabricated-evidence` | An evidence note contains a blocklisted marker (`"would pass"`, `"TBD"`, `"n/a"`) standing as a whole word — never inside a path, a file name, a URL or a longer word, so `pack.json/atlas` is not `n/a` — or a bare `verified` claim with no attached command result. `canon evidence add` refuses such a note before writing (refused with `fabricated-evidence`, `EVIDENCE_NOTE_INVALID`, exit 2). |
|
|
32
32
|
| `open-blocker` | With `spec_coverage.require_review` set (and `block_on_findings`, the default), a Finding whose latest version is severity `blocker`, disposition `open`, on a change an in-scope subject adopted — or closed `fixed` while an evidenced scenario of the subject has no evidence recorded after the close (re-verification). Subject string `<change_id>#<round>.<seq>`. See `canon-review`. |
|
|
33
33
|
| `false-success` | The latest audit record (`canon evidence audit`) of a scenario says `refuted`: an external evaluator found a counterexample to the claimed success. Always on, regardless of policy or sampling, and takes precedence over any declared faithful verdict; only a newer audit (`confirmed` or `indeterminate`) clears it. The detail names the evaluator, its version, its sha256 and the counterexample paths. |
|
|
34
34
|
|
|
@@ -225,9 +225,9 @@ canon divergence accept cart.add.01 --project root --reason "known gap" --tracki
|
|
|
225
225
|
|
|
226
226
|
Accepting a scenario whose latest evidence is `divergent` as a known gap
|
|
227
227
|
limited by something outside the change is a human-only act: with a role
|
|
228
|
-
declared (`--as`, `CANON_ROLE`) the leaf is refused with `
|
|
228
|
+
declared (`--as`, `CANON_ROLE`) the leaf is refused with `ACTOR_DENIED`. It is
|
|
229
229
|
never a way to skip a fix.
|
|
230
|
-
Refused (`
|
|
230
|
+
Refused (`DIVERGENCE_CONFLICT` when the evidence is not divergent, `DIVERGENCE_DENIED` when the actor or session attested it) unless the latest verdict is
|
|
231
231
|
divergent and the session and actor differ from the evidence's. The record
|
|
232
232
|
pins that evidence: new evidence for the scenario, or `--expiry` passing,
|
|
233
233
|
ends it. While it holds, the ship guard counts the cell covered and
|
|
@@ -304,10 +304,10 @@ never rides along into a confirming audit. `--drop-attachment` and
|
|
|
304
304
|
The approval is never assumed: the agent writes the brief, shows it to the
|
|
305
305
|
human and asks, and builds nothing for that scope until the human answers.
|
|
306
306
|
`canon evidence add` is the backstop for that rule (0.16 M7). It
|
|
307
|
-
refuses (exit `
|
|
307
|
+
refuses (exit `2`, nothing staged or stored) while a subject the record
|
|
308
308
|
attests for has an enforced, unapproved brief: a change the record
|
|
309
309
|
answers to (below) has a canon `.canon/changes/<change>/brief.md` with no `Approved:`
|
|
310
|
-
line, was edited after its approval (`
|
|
310
|
+
line, was edited after its approval (`BRIEF_APPROVAL_STALE`), or
|
|
311
311
|
there is no canon `brief.md` yet but the change comes from an
|
|
312
312
|
external openspec plan with a `proposal.md` under the plan sources (the
|
|
313
313
|
check `canon status` and the ship guard use; see
|
|
@@ -461,7 +461,7 @@ mentions. Each bound case is its own attachment with its name and
|
|
|
461
461
|
outcome. `--report-case <name>` (repeatable; a Rust test by its
|
|
462
462
|
function name) ADDS cases; it never hides the scenario's own. No match,
|
|
463
463
|
or a `--report-case` naming no case, refuses (exit 2); a `faithful`
|
|
464
|
-
verdict when ANY bound case failed or was skipped refuses (exit
|
|
464
|
+
verdict when ANY bound case failed or was skipped refuses (exit 2). Files
|
|
465
465
|
must be inside the repository, are recorded by relative path, and are
|
|
466
466
|
stored (see Bound evidence stays provable).
|
|
467
467
|
|
|
@@ -517,8 +517,9 @@ report (a JUnit test case's `[[ATTACHMENT|path]]` lines, which Playwright's
|
|
|
517
517
|
JUnit reporter writes; a Cucumber JSON embedding), so a test's screenshot
|
|
518
518
|
stays with its scenario. A file the report does not name goes with
|
|
519
519
|
`--artifact <scenario-id>=<path>`; a bare `--artifact <path>` in a batch is
|
|
520
|
-
refused (`
|
|
521
|
-
outside the repo or oversized is refused
|
|
520
|
+
refused (`EVIDENCE_ARGUMENT_CONFLICT`). A report attachment that is missing,
|
|
521
|
+
outside the repo or oversized is refused (`EVIDENCE_BINDING_NOT_FOUND`,
|
|
522
|
+
`EVIDENCE_BINDING_DENIED`, `EVIDENCE_BINDING_INVALID`).
|
|
522
523
|
|
|
523
524
|
It is all or nothing: a claimed `faithful` verdict over a failed case,
|
|
524
525
|
a fabrication marker in `--summary`, an unapproved brief for any
|
|
@@ -536,13 +537,14 @@ or `-`; an array (or NDJSON) is a batch, validated element by element before
|
|
|
536
537
|
the first write (a refusal writes nothing, exit 2). Keys are the option
|
|
537
538
|
names in camelCase plus `operands`: one object per scenario, with
|
|
538
539
|
`scenario`, `class`, `ref` and `role`. `canon schema evidence add --json`
|
|
539
|
-
shows `input
|
|
540
|
+
shows `input` (its limits and a complete `example`) and `canon schema evidence add --schemas --json`
|
|
541
|
+
gives `Input`, the schema of one document. Each element reports `written`,
|
|
540
542
|
`unchanged` or `failed` in `data.items[]`.
|
|
541
543
|
|
|
542
544
|
`--rev <rev>` names the commit the evidence ran against (default `HEAD`).
|
|
543
545
|
Evidence for uncommitted code is recorded with its `codeTree` and
|
|
544
546
|
`worktreeDirty`; outside git, or with no commit, the add is refused with
|
|
545
|
-
`
|
|
547
|
+
`COMMIT_REQUIRED`.
|
|
546
548
|
|
|
547
549
|
**Done when:** `canon gate check` shows no violation for the scenarios you
|
|
548
550
|
recorded evidence for; each record's own output line says whether it was
|
|
@@ -697,7 +699,7 @@ aggregates every record bound to the task, on one line:
|
|
|
697
699
|
(the latest `--summary`, or a default naming the latest passing record).
|
|
698
700
|
Every other path — missing evidence, a `Divergent` verdict, a fabricated
|
|
699
701
|
note on any of the task's records — leaves the row byte-unchanged and
|
|
700
|
-
exits `
|
|
702
|
+
exits `2` with the blocking violation on stderr. After a flip, the plan
|
|
701
703
|
source is re-ingested so the record store's task status agrees with the
|
|
702
704
|
checkbox (`canon query --kind task` reads `done`); a failed re-ingest is
|
|
703
705
|
a stderr warning naming `canon ingest plans`, never a failed flip.
|
|
@@ -734,7 +736,7 @@ Staging → committed: every well-formed record under
|
|
|
734
736
|
applies, assigned a monotonic per-(role, surface) `run_seq` (gap-free
|
|
735
737
|
within one invocation, continuing from the committed max), and moved into
|
|
736
738
|
the committed ledger. A malformed or unpartitionable candidate is refused
|
|
737
|
-
— exit `
|
|
739
|
+
— exit `2` (`PROMOTION_INVALID`; several are `error.details[]`), no `run_seq` consumed, the file left in place. A refusal carries no `data`. `--dry-run`
|
|
738
740
|
prints the plan (target path + assigned `run_seq` per candidate) without
|
|
739
741
|
writing or deleting.
|
|
740
742
|
|
|
@@ -789,8 +791,10 @@ It installs no git hook: copy the script into git's `pre-commit` hook
|
|
|
789
791
|
agent hook files and the script, also under `--dry-run`. In `--json`,
|
|
790
792
|
`installed` is true when an agent hook file changed and
|
|
791
793
|
`preCommitScriptWritten` when the script was written. A `--repo` that is not an
|
|
792
|
-
existing directory exits 2 with `
|
|
793
|
-
and creates nothing.
|
|
794
|
+
existing directory exits 2 with `HOOKS_REPO_INVALID` (also under `--dry-run`)
|
|
795
|
+
and creates nothing. When the install writes the first hook file and then cannot
|
|
796
|
+
write the second, it exits 1 with `HOOKS_INSTALL_INCOMPLETE`: the first file
|
|
797
|
+
stays, `meta.next` leads with `canon status`, then run the install again.
|
|
794
798
|
|
|
795
799
|
Prefer this over hand-editing `settings.json`/`hooks.json`.
|
|
796
800
|
|
|
@@ -164,7 +164,9 @@ specs:
|
|
|
164
164
|
whole root aborts, 0 writes, violations reported.
|
|
165
165
|
- **A root on the pre-0.17 layout** (a `.feature` file under
|
|
166
166
|
`<root>/features/`) → a `layout-grammar` violation at path `features`;
|
|
167
|
-
the root aborts, 0 writes, exit
|
|
167
|
+
the root aborts, 0 writes, exit 2 (`INVENTORY_INVALID`, each violation in
|
|
168
|
+
`error.details`; exit 1 `INVENTORY_INCOMPLETE` when an earlier root was
|
|
169
|
+
indexed first). Run `canon migrate`. An empty
|
|
168
170
|
leftover `features/` directory is not a refusal.
|
|
169
171
|
- **A duplicate `scenario_id`** within one root → that root aborts, 0
|
|
170
172
|
writes, reported as a sync error (a distinct lane from fmt violations).
|
|
@@ -76,7 +76,7 @@ A human approves the policy after reviewing `.canon/policy.yaml`, in the
|
|
|
76
76
|
same answer that approves a subject's brief (0.16; see the skill's working
|
|
77
77
|
loop). `canon brief approve` records both in one call. `canon policy
|
|
78
78
|
approve` is a human's decision: with a role declared (`--as` or `CANON_ROLE`)
|
|
79
|
-
it is refused with `
|
|
79
|
+
it is refused with `ACTOR_DENIED` (exit 2, not retryable) unless it records the
|
|
80
80
|
answer the human gave in the conversation: show them `.canon/policy.yaml`, ask,
|
|
81
81
|
and on an explicit approval run it (the steps are in `canon skills show role-planner`) with `--relayed-via <tool>`, `--actor`,
|
|
82
82
|
`--approver` and `--note` (their name and words); the file then carries `relay`
|
|
@@ -117,8 +117,8 @@ unreviewed-promotion policy — policy changed since approval: .canon/policy.yam
|
|
|
117
117
|
```
|
|
118
118
|
|
|
119
119
|
`canon gate check` exits `1`; `canon subject move` (the ship guard and
|
|
120
|
-
the reopen) refuses with `
|
|
121
|
-
`
|
|
120
|
+
the reopen) refuses with `POLICY_APPROVAL_STALE`, or
|
|
121
|
+
`POLICY_APPROVAL_CORRUPT` (or `POLICY_APPROVAL_DENIED` when the file may not be read) for a broken approval, and
|
|
122
122
|
`--override-reason` does not waive either. A policy never approved stays
|
|
123
123
|
an advisory. `canon status` prints the same text as a `warning:` line (and
|
|
124
124
|
in `--json` `warnings`). The record names who approved which bytes and
|
|
@@ -143,7 +143,7 @@ canon dashboard --snapshot /tmp/canon-snap --port 8080
|
|
|
143
143
|
- Runs in any repo: the released binary carries the app (in canon's own
|
|
144
144
|
checkout a built `packages/dashboard/dist` is used instead). It prints the
|
|
145
145
|
panels URL and a briefs URL (`/briefs.html`), then serves until Ctrl-C.
|
|
146
|
-
A taken port fails with `
|
|
146
|
+
A taken port fails with `DASHBOARD_PORT_UNAVAILABLE`: pass `--port <n>` or
|
|
147
147
|
`--port 0`.
|
|
148
148
|
- Without the `duckdb` CLI on `PATH` the server still runs; the panels page
|
|
149
149
|
says why there is no snapshot and how to get one (it never shows demo
|
|
@@ -160,11 +160,11 @@ answer once and clicks Approve: one request carries every selected brief with
|
|
|
160
160
|
the sha256 of the file the page read, and records exactly what `canon brief
|
|
161
161
|
approve <id>+ --approver <name> --note <text>` records, the `Approved:` line
|
|
162
162
|
bound to the brief digest and the policy approval, for each. A brief that
|
|
163
|
-
changed after the page loaded (`
|
|
164
|
-
blockers refuses the whole request (409 `
|
|
165
|
-
refused brief): nothing is written and the page says to read it again. A request
|
|
163
|
+
changed after the page loaded (`BRIEF_PAGE_STALE`) or that has
|
|
164
|
+
blockers refuses the whole request (409, the first refused brief's own code such as `BRIEF_INVALID`, with an
|
|
165
|
+
`error.details` entry for each refused brief): nothing is written and the page says to read it again. A request
|
|
166
166
|
naming one brief the old way (`changeId`, `sha256`) is still accepted. The server is localhost only and
|
|
167
|
-
refuses requests from other origins (`
|
|
167
|
+
refuses requests from other origins (`DASHBOARD_REQUEST_DENIED`).
|
|
168
168
|
|
|
169
169
|
For an agent: when clean briefs are waiting, show them (`canon brief show
|
|
170
170
|
<slug> --body`), ask with the harness question tool, and tell the human they
|
|
@@ -89,7 +89,7 @@ in the JSON. Give the reason when you reject or defer: it is the only record
|
|
|
89
89
|
of why the finding was not fixed.
|
|
90
90
|
|
|
91
91
|
`--scenario` (repeatable, each a scenario the index knows; refused with
|
|
92
|
-
`
|
|
92
|
+
`SCENARIO_NOT_FOUND` otherwise) names the scenarios the finding is
|
|
93
93
|
about. After a `fixed` close, fresh evidence for those scenarios alone
|
|
94
94
|
re-verifies the fix; a finding naming none asks every evidenced scenario of
|
|
95
95
|
the subject, as before. `finding close` copies the list.
|
|
@@ -116,14 +116,15 @@ needs it or `--introduced-unknown` (never both). A revision that names no
|
|
|
116
116
|
commit is refused (exit `2`). A finding recorded against uncommitted code
|
|
117
117
|
is allowed: the record carries the `codeTree` it saw and `worktreeDirty`.
|
|
118
118
|
Outside git, or in a repository with no commit, the write is refused with
|
|
119
|
-
`
|
|
119
|
+
`COMMIT_REQUIRED`.
|
|
120
120
|
|
|
121
121
|
Many findings at once: `--input` takes inline JSON, a file or `-`; an array
|
|
122
122
|
(or NDJSON) is a batch validated before any write. Keys are the option
|
|
123
123
|
names in camelCase (`change`, `actor`, `resolutionRev`); `canon schema
|
|
124
|
-
finding add --json` shows `input
|
|
124
|
+
finding add --json` shows `input` (its limits and a complete `example`) and `canon schema finding add
|
|
125
|
+
--schemas --json` gives `Input`, the schema of one document. An identical
|
|
125
126
|
repeat is `unchanged` (`data.unchanged`) and writes nothing; a different
|
|
126
|
-
finding under an occupied key is `
|
|
127
|
+
finding under an occupied key is `FINDING_EXISTS`.
|
|
127
128
|
|
|
128
129
|
### A defect the author found in its own work
|
|
129
130
|
|
|
@@ -197,7 +198,7 @@ saw (the tree with `.canon/`, the spec roots and `code.exclude` removed), and
|
|
|
197
198
|
allowed, and the commit made from it has the same code tree, so committing it
|
|
198
199
|
afterwards leaves the review as it was: a review is judged by its pins (the
|
|
199
200
|
scenario and what its evidence says), not by the commit. Outside git, or
|
|
200
|
-
with no commit, the write is refused with `
|
|
201
|
+
with no commit, the write is refused with `COMMIT_REQUIRED`. An identical review
|
|
201
202
|
written again is `unchanged` (`data.unchanged` under `--json`) and adds no
|
|
202
203
|
record.
|
|
203
204
|
|
|
@@ -475,7 +476,7 @@ stderr: canon subject move: review guard for building → verifying (spec_covera
|
|
|
475
476
|
|
|
476
477
|
A target status outside the scope prints `skipped unreviewed-promotion —
|
|
477
478
|
`specced` is not in require_review.scope`. A transition into an in-scope
|
|
478
|
-
status with gaps prints the violations, exits
|
|
479
|
+
status with gaps prints the violations, exits 2, leaves the record
|
|
479
480
|
unchanged, and names `--override-reason`.
|
|
480
481
|
|
|
481
482
|
`--override-reason "<one line>"` waives ONLY `unreviewed-promotion` and
|
|
@@ -295,7 +295,7 @@ answer; without it init takes the harnesses whose
|
|
|
295
295
|
`.claude`, `.codex`, `.omp` or `.pi` directory exists, and with none detected
|
|
296
296
|
it writes only a commented example
|
|
297
297
|
and installs nothing. `.agents` alone never selects Codex. `canon skills
|
|
298
|
-
install|check|doctor` follow the section; `install` prunes projected files the bundle no longer ships when their bytes match the lock (a modified one stays, reported as `kept:`), `check` exits 1 (`
|
|
298
|
+
install|check|doctor` follow the section; `install` prunes projected files the bundle no longer ships when their bytes match the lock (a modified one stays, reported as `kept:`), `check` exits 1 (`SKILLS_CHECK_FAILED`) naming each orphan and `doctor` prints `orphan:` lines; `canon skills install
|
|
299
299
|
--providers=<list>` rewrites it in place. Without the section they use the
|
|
300
300
|
install lock's providers, then the detected ones; nothing undetected is ever
|
|
301
301
|
added. A present section that is not this shape, or names another harness,
|
|
@@ -395,7 +395,7 @@ so a killed commit never leaves it held, and the file is removed only by a
|
|
|
395
395
|
call that made it to take the lock and then ended refused (a refusal leaves
|
|
396
396
|
no file and no `.git/info/exclude` line behind). A
|
|
397
397
|
command that waited 30 s for it starts nothing: it exits `2` with
|
|
398
|
-
`
|
|
398
|
+
`REPO_LOCK_UNAVAILABLE` (retryable; run it again in a moment). The first
|
|
399
399
|
call that needs the lock makes the file, in any repository.
|
|
400
400
|
|
|
401
401
|
## What `canon init` keeps out of git
|
|
@@ -71,7 +71,8 @@ canon subject new subject-domain-loop \
|
|
|
71
71
|
subjects at once: `--input` takes inline JSON, a file or `-`; an array (or
|
|
72
72
|
NDJSON) is a batch validated before any write, with `operands` holding the
|
|
73
73
|
id and the other keys the option names in camelCase (`canon schema subject
|
|
74
|
-
new --json` shows `input
|
|
74
|
+
new --json` shows `input`, its limits and a complete `example`; `canon schema subject new --schemas --json`
|
|
75
|
+
gives `Input`, the schema of one document). Writing an identical subject
|
|
75
76
|
again is a no-op reported `unchanged` (`data.unchanged`).
|
|
76
77
|
|
|
77
78
|
### 2. Retrieve subject-scoped strategy memory BEFORE working
|
|
@@ -137,7 +138,7 @@ canon subject move subject-domain-loop --to shipped
|
|
|
137
138
|
|
|
138
139
|
On success the status updates in place; `--json` prints the updated
|
|
139
140
|
record. On a gate block it prints violations by failure class to stderr,
|
|
140
|
-
exits
|
|
141
|
+
exits 2 (the code names the condition: `SUBJECT_APPROVAL_REQUIRED`, `EVIDENCE_STALE`, `LAYOUT_MIGRATION_REQUIRED` or `SUBJECT_INVALID`; several causes are `error.details[]`), and the record is unchanged.
|
|
141
142
|
|
|
142
143
|
**Corpus-wide, the same join:** `canon gate check` with
|
|
143
144
|
`.canon/policy.yaml`'s opt-in `spec_coverage` section generalizes this
|
|
@@ -166,7 +167,7 @@ from shipping, until every evidenced scenario has evidence recorded after
|
|
|
166
167
|
the close or the approval; the refusal names the scenarios and the
|
|
167
168
|
`canon evidence add --all-scenarios` command. Each refusal prints by
|
|
168
169
|
failure class (`uncovered-cell`), carries a `hint`,
|
|
169
|
-
exits
|
|
170
|
+
exits 2, and the status stays `verifying`. `retired` is not gated.
|
|
170
171
|
|
|
171
172
|
**The brief (0.16, 0.17, 0.19):** `verifying → shipped` also refuses where a brief
|
|
172
173
|
exists and is not approved, read exactly as `canon status` reads it (one
|
|
@@ -174,7 +175,7 @@ shared check, so status says `ship` only when this passes): the subject's
|
|
|
174
175
|
scope (every change the subject answers for, see below) has a canon `.canon/changes/<change>/brief.md`
|
|
175
176
|
with no `Approved:` line outside HTML comments and code fences, whose
|
|
176
177
|
`Approved:` line carries a digest the brief's text no longer matches
|
|
177
|
-
(`
|
|
178
|
+
(`BRIEF_APPROVAL_STALE`; the brief was edited after the human
|
|
178
179
|
answered), or has no canon `brief.md` yet but comes from an external
|
|
179
180
|
openspec plan with a `proposal.md` under the plan sources. It also
|
|
180
181
|
refuses while `canon brief check` has blocker findings for that change,
|
|
@@ -184,7 +185,7 @@ a policy. The refusal is an `unreviewed-promotion` naming the subject, and
|
|
|
184
185
|
says what to do:
|
|
185
186
|
|
|
186
187
|
```output
|
|
187
|
-
output: canon subject move:
|
|
188
|
+
output: canon subject move: SUBJECT_INVALID — 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>"`
|
|
188
189
|
output: 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
|
|
189
190
|
```
|
|
190
191
|
|
|
@@ -211,7 +212,7 @@ This refusal is a backstop, and so is the evidence one: shipping is not
|
|
|
211
212
|
the first thing an unapproved brief stops. The agent writes the brief,
|
|
212
213
|
runs `canon brief check` until it has no blockers, then shows it to the
|
|
213
214
|
human and asks, and nothing is built or attested for the subject until the human
|
|
214
|
-
answers. `canon evidence add` refuses (exit
|
|
215
|
+
answers. `canon evidence add` refuses (exit 2, nothing staged) a
|
|
215
216
|
scenario whose `@subject` owner, or a task whose change
|
|
216
217
|
an adopting subject, has an enforced, unapproved brief, through the same
|
|
217
218
|
check; see `canon-gate`.
|
|
@@ -223,7 +224,7 @@ check; see `canon-gate`.
|
|
|
223
224
|
edited since, and even if the tags were removed; or (3) a *chore*, which has
|
|
224
225
|
no scenario to tag and so governs from the moment it is adopted. They pass
|
|
225
226
|
only when every one of them reads as approved now; an unapproved one and one
|
|
226
|
-
edited after its approval (`
|
|
227
|
+
edited after its approval (`BRIEF_APPROVAL_STALE`) are named for
|
|
227
228
|
different reasons, and the answer does not depend on the order the changes
|
|
228
229
|
were adopted or approved. The ship guard's brief-structure check runs over
|
|
229
230
|
all of them. When several block, the hint is one
|
|
@@ -245,7 +246,7 @@ answers only to the changes its tags name (counting only changes the subject
|
|
|
245
246
|
adopted); another change's edit after its approval never blocks it. An untagged
|
|
246
247
|
scenario (one whose tags were removed reads the same) answers to every adopted
|
|
247
248
|
change with an `Approved:` line, a chore included, so an approved change edited
|
|
248
|
-
since refuses it (`
|
|
249
|
+
since refuses it (`BRIEF_APPROVAL_STALE`); an unapproved chore blocks
|
|
249
250
|
reopen and ship, never evidence. When no adopted change has an approved line,
|
|
250
251
|
a scenario with evidence recorded before the subject first adopted a change
|
|
251
252
|
(and without a brief override) needs no brief, and one without answers to the
|
|
@@ -270,7 +271,7 @@ A target outside `require_review.scope` prints `skipped
|
|
|
270
271
|
unreviewed-promotion — `specced` is not in require_review.scope`. A
|
|
271
272
|
transition INTO an in-scope status with gaps — an owned scenario with no
|
|
272
273
|
qualifying review (`unreviewed-promotion`), or an open blocker finding
|
|
273
|
-
on an adopted change (`open-blocker`) — prints the violations, exits
|
|
274
|
+
on an adopted change (`open-blocker`) — prints the violations, exits 2,
|
|
274
275
|
leaves the record unchanged, and names `--override-reason`. `shipped`
|
|
275
276
|
also refuses a `false-success` (a scenario whose latest audit is
|
|
276
277
|
`refuted`) and, when `require_audit.scope` covers `shipped`, an owed
|
|
@@ -332,14 +333,14 @@ output: canon subject move: demo-subject → verifying — written directly; not
|
|
|
332
333
|
- Inside the approved scope it needs no human: every change the subject
|
|
333
334
|
answers for (tagged, approved or chore) has an approved brief, or there
|
|
334
335
|
is no brief to answer.
|
|
335
|
-
Otherwise it refuses, exit
|
|
336
|
+
Otherwise it refuses, exit 2, naming the brief to approve, and
|
|
336
337
|
`--override-reason` does not waive it:
|
|
337
338
|
``unreviewed-promotion demo-subject — shipped → verifying: reopening needs the approved scope, and the brief is not approved — .canon/changes/c-next/brief.md has no `Approved:` line; …``.
|
|
338
339
|
- The review guard does not run on a reopen (it prints `skipped … — a
|
|
339
340
|
reopen moves the subject back to fix its gaps; shipping again runs
|
|
340
341
|
it`). `verifying → shipped` afterwards runs every guard above again.
|
|
341
|
-
- A policy that fails closed (`
|
|
342
|
-
`
|
|
342
|
+
- A policy that fails closed (`POLICY_APPROVAL_STALE`,
|
|
343
|
+
`POLICY_APPROVAL_CORRUPT`, `POLICY_APPROVAL_DENIED`: see `canon-policy`) refuses the reopen and
|
|
343
344
|
the ship, and `--override-reason` does not waive it.
|
|
344
345
|
- `canon change new` on a shipped subject prints the reopen command
|
|
345
346
|
(`canon subject move <id> --to verifying --reason "<why it reopens>"`)
|
|
@@ -422,7 +423,7 @@ canon subject unadopt <S> --change <change> --json
|
|
|
422
423
|
|
|
423
424
|
Removes the link on both records and keeps the change and its brief, so the
|
|
424
425
|
draft can be adopted elsewhere (a `proposed` holding subject, say) while the
|
|
425
|
-
live subject keeps shipping. It is refused with `
|
|
426
|
+
live subject keeps shipping. It is refused with `SUBJECT_CONFLICT` (reason `APPROVED_BRIEF` or `FLOW_TAGGED`)
|
|
426
427
|
for a change whose brief carries an `Approved:` line, and while a scenario
|
|
427
428
|
the subject owns carries a `@flow:<change>.*` tag (it would fall back to an
|
|
428
429
|
older approval; remove or retag those scenarios first, the hint names them);
|
|
@@ -509,12 +510,12 @@ same answer and one timestamp on every brief and on the policy approval
|
|
|
509
510
|
(0.31). Every slug is checked before anything is written (a brief that
|
|
510
511
|
exists and reads, no blocker, a one-line name and answer, a body that does not
|
|
511
512
|
end inside an open code fence); one refused slug refuses the call, exit 2
|
|
512
|
-
|
|
513
|
-
nothing is written. A repeated slug counts once. With one slug the output is as
|
|
513
|
+
with the first refused slug's own code (`BRIEF_INVALID`, `BRIEF_NOT_FOUND`) and an
|
|
514
|
+
`error.details` entry for each refused slug, and nothing is written. A repeated slug counts once. With one slug the output is as
|
|
514
515
|
before; with several, `--json` carries one entry per slug (`written`,
|
|
515
516
|
`unchanged`, `failed`, `skipped`). A disk error while writing exits 1 and
|
|
516
517
|
leaves the slugs already written approved. The call is human-only for every
|
|
517
|
-
slug; the `
|
|
518
|
+
slug; the `ACTOR_DENIED` hint gives the human one line with all the slugs.
|
|
518
519
|
|
|
519
520
|
Without the change operand, the repo's only live change is read. The brief is the
|
|
520
521
|
PRD `canon change new` writes; sections are found by their English `##`
|
|
@@ -524,7 +525,7 @@ before. A brief with `<!-- canon:… -->` comments or Korean headings is in the
|
|
|
524
525
|
0.30 format: `brief check` gives it one blocker (`brief.old-format`) and
|
|
525
526
|
`canon migrate` rewrites it; `status`, `gate check`, `context` and `brief show`
|
|
526
527
|
warn, and a command that writes and judges it is refused
|
|
527
|
-
(`
|
|
528
|
+
(`BRIEF_MIGRATION_REQUIRED`).
|
|
528
529
|
|
|
529
530
|
- **Blockers (structure, `brief.*`)**: a missing, duplicated or
|
|
530
531
|
out-of-order section; a flow with no steps or a duplicate step id;
|
|
@@ -549,7 +550,7 @@ warn, and a command that writes and judges it is refused
|
|
|
549
550
|
`Approved: <who> <when> — "<words>" (brief sha256:<digest>)` into the
|
|
550
551
|
brief and records the policy approval in the same call. It refuses
|
|
551
552
|
(exit 2) while the check has structure blockers. Edit the brief
|
|
552
|
-
afterwards and every reader says `
|
|
553
|
+
afterwards and every reader says `BRIEF_APPROVAL_STALE` until a
|
|
553
554
|
human answers again and `approve` runs again. Run it only from the
|
|
554
555
|
human's answer, with their words as `--note`.
|
|
555
556
|
|
|
@@ -619,7 +620,7 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
619
620
|
`Approved: <who> <when> — "<the human's words>" (brief sha256:<digest>)`,
|
|
620
621
|
the digest covering the brief without its `Approved:` lines. A brief
|
|
621
622
|
edited after that reads `brief: not approved (<brief> changed after its
|
|
622
|
-
approval (
|
|
623
|
+
approval (BRIEF_APPROVAL_STALE))` and names the re-approval
|
|
623
624
|
command: the changed brief needs a new human answer. A line with no
|
|
624
625
|
digest (written before 0.19) stays approved, with an `advisory:` to
|
|
625
626
|
re-approve so it binds to the text. Fixes and follow-ups
|
|
@@ -10,7 +10,7 @@ build nothing meanwhile. The only waiver is `--override-reason
|
|
|
10
10
|
the human's answer: canon records it on the evidence, echoes it in
|
|
11
11
|
`data.overrides[]` and lists it in `status` for the human. Never use it to
|
|
12
12
|
skip the wait yourself. `brief approve`, `policy approve` and `divergence
|
|
13
|
-
accept` are the human's; they refuse you (`
|
|
13
|
+
accept` are the human's; they refuse you (`ACTOR_DENIED`) unless they record an
|
|
14
14
|
answer the human gave in the conversation (`--relayed-via`, the planner's
|
|
15
15
|
procedure: `canon skills show role-planner`). You never run them without that
|
|
16
16
|
answer, and never remove or unset your role (`env -u CANON_ROLE`, dropping
|
|
@@ -25,7 +25,7 @@ in your ids. Use only the options on a line; never guess one. Ask `canon schema
|
|
|
25
25
|
<command> --json` only for a leaf this block does not list, or after a `USAGE` refusal.
|
|
26
26
|
|
|
27
27
|
<!-- canon:generated commands-implementer begin -->
|
|
28
|
-
Every leaf takes `--as <ROLE>` and `--json`; `--repo <DIR>` too, except `completion`, `schema`, `skills show`. `--input <JSON|FILE|->` runs a leaf from one JSON document (an array is a batch) and is only on the lines ending `[--input]`. Its document keys are the option names in camelCase, singular even when the option repeats (the value is then an array), and `operands` holds the operands. `--fields <FIELDS>` is a comma list of the paths `canon schema <COMMAND> --json` declares under `outputs[].fields.paths`; a path is the record's own key, spelled as the answer spells it.
|
|
28
|
+
Every leaf takes `--as <ROLE>` and `--json`; `--repo <DIR>` too, except `completion`, `schema`, `skills show`. `--input <JSON|FILE|->` runs a leaf from one JSON document (an array is a batch) and is only on the lines ending `[--input]`. Its document keys are the option names in camelCase, singular even when the option repeats (the value is then an array; none is the key left out, `[]` is refused), and `operands` holds the operands. `--fields <FIELDS>` is a comma list of the paths `canon schema <COMMAND> --json` declares under `outputs[].fields.paths`; a path is the record's own key, spelled as the answer spells it.
|
|
29
29
|
A `usage:` line shows the syntax and is not itself a command to run (the runnable example under it is): `<X>` is a value, `[x]` optional, `a | b` a choice, `(a | b)` exactly one is required, `[--x <V>]*` may repeat, `<X>+` is one or more, `[--a --b <V>]` go together. An option that is not on the line does not exist: it is refused (`USAGE`).
|
|
30
30
|
|
|
31
31
|
```text
|
|
@@ -177,7 +177,7 @@ canon scenario new auth.login.02 --title "Sign out" --feature .canon/specs/kind=
|
|
|
177
177
|
```
|
|
178
178
|
```text
|
|
179
179
|
# Describe canon's own commands
|
|
180
|
-
usage: canon schema [<PATH>]* [--
|
|
180
|
+
usage: canon schema [<PATH>]* [--schemas | --error <CODE> | --errors | --warning <CODE> | --warnings]
|
|
181
181
|
```
|
|
182
182
|
```bash
|
|
183
183
|
canon schema evidence add --json
|
|
@@ -224,7 +224,7 @@ After the first `status`, follow `meta.next` of each write; do not call
|
|
|
224
224
|
the commit it is about from `--rev` (default `HEAD`, any git revision). You
|
|
225
225
|
need not commit first: code that is not committed yet is recorded with its
|
|
226
226
|
`codeTree` and `worktreeDirty: true`, never refused. Outside git, or in a
|
|
227
|
-
repo with no commits, a write that needs a commit refuses `
|
|
227
|
+
repo with no commits, a write that needs a commit refuses `COMMIT_REQUIRED`.
|
|
228
228
|
|
|
229
229
|
The forms you reach for most (the story's ids; swap in yours):
|
|
230
230
|
|
|
@@ -253,7 +253,7 @@ canon evidence add --input '[{"scenario":"auth.login.01","class":"test-run","ref
|
|
|
253
253
|
keys are the option names in camelCase plus `operands` (the scenario id);
|
|
254
254
|
every element is validated before the first write, so a bad element
|
|
255
255
|
writes nothing and `error.field` names it (`/1/case`).
|
|
256
|
-
`canon schema scenario new --json` shows `input
|
|
256
|
+
`canon schema scenario new --json` shows `input` (its limits and a complete `example`); `canon schema scenario new --schemas --json` gives `Input`, the schema of one document.
|
|
257
257
|
(`scenario new --from` is gone.) When the gate asks for a missing case
|
|
258
258
|
(`require_cases`), add a new scenario; never retag an existing one. Every
|
|
259
259
|
bug fix adds or extends a scenario. Canon indexes added, edited or deleted
|