@journeykit/canon 0.32.0 → 0.34.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/index.js +4 -0
- package/dist/skills/SKILL.src.md +41 -19
- package/dist/skills/reference/canon-authoring.md +2 -2
- package/dist/skills/reference/canon-context.md +2 -2
- package/dist/skills/reference/canon-gate.md +2 -2
- package/dist/skills/reference/canon-review.md +3 -3
- package/dist/skills/reference/canon-storage.md +7 -4
- package/dist/skills/reference/canon-subject.md +15 -13
- package/dist/skills/reference/role-implementer.md +35 -35
- package/dist/skills/reference/role-orchestrator.md +71 -71
- package/dist/skills/reference/role-planner.md +25 -25
- package/dist/skills/reference/role-reviewer.md +28 -28
- package/man/canon-adapter-authorize.1 +3 -3
- package/man/canon-adapter-validate.1 +3 -3
- package/man/canon-adapter.1 +3 -3
- package/man/canon-artifacts-move.1 +4 -4
- package/man/canon-artifacts-store.1 +3 -3
- package/man/canon-artifacts-verify.1 +3 -3
- package/man/canon-artifacts.1 +3 -3
- package/man/canon-brief-approve.1 +3 -3
- package/man/canon-brief-check.1 +3 -3
- package/man/canon-brief-show.1 +3 -3
- package/man/canon-brief.1 +3 -3
- package/man/canon-change-new.1 +3 -3
- package/man/canon-change.1 +3 -3
- package/man/canon-completion.1 +3 -3
- package/man/canon-context-pack-add.1 +3 -3
- package/man/canon-context-pack-show.1 +3 -3
- package/man/canon-context-pack-verify.1 +3 -3
- package/man/canon-context-pack.1 +3 -3
- package/man/canon-context.1 +4 -4
- package/man/canon-dashboard.1 +3 -3
- package/man/canon-demo-init.1 +3 -3
- package/man/canon-demo-review.1 +3 -3
- package/man/canon-demo.1 +3 -3
- package/man/canon-dispatch-begin.1 +3 -3
- package/man/canon-dispatch-diff.1 +3 -3
- package/man/canon-dispatch-end.1 +3 -3
- package/man/canon-dispatch.1 +3 -3
- package/man/canon-divergence-accept.1 +3 -3
- package/man/canon-divergence-add.1 +3 -3
- package/man/canon-divergence-defer.1 +3 -3
- package/man/canon-divergence-list.1 +6 -6
- package/man/canon-divergence-resolve.1 +3 -3
- package/man/canon-divergence.1 +3 -3
- package/man/canon-evidence-add.1 +3 -3
- package/man/canon-evidence-approval-payload.1 +3 -3
- package/man/canon-evidence-audit.1 +3 -3
- package/man/canon-evidence.1 +3 -3
- package/man/canon-export.1 +6 -6
- package/man/canon-feature-new.1 +3 -3
- package/man/canon-feature.1 +3 -3
- package/man/canon-finding-add.1 +4 -4
- package/man/canon-finding-close.1 +3 -3
- package/man/canon-finding-list.1 +6 -6
- package/man/canon-finding.1 +3 -3
- package/man/canon-format.1 +3 -3
- package/man/canon-gate-check.1 +3 -3
- package/man/canon-gate-install-hooks.1 +3 -3
- package/man/canon-gate-promote.1 +3 -3
- package/man/canon-gate.1 +3 -3
- package/man/canon-ingest-plans.1 +3 -3
- package/man/canon-ingest-records.1 +3 -3
- package/man/canon-ingest-sessions.1 +3 -3
- package/man/canon-ingest.1 +3 -3
- package/man/canon-init.1 +4 -4
- package/man/canon-inventory-sync.1 +3 -3
- package/man/canon-inventory.1 +3 -3
- package/man/canon-ledger-compact.1 +3 -3
- package/man/canon-ledger.1 +3 -3
- package/man/canon-migrate.1 +3 -3
- package/man/canon-plugin-sync.1 +3 -3
- package/man/canon-plugin.1 +3 -3
- package/man/canon-policy-approve.1 +3 -3
- package/man/canon-policy-show.1 +3 -3
- package/man/canon-policy.1 +3 -3
- package/man/canon-prompt-add.1 +3 -3
- package/man/canon-prompt-show.1 +3 -3
- package/man/canon-prompt.1 +3 -3
- package/man/canon-purge.1 +3 -3
- package/man/canon-query.1 +6 -6
- package/man/canon-regime-show.1 +3 -3
- package/man/canon-regime.1 +3 -3
- package/man/canon-report-build.1 +3 -3
- package/man/canon-report-check.1 +3 -3
- package/man/canon-report-snapshot.1 +3 -3
- package/man/canon-report.1 +3 -3
- package/man/canon-retrieve.1 +4 -4
- package/man/canon-review-change.1 +3 -3
- package/man/canon-review-scenario.1 +3 -3
- package/man/canon-review.1 +3 -3
- package/man/canon-scenario-new.1 +3 -3
- package/man/canon-scenario.1 +3 -3
- package/man/canon-schema.1 +14 -6
- package/man/canon-search.1 +3 -3
- package/man/canon-selftest.1 +3 -3
- package/man/canon-skills-check.1 +3 -3
- package/man/canon-skills-doctor.1 +3 -3
- package/man/canon-skills-install.1 +3 -3
- package/man/canon-skills-show.1 +3 -3
- package/man/canon-skills.1 +3 -3
- package/man/canon-status.1 +4 -4
- package/man/canon-strategy-approval-payload.1 +3 -3
- package/man/canon-strategy-promote.1 +3 -3
- package/man/canon-strategy-rollback.1 +3 -3
- package/man/canon-strategy.1 +3 -3
- package/man/canon-subject-adopt.1 +3 -3
- package/man/canon-subject-move.1 +3 -3
- package/man/canon-subject-new.1 +4 -4
- package/man/canon-subject-show.1 +3 -3
- package/man/canon-subject-unadopt.1 +3 -3
- package/man/canon-subject.1 +3 -3
- package/man/canon-task-done.1 +3 -3
- package/man/canon-task.1 +3 -3
- package/man/canon-tier-age.1 +3 -3
- package/man/canon-tier.1 +3 -3
- package/man/canon-trace.1 +3 -3
- package/man/canon.1 +3 -3
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { spawnSync, execSync } from "node:child_process";
|
|
5
5
|
import { existsSync, readdirSync, realpathSync } from "node:fs";
|
|
6
|
+
import { constants as osConstants } from "node:os";
|
|
6
7
|
import { resolve, join, basename } from "node:path";
|
|
7
8
|
import { fileURLToPath } from "node:url";
|
|
8
9
|
var binaryName = process.platform === "win32" ? "canon.exe" : "canon";
|
|
@@ -165,4 +166,7 @@ var result = spawnSync(binary, process.argv.slice(2), {
|
|
|
165
166
|
if (result.error) {
|
|
166
167
|
console.error(`canon: failed to run ${binary}: ${result.error.message}`);
|
|
167
168
|
}
|
|
169
|
+
if (result.status === null && result.signal) {
|
|
170
|
+
process.exit(128 + (osConstants.signals[result.signal] ?? 0));
|
|
171
|
+
}
|
|
168
172
|
process.exit(result.status ?? 1);
|
package/dist/skills/SKILL.src.md
CHANGED
|
@@ -186,7 +186,7 @@ variable, and an unknown value is refused (`UNKNOWN_ROLE`).
|
|
|
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`
|
|
188
188
|
and `meta.next` then show only your role's steps, and count the others in
|
|
189
|
-
`waitingOn`; `canon schema --as <role>` lists only your role's commands.
|
|
189
|
+
`data.waitingOn`; `canon schema --as <role>` lists only your role's commands.
|
|
190
190
|
Do not load another role's guide.
|
|
191
191
|
- **No role (one agent doing everything):** follow `canon status` and load
|
|
192
192
|
each role guide as its phase starts: planner for steps 1–2,
|
|
@@ -201,30 +201,52 @@ A role is guidance, not enforcement: `--role` on `evidence add` and
|
|
|
201
201
|
|
|
202
202
|
- Start a session with `canon status`: where each subject stands and the next
|
|
203
203
|
commands. After that, do not call it only to learn the next step: every
|
|
204
|
-
write returns `meta.next` (`[{command, argv,
|
|
205
|
-
steps `status` would give, narrowed to what the write touched.
|
|
204
|
+
write returns `meta.next` (`[{command, argv, reason, x-canon: {actor, role}}]`), the same
|
|
205
|
+
steps `status` would give, narrowed to what the write touched. Each entry is
|
|
206
|
+
runnable: `argv` is the command without `canon` (with `--json` when you
|
|
207
|
+
called in JSON mode). Guidance that needs a value you must fill in is not a
|
|
208
|
+
next entry; it is in the error `hint` or the report text. `x-canon.actor: human`
|
|
206
209
|
marks a step only the human takes.
|
|
207
210
|
- Your role guide's **Commands** block (`canon skills show role-<role>`) is
|
|
208
211
|
your complete command set, every option of every leaf included. Run `canon schema <command> --json` only for a
|
|
209
212
|
command it does not list, or after a `USAGE` refusal (read `error.field`
|
|
210
|
-
and `error.expected` first). `canon schema`
|
|
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); `canon schema <group> --json` lists a group's
|
|
215
|
+
commands; `canon schema <command> --json` is one command in full: `options` (each with
|
|
216
|
+
`valueType`, a typed `default`, `possibleValues`, `env`, `flagOnly`), `errors`, `outputs`
|
|
217
|
+
with the JSON Schema of each report in `schemas`, `input` (the schema of one `--input`
|
|
218
|
+
document and a complete `example`) and `examples`. The first line of every `--help`
|
|
219
|
+
points at it.
|
|
211
220
|
- Pass `--json` and read stdout as one document, nothing on stderr. Success is
|
|
212
221
|
`{"ok":true,"data":…,"meta":…}`; failure is
|
|
213
222
|
`{"ok":false,"error":{…},"meta":…}` (a check that fails keeps its report in
|
|
214
|
-
`data`). `meta` carries `
|
|
215
|
-
`
|
|
216
|
-
|
|
223
|
+
`data`). `meta` carries `tool`, `toolVersion`, `contract` (`atip/1`),
|
|
224
|
+
`contractVersion` (`1.1`), `schemaVersion`,
|
|
225
|
+
`command`, and when present `next`, `warnings` (`[{code, message}]`) and
|
|
226
|
+
`page`; a repeated write that changed nothing reports `data.unchanged: true`.
|
|
227
|
+
Absent members are omitted, never `null` or `[]` (a value you sent empty comes back as `received: ""`).
|
|
228
|
+
Read the members you know and ignore the ones you do not: a later canon
|
|
229
|
+
adds members, and a value of a closed set you have not seen (a `severity`, an
|
|
230
|
+
`outcome`, a `reason`) is one item to leave out, never a reason to reject the document. A paged list puts
|
|
231
|
+
`meta.page.nextCursor` on the call's `meta.next` as `--cursor <nextCursor>`;
|
|
232
|
+
no `nextCursor` means no more.
|
|
233
|
+
On failure branch on `error.code`, and on `error.reason` where the code has
|
|
234
|
+
reasons (`INPUT_INVALID` says `NOT_JSON`, `UNKNOWN_KEY`, `STDIN_TTY`, … so you
|
|
235
|
+
know whether to fix the JSON or the shell); fix the option `error.field` names
|
|
217
236
|
using the `error.expected` values (`field` is an option name, or a JSON
|
|
218
237
|
pointer such as `/items/2/scenario` into an `--input` document), and
|
|
219
|
-
follow `error.hint`:
|
|
220
|
-
|
|
221
|
-
`canon schema --
|
|
222
|
-
|
|
223
|
-
|
|
238
|
+
follow `error.hint`: it is one runnable command line that starts with `canon`, the
|
|
239
|
+
same with `<PLACEHOLDER>`s you fill in, or one sentence. The codes
|
|
240
|
+
are stable; `canon schema --errors --json` lists them with their reasons and
|
|
241
|
+
`canon schema --error <CODE>` explains one. A warning code (`meta.warnings`) is in
|
|
242
|
+
`canon schema --warnings --json`; `canon schema --warning <CODE>` explains one.
|
|
243
|
+
- **Exit codes:** only 0, 1 and 2 exist: 0 ok; 1 the command ran and its answer
|
|
244
|
+
is negative or incomplete (a failed check, a violation, `unverifiable` when
|
|
245
|
+
nothing was examined, a partly failed batch); 2 refused to run (usage,
|
|
224
246
|
`CONFIG_MISSING`, an id or file that does not exist, an invalid argument).
|
|
225
247
|
A refusal leaves the tree unchanged.
|
|
226
248
|
- Repeating a write is safe: a record that already exists with identical
|
|
227
|
-
content is reported `unchanged` (`
|
|
249
|
+
content is reported `unchanged` (`data.unchanged`), not duplicated.
|
|
228
250
|
- An option that takes an id is the bare noun (`--change add-login`,
|
|
229
251
|
`--scenario auth.login.01`, `--actor reviewer-1`, `--project root`,
|
|
230
252
|
`--session s-1`), and an `--input` document key is that name without `Id`
|
|
@@ -236,8 +258,8 @@ A role is guidance, not enforcement: `--role` on `evidence add` and
|
|
|
236
258
|
has blockers; the approval step appears only when the brief is clean and
|
|
237
259
|
unapproved.
|
|
238
260
|
- Page long lists with `--limit <n>` and `--cursor <nextCursor>` (`--all`
|
|
239
|
-
for everything), and
|
|
240
|
-
`query`, `finding list`, `divergence list`, `context`).
|
|
261
|
+
for everything); a cursor holds only for the call that issued it, so change nothing but `--limit`, `--all` and `--fields` (`CURSOR_INVALID` with `error.reason` `ARGUMENTS_CHANGED` otherwise). Project fields with `--fields a,b`
|
|
262
|
+
(`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.
|
|
241
263
|
- `--override-reason <text>` is the only way to proceed past a waivable
|
|
242
264
|
refusal; it is recorded, echoed in `data.overrides[]` and listed by `status`
|
|
243
265
|
for the human. There is no `--force`. `brief approve`, `policy approve`,
|
|
@@ -257,9 +279,9 @@ from a file or stdin) is a batch, run in order and answered with
|
|
|
257
279
|
`skipped`, and that element's `data` or `error`). A batch is validated whole
|
|
258
280
|
before anything is written: an invalid element writes nothing and exits 2,
|
|
259
281
|
`error.field` pointing at `/items/<i>/<key>`; a write that fails stops there
|
|
260
|
-
(exit 1) and re-running the same batch reports the finished elements
|
|
261
|
-
`unchanged`. A typo in a key is refused (`
|
|
262
|
-
`canon schema <command> --json` shows the leaf's input schema and
|
|
282
|
+
(exit 1, `BATCH_INCOMPLETE`) and re-running the same batch reports the finished elements
|
|
283
|
+
`unchanged`. A typo in a key is refused (`INPUT_INVALID`, `field` naming the key), never dropped.
|
|
284
|
+
`canon schema <command> --json` shows the leaf's `input`: the schema of one document and a complete `example`.
|
|
263
285
|
|
|
264
286
|
```text
|
|
265
287
|
canon scenario new --input '[{"operands":["auth.login.01"],"title":"Logs in","case":"happy"},{"operands":["auth.login.02"],"title":"Wrong password","case":"failure"}]'
|
|
@@ -276,7 +298,7 @@ The five commands that delete or rewrite existing data (`canon purge`,
|
|
|
276
298
|
`canon tier age`, `canon ledger compact`, `canon artifacts move`,
|
|
277
299
|
`canon migrate`) act in two steps. The bare run previews: it writes nothing,
|
|
278
300
|
exits 0 and prints the effects and a `planDigest`. Read the effects, then act
|
|
279
|
-
with `--commit --plan-digest <planDigest>`. It refuses (`
|
|
301
|
+
with `--commit --plan-digest <planDigest>`. It refuses (`PLAN_STALE`) when
|
|
280
302
|
the plan differs from the one you previewed, so run the preview again. Appends
|
|
281
303
|
and state transitions (`gate promote`, `subject move`) run directly. Where a
|
|
282
304
|
preview helps elsewhere (`init`, `skills install`, `export`, `inventory sync`,
|
|
@@ -111,8 +111,8 @@ Fix it and the next command indexes the files (see `canon-inventory`).
|
|
|
111
111
|
Many scenarios at once: `--input` takes inline JSON, a file or `-`. An
|
|
112
112
|
array (or NDJSON) is a batch, validated whole before anything is written;
|
|
113
113
|
each element holds `operands` (the scenario tag) and the other options as
|
|
114
|
-
camelCase keys. `canon schema scenario new --json` shows the
|
|
115
|
-
and
|
|
114
|
+
camelCase keys. `canon schema scenario new --json` shows `input`: the schema of one document
|
|
115
|
+
and a complete `example`. There is no `--from`.
|
|
116
116
|
|
|
117
117
|
```text
|
|
118
118
|
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"}]'
|
|
@@ -34,8 +34,8 @@ authored; `canon status` (see `canon-subject`) says where the repo stands
|
|
|
34
34
|
and what to run next. `--json` prints the `{ok, data, meta}` envelope: the
|
|
35
35
|
header adds no field, and `policy.spec_coverage`/`policy.diagnostics`
|
|
36
36
|
already carry the same fact. `--fields <list>` keeps only the named
|
|
37
|
-
top-level fields (`kinds`, `enums`, `policy`, `review`, …); an unknown name is
|
|
38
|
-
`
|
|
37
|
+
top-level fields (`kinds`, `enums`, `policy`, `review`, …), spelled as the report spells them; an unknown name is
|
|
38
|
+
`USAGE` (exit 2; `field` is `--fields`, `expected` lists the selectable fields), and `meta.fields` lists the kept ones.
|
|
39
39
|
|
|
40
40
|
On a repository that still holds 0.27 canon state, `canon context` warns
|
|
41
41
|
and puts `canon migrate --json` first in `meta.next`: run `canon migrate`
|
|
@@ -347,7 +347,7 @@ brief_override:
|
|
|
347
347
|
Under `--json` the same waiver is `data.overrides[]` (`code` of the waived
|
|
348
348
|
refusal, `reason` verbatim), so a caller sees what its `--override-reason`
|
|
349
349
|
let through; a repeat of an identical record is `unchanged`
|
|
350
|
-
(`
|
|
350
|
+
(`data.unchanged`) and records no second override. `--override-reason`
|
|
351
351
|
exists on `subject move` too (see `canon-subject`).
|
|
352
352
|
|
|
353
353
|
A blank or multi-line reason exits 2; an override when nothing refused is
|
|
@@ -534,7 +534,7 @@ or `-`; an array (or NDJSON) is a batch, validated element by element before
|
|
|
534
534
|
the first write (a refusal writes nothing, exit 2). Keys are the option
|
|
535
535
|
names in camelCase plus `operands`: one object per scenario, with
|
|
536
536
|
`scenario`, `class`, `ref` and `role`. `canon schema evidence add --json`
|
|
537
|
-
shows the
|
|
537
|
+
shows `input`: the schema of one document and a complete `example`. Each element reports `written`,
|
|
538
538
|
`unchanged` or `failed` in `data.items[]`.
|
|
539
539
|
|
|
540
540
|
`--rev <rev>` names the commit the evidence ran against (default `HEAD`).
|
|
@@ -121,8 +121,8 @@ Outside git, or in a repository with no commit, the write is refused with
|
|
|
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 the
|
|
125
|
-
repeat is `unchanged` (`
|
|
124
|
+
finding add --json` shows `input`: the schema of one document and a complete `example`. An identical
|
|
125
|
+
repeat is `unchanged` (`data.unchanged`) and writes nothing; a different
|
|
126
126
|
finding under an occupied key is `FINDING_SEQ_OCCUPIED`.
|
|
127
127
|
|
|
128
128
|
### A defect the author found in its own work
|
|
@@ -198,7 +198,7 @@ allowed, and the commit made from it has the same code tree, so committing it
|
|
|
198
198
|
afterwards leaves the review as it was: a review is judged by its pins (the
|
|
199
199
|
scenario and what its evidence says), not by the commit. Outside git, or
|
|
200
200
|
with no commit, the write is refused with `NO_COMMIT`. An identical review
|
|
201
|
-
written again is `unchanged` (`
|
|
201
|
+
written again is `unchanged` (`data.unchanged` under `--json`) and adds no
|
|
202
202
|
record.
|
|
203
203
|
|
|
204
204
|
**Done when:** `canon gate check` reports no `unreviewed-promotion` for the
|
|
@@ -104,9 +104,12 @@ canon query --kind handoff --since 2026-06-01T00:00:00Z
|
|
|
104
104
|
canon query --kind trajectory --json
|
|
105
105
|
|
|
106
106
|
# Page a long result and keep only the fields you need; `meta` carries
|
|
107
|
-
# returned, total,
|
|
107
|
+
# `page` = {returned, total, nextCursor} and `fields` = the paths kept; a present `nextCursor` means more, and
|
|
108
|
+
# `meta.next` repeats the call with `--cursor <nextCursor>` (`--all` returns everything). A cursor is bound to the
|
|
109
|
+
# call that issued it: change only `--limit`, `--all` or `--fields`; any other change is `CURSOR_INVALID`
|
|
110
|
+
# (`error.reason` `ARGUMENTS_CHANGED`). A field path is the record's own key, written as it is.
|
|
108
111
|
canon query --kind trajectory --json --limit 50 --fields at,kind
|
|
109
|
-
canon query --kind trajectory --json --limit 50 --cursor <nextCursor>
|
|
112
|
+
canon query --kind trajectory --json --limit 50 --fields at,kind --cursor <nextCursor>
|
|
110
113
|
```
|
|
111
114
|
|
|
112
115
|
## The ledger is latest-only; the archive holds history
|
|
@@ -189,7 +192,7 @@ section listing them and emits a matching stderr `WARN`.
|
|
|
189
192
|
`canon purge --kind <kind> --before <RFC3339> [--commit --plan-digest <planDigest>] [--repo <dir>] [--json]`
|
|
190
193
|
is the canonical data-lifecycle boundary: the bare run previews: it prints the removal set and
|
|
191
194
|
its `planDigest` and deletes nothing; `--commit --plan-digest <planDigest>` deletes only if
|
|
192
|
-
the plan recomputed now has the same digest (`
|
|
195
|
+
the plan recomputed now has the same digest (`PLAN_STALE`, exit 2, when the
|
|
193
196
|
data moved). The only purgeable kinds are
|
|
194
197
|
`session`, `run`, `event`, and `trajectory`; the cutoff applies to every
|
|
195
198
|
routed rung and every configured aging destination, including retained
|
|
@@ -210,7 +213,7 @@ arguments previews an empty removal set.
|
|
|
210
213
|
With `--json`, `purge` and `export` answer `{ "data", "meta" }` like every other
|
|
211
214
|
command: `data` is the plan or manifest, `meta.next` the step after (a plan's is the
|
|
212
215
|
human's review and `--commit --plan-digest`), and an export's page state (`total`, `returned`,
|
|
213
|
-
`nextCursor`) sits in `meta`. `export --json --output <file>` writes the manifest to the
|
|
216
|
+
`nextCursor`) sits in `meta.page`. `export --json --output <file>` writes the manifest to the
|
|
214
217
|
file and answers with `data: { output, kind, recordCount }`; `--dry-run`
|
|
215
218
|
answers with what it would write and writes nothing.
|
|
216
219
|
|
|
@@ -70,8 +70,8 @@ canon subject new subject-domain-loop \
|
|
|
70
70
|
subjects at once: `--input` takes inline JSON, a file or `-`; an array (or
|
|
71
71
|
NDJSON) is a batch validated before any write, with `operands` holding the
|
|
72
72
|
id and the other keys the option names in camelCase (`canon schema subject
|
|
73
|
-
new --json` shows the schema and
|
|
74
|
-
again is a no-op reported `unchanged` (`
|
|
73
|
+
new --json` shows `input`: the schema of one document and a complete `example`). Writing an identical subject
|
|
74
|
+
again is a no-op reported `unchanged` (`data.unchanged`).
|
|
75
75
|
|
|
76
76
|
### 2. Retrieve subject-scoped strategy memory BEFORE working
|
|
77
77
|
|
|
@@ -747,21 +747,23 @@ Status fails closed rather than suggest progress the gate would refuse:
|
|
|
747
747
|
```
|
|
748
748
|
|
|
749
749
|
The steps that follow are not in `data`: they are `meta.next`, most useful
|
|
750
|
-
first, with `
|
|
750
|
+
first, with `data.nextOmitted` counting what was cut and `data.waitingOn`
|
|
751
751
|
(with a declared role, `--as`) counting the steps each other owner holds:
|
|
752
752
|
|
|
753
753
|
```json
|
|
754
754
|
"next": [
|
|
755
|
-
{ "command": "
|
|
756
|
-
{ "command": "canon
|
|
757
|
-
{ "command": "canon status", "argv": ["
|
|
755
|
+
{ "command": "canon brief show c-promo --json", "argv": ["brief", "show", "c-promo", "--json"], "reason": "promo: the brief is not approved; build and attest nothing for promo until the human answers", "x-canon": { "actor": "human" } },
|
|
756
|
+
{ "command": "canon gate check --json", "argv": ["gate", "check", "--json"], "reason": "cart: 1 open blocker finding(s); fix it, commit, then close it with `canon finding close`", "x-canon": { "actor": "agent", "role": "implementer" } },
|
|
757
|
+
{ "command": "canon status --json", "argv": ["status", "--json"], "reason": "1 scenario(s) carry no @subject tag (first: cart.promo.01); add `@subject:<id>` above each in its .feature file, then check again", "x-canon": { "actor": "agent", "role": "planner" } }
|
|
758
758
|
]
|
|
759
759
|
```
|
|
760
760
|
|
|
761
|
-
`argv` is the command
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
761
|
+
`argv` is the command without the executable (`canon` + `argv` is the call),
|
|
762
|
+
and carries `--json` when you called in JSON mode. Every next entry is
|
|
763
|
+
runnable as it stands: guidance that needs a value only you know (an actor id,
|
|
764
|
+
a session, the human's words) is not a next entry, it is in the error `hint`
|
|
765
|
+
or the report text. On a repository that still holds 0.27 canon state,
|
|
766
|
+
`canon status` warns (`data.warnings`, `meta.warnings` as `[{code, message}]`) and puts `canon
|
|
765
767
|
migrate --json` first in `meta.next`: run `canon migrate`, then `canon
|
|
766
768
|
migrate --commit --plan-digest <digest from the preview>`, then `canon
|
|
767
769
|
skills install`.
|
|
@@ -792,14 +794,14 @@ only the pending drafts, and `flow` lists each flow step of every tagged
|
|
|
792
794
|
change as `{ "id", "change", "scenarios": [{ id, title, failure, evidenced,
|
|
793
795
|
review }], "gaps" }`.
|
|
794
796
|
|
|
795
|
-
Each `meta.next` entry's `actor` is `agent`
|
|
796
|
-
|
|
797
|
+
Each `meta.next` entry's `x-canon.actor` is `agent` or `human` (a step only the
|
|
798
|
+
human takes; its `reason` says what to get from them).
|
|
797
799
|
|
|
798
800
|
`policy.spec_coverage` has the shape `canon context --json` prints
|
|
799
801
|
(`null` when absent, `{"invalid": …}` when unusable). `statusVersion`
|
|
800
802
|
changes only when a field changes meaning or is removed. It became `2`
|
|
801
803
|
in 0.16, when `next[].command` stopped always being a command line
|
|
802
|
-
(`actor`
|
|
804
|
+
(`actor` told which), and `brief` was added alongside. It is `3` since
|
|
803
805
|
0.17, when `brief.proposal` was removed: the canon `brief.md` is
|
|
804
806
|
`brief.brief`, with `briefExists` and `source`. It is `4` since 0.31, when the
|
|
805
807
|
`brief` object became the `briefs` list.
|
|
@@ -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
|
|
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.
|
|
29
29
|
In a syntax line `<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
|
|
@@ -33,194 +33,194 @@ In a syntax line `<X>` is a value, `[x]` optional, `a | b` a choice, `(a | b)` e
|
|
|
33
33
|
canon completion <SHELL>
|
|
34
34
|
```
|
|
35
35
|
```bash
|
|
36
|
-
canon completion zsh
|
|
36
|
+
canon completion zsh --json
|
|
37
37
|
```
|
|
38
38
|
```text
|
|
39
39
|
# Show what you can author here: record kinds, fields, enums, policies
|
|
40
40
|
canon context [--fields <FIELDS>]
|
|
41
41
|
```
|
|
42
42
|
```bash
|
|
43
|
-
canon context
|
|
43
|
+
canon context --json
|
|
44
44
|
```
|
|
45
45
|
```text
|
|
46
46
|
# Create an immutable context pack from a repository-local JSON manifest
|
|
47
47
|
canon context-pack add --manifest <FILE> [--input]
|
|
48
48
|
```
|
|
49
49
|
```bash
|
|
50
|
-
canon context-pack add --manifest .canon/context-manifest.json
|
|
50
|
+
canon context-pack add --manifest .canon/context-manifest.json --json
|
|
51
51
|
```
|
|
52
52
|
```text
|
|
53
53
|
# Show a context pack after verifying its manifest and content objects
|
|
54
54
|
canon context-pack show <PACK_ID>
|
|
55
55
|
```
|
|
56
56
|
```bash
|
|
57
|
-
canon context-pack show sha256:0000000000000000000000000000000000000000000000000000000000000000
|
|
57
|
+
canon context-pack show sha256:0000000000000000000000000000000000000000000000000000000000000000 --json
|
|
58
58
|
```
|
|
59
59
|
```text
|
|
60
60
|
# Verify a context pack's manifest and immutable content objects
|
|
61
61
|
canon context-pack verify <PACK_ID>
|
|
62
62
|
```
|
|
63
63
|
```bash
|
|
64
|
-
canon context-pack verify sha256:0000000000000000000000000000000000000000000000000000000000000000
|
|
64
|
+
canon context-pack verify sha256:0000000000000000000000000000000000000000000000000000000000000000 --json
|
|
65
65
|
```
|
|
66
66
|
```text
|
|
67
67
|
# Add a divergence candidate, staged with no run_seq yet
|
|
68
68
|
canon divergence add <SCENARIO_ID> --actor <ACTOR_ID> [--project <PROJECT_ID>] [--rev <REV>] [--state <open|still-divergent|resolved|deferred>] [--reason <TEXT>] [--expiry <TIMESTAMP>] [--round <N>] [--session <SESSION_ID>] [--detail <TEXT>] [--role <ROLE>] [--promote | --no-promote] [--input]
|
|
69
69
|
```
|
|
70
70
|
```bash
|
|
71
|
-
canon divergence add auth.login.01 --actor alice --role reviewer
|
|
71
|
+
canon divergence add auth.login.01 --actor alice --role reviewer --json
|
|
72
72
|
```
|
|
73
73
|
```text
|
|
74
74
|
# Directly record a deferred divergence (requires --reason/--expiry)
|
|
75
75
|
canon divergence defer <SCENARIO_ID> --actor <ACTOR_ID> --reason <TEXT> --expiry <TIMESTAMP> [--project <PROJECT_ID>] [--rev <REV>] [--round <N>] [--session <SESSION_ID>] [--role <ROLE>] [--input]
|
|
76
76
|
```
|
|
77
77
|
```bash
|
|
78
|
-
canon divergence defer auth.login.01 --actor alice --reason "waiting on the vendor" --expiry 2030-01-01T00:00:00Z --role reviewer
|
|
78
|
+
canon divergence defer auth.login.01 --actor alice --reason "waiting on the vendor" --expiry 2030-01-01T00:00:00Z --role reviewer --json
|
|
79
79
|
```
|
|
80
80
|
```text
|
|
81
81
|
# List the current divergence burn-down state
|
|
82
82
|
canon divergence list [--as-of <TIMESTAMP>] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>]
|
|
83
83
|
```
|
|
84
84
|
```bash
|
|
85
|
-
canon divergence list --as-of 2030-01-01
|
|
85
|
+
canon divergence list --as-of 2030-01-01 --json
|
|
86
86
|
```
|
|
87
87
|
```text
|
|
88
88
|
# Directly record a resolved divergence
|
|
89
89
|
canon divergence resolve <SCENARIO_ID> --actor <ACTOR_ID> [--project <PROJECT_ID>] [--rev <REV>] [--round <N>] [--session <SESSION_ID>] [--detail <TEXT>] [--role <ROLE>] [--input]
|
|
90
90
|
```
|
|
91
91
|
```bash
|
|
92
|
-
canon divergence resolve auth.login.01 --actor alice --role reviewer
|
|
92
|
+
canon divergence resolve auth.login.01 --actor alice --role reviewer --json
|
|
93
93
|
```
|
|
94
94
|
```text
|
|
95
95
|
# Record one attributed EvidenceRecord for a task or scenario
|
|
96
|
-
canon evidence add [--task <TASK_ID>] [--project <PROJECT_ID>] [--class <CLASS>] [--ref <TEXT>] [--verdict <faithful|not-applicable|divergent>] [--summary <TEXT>] [--command-result <TEXT>] [--scenario <SCENARIO_ID>] [--run <RUN_ID>] [--surface-ref <PATH_OR_EFFECT>]* [--actor <ACTOR_ID>] [--role <ROLE>] [--session <SESSION_ID>] [--approver <NAME>] [--approval-role <human>] [--signature-file <FILE>] [--approval-at <TIMESTAMP>] [--rev <REV>] [--artifact <PATH>]* [--report <FORMAT:PATH>]* [--report-case <NAME>
|
|
96
|
+
canon evidence add [--task <TASK_ID> | --all-scenarios] [--project <PROJECT_ID>] [--class <CLASS>] [--ref <TEXT>] [--verdict <faithful|not-applicable|divergent>] [--summary <TEXT>] [--command-result <TEXT> (with --summary)] [--scenario <SCENARIO_ID> | --all-scenarios] [--run <RUN_ID>] [--surface-ref <PATH_OR_EFFECT>]* [--actor <ACTOR_ID>] [--role <ROLE>] [--session <SESSION_ID>] [--approver <NAME> | --all-scenarios] [--approval-role <human> | --all-scenarios] [--signature-file <FILE> | --all-scenarios] [--approval-at <TIMESTAMP> | --all-scenarios] [--rev <REV>] [--artifact <PATH>]* [--report <FORMAT:PATH>]* [--report-case <NAME> | --all-scenarios]* [--max-artifact-mib <N>] [--override-reason <TEXT>] [--promote | --no-promote] [--input]
|
|
97
97
|
```
|
|
98
98
|
```bash
|
|
99
|
-
canon evidence add --scenario auth.login.01 --class test-run --ref "npm test" --role implementer
|
|
99
|
+
canon evidence add --scenario auth.login.01 --class test-run --ref "npm test" --role implementer --json
|
|
100
100
|
```
|
|
101
101
|
```text
|
|
102
102
|
# Emit exact bytes for external `ssh-keygen -Y sign -n canon-approval-v1`
|
|
103
103
|
canon evidence approval-payload --approver <NAME> --approval-at <TIMESTAMP> [--task <TASK_ID>] [--project <PROJECT_ID>] [--scenario <SCENARIO_ID>] [--run <RUN_ID>] [--rev <REV>] [--surface-ref <PATH_OR_EFFECT>]*
|
|
104
104
|
```
|
|
105
105
|
```bash
|
|
106
|
-
canon evidence approval-payload --scenario auth.login.01 --project root --approver alice --approval-at 2030-01-01T00:00:00Z
|
|
106
|
+
canon evidence approval-payload --scenario auth.login.01 --project root --approver alice --approval-at 2030-01-01T00:00:00Z --json
|
|
107
107
|
```
|
|
108
108
|
```text
|
|
109
109
|
# Record an external evaluator's re-audit of one scenario (class `audit`; the verdict follows --audit-result; canon never runs the evaluator)
|
|
110
|
-
canon evidence audit <SCENARIO_ID> --ref <TEXT> --evaluator <ID> --evaluator-version <TEXT> --evaluator-digest <DIGEST> --audit-result <confirmed|refuted|indeterminate> [--project <PROJECT_ID>] [--summary <TEXT>] [--command-result <TEXT>] [--run <RUN_ID>] [--actor <ACTOR_ID>] [--role <ROLE>] [--session <SESSION_ID>] [--rev <REV>] [--artifact <PATH>]* [--report <FORMAT:PATH>]* [--report-case <NAME>]* [--max-artifact-mib <N>] [--override-reason <TEXT>] [--promote | --no-promote] [--input]
|
|
110
|
+
canon evidence audit <SCENARIO_ID> --ref <TEXT> --evaluator <ID> --evaluator-version <TEXT> --evaluator-digest <DIGEST> --audit-result <confirmed|refuted|indeterminate> [--project <PROJECT_ID>] [--summary <TEXT>] [--command-result <TEXT> (with --summary)] [--run <RUN_ID>] [--actor <ACTOR_ID>] [--role <ROLE>] [--session <SESSION_ID>] [--rev <REV>] [--artifact <PATH>]* [--report <FORMAT:PATH>]* [--report-case <NAME> (with --report)]* [--max-artifact-mib <N>] [--override-reason <TEXT>] [--promote | --no-promote] [--input]
|
|
111
111
|
```
|
|
112
112
|
```bash
|
|
113
|
-
canon evidence audit auth.login.01 --ref audit-report.json --evaluator eval-1 --evaluator-version 2.1 --evaluator-digest 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef --audit-result confirmed --role implementer
|
|
113
|
+
canon evidence audit auth.login.01 --ref audit-report.json --evaluator eval-1 --evaluator-version 2.1 --evaluator-digest 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef --audit-result confirmed --role implementer --json
|
|
114
114
|
```
|
|
115
115
|
```text
|
|
116
116
|
# Create a fresh .feature file for a new area.surface
|
|
117
117
|
canon feature new <SURFACE> --title <TEXT> [--actor <ACTOR_ID>] [--session <SESSION_ID>] [--project <PROJECT_ID>] [--input]
|
|
118
118
|
```
|
|
119
119
|
```bash
|
|
120
|
-
canon feature new billing.invoice --title Invoices
|
|
120
|
+
canon feature new billing.invoice --title Invoices --json
|
|
121
121
|
```
|
|
122
122
|
```text
|
|
123
123
|
# List a change's committed findings at their latest version
|
|
124
124
|
canon finding list --change <CHANGE_ID> [--open] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>]
|
|
125
125
|
```
|
|
126
126
|
```bash
|
|
127
|
-
canon finding list --change add-login
|
|
127
|
+
canon finding list --change add-login --json
|
|
128
128
|
```
|
|
129
129
|
```text
|
|
130
130
|
# Validate a spec/artifact corpus against canon's format
|
|
131
131
|
canon format [<DIR>]
|
|
132
132
|
```
|
|
133
133
|
```bash
|
|
134
|
-
canon format .canon/specs
|
|
134
|
+
canon format .canon/specs --json
|
|
135
135
|
```
|
|
136
136
|
```text
|
|
137
137
|
# Run the coverage/ledger/staleness/trust checks (0 clean, 1 red, 2 usage)
|
|
138
138
|
canon gate check [--release]
|
|
139
139
|
```
|
|
140
140
|
```bash
|
|
141
|
-
canon gate check
|
|
141
|
+
canon gate check --json
|
|
142
142
|
```
|
|
143
143
|
```text
|
|
144
144
|
# Promote staged records (evidence, findings, divergences) to the committed ledger
|
|
145
145
|
canon gate promote [--kind <evidence|finding|divergence>] [--dry-run] [--input]
|
|
146
146
|
```
|
|
147
147
|
```bash
|
|
148
|
-
canon gate promote --kind evidence
|
|
148
|
+
canon gate promote --kind evidence --json
|
|
149
149
|
```
|
|
150
150
|
```text
|
|
151
151
|
# Validate each spec root, then materialize scenario index records
|
|
152
152
|
canon inventory sync [--spec-root <DIR>] [--dry-run] [--input]
|
|
153
153
|
```
|
|
154
154
|
```bash
|
|
155
|
-
canon inventory sync
|
|
155
|
+
canon inventory sync --json
|
|
156
156
|
```
|
|
157
157
|
```text
|
|
158
158
|
# Read stored records across every storage tier
|
|
159
159
|
canon query --kind <change|task|scenario|session|run|event|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding> [--since <TIMESTAMP>] [--plugin <PLUGIN_ID> | --history] [--change <CHANGE_ID>] [--status <STATUS>] [--domain <NAME>] [--include-sensitive] [--limit <N> | --all] [--cursor <CURSOR>] [--fields <FIELDS>]
|
|
160
160
|
```
|
|
161
161
|
```bash
|
|
162
|
-
canon query --kind evidence
|
|
162
|
+
canon query --kind evidence --json
|
|
163
163
|
```
|
|
164
164
|
```text
|
|
165
165
|
# Fetch role-scoped strategy guidance
|
|
166
|
-
canon retrieve --for-role <ROLE>
|
|
166
|
+
canon retrieve --for-role <ROLE> (--regime <KEY> | --domain <NAME>) [--subject <SUBJECT_ID> (with --domain)] [--limit <N>]
|
|
167
167
|
```
|
|
168
168
|
```bash
|
|
169
|
-
canon retrieve --for-role reviewer --domain dev --limit 20
|
|
169
|
+
canon retrieve --for-role reviewer --domain dev --limit 20 --json
|
|
170
170
|
```
|
|
171
171
|
```text
|
|
172
172
|
# Append a tagged scenario stub to its .feature file (created if missing); many at once with `--input`
|
|
173
173
|
canon scenario new <SCENARIO_ID> --title <TEXT> [--subject <SUBJECT_ID>] [--lane <NAME>] [--case <NAME>] [--flow <FLOW_ID>] [--change <CHANGE_ID> (with --flow)] [--actor <ACTOR_ID>] [--session <SESSION_ID>] [--feature <FILE>] [--project <PROJECT_ID>] [--input]
|
|
174
174
|
```
|
|
175
175
|
```bash
|
|
176
|
-
canon scenario new auth.login.02 --title "Sign out" --feature .canon/specs/kind=feature/area=auth/login.feature
|
|
176
|
+
canon scenario new auth.login.02 --title "Sign out" --feature .canon/specs/kind=feature/area=auth/login.feature --json
|
|
177
177
|
```
|
|
178
178
|
```text
|
|
179
179
|
# Describe canon's own commands
|
|
180
|
-
canon schema [<PATH>]* [--errors | --error <CODE>]
|
|
180
|
+
canon schema [<PATH>]* [--errors | --error <CODE> | --warning <CODE> | --warnings]
|
|
181
181
|
```
|
|
182
182
|
```bash
|
|
183
|
-
canon schema evidence add
|
|
183
|
+
canon schema evidence add --json
|
|
184
184
|
```
|
|
185
185
|
```text
|
|
186
186
|
# Search records, brief sections and scenario text, with each hit's neighbors in the record graph
|
|
187
187
|
canon search <TEXT> [--kind <change|task|scenario|session|run|event|handoff|review|divergence|trajectory|strategy_item|evidence|subject|finding|brief>]* [--expand <N>] [--limit <N>]
|
|
188
188
|
```
|
|
189
189
|
```bash
|
|
190
|
-
canon search timeout --kind finding
|
|
190
|
+
canon search timeout --kind finding --json
|
|
191
191
|
```
|
|
192
192
|
```text
|
|
193
193
|
# Print a guide built into this binary (markdown on stdout); the installed SKILL.md is a stub that points here
|
|
194
194
|
canon skills show <NAME> [--full]
|
|
195
195
|
```
|
|
196
196
|
```bash
|
|
197
|
-
canon skills show canon --full
|
|
197
|
+
canon skills show canon --full --json
|
|
198
198
|
```
|
|
199
199
|
```text
|
|
200
200
|
# Show where this repo stands: subjects by status, their gaps, and the next commands
|
|
201
201
|
canon status [--fields <FIELDS>]
|
|
202
202
|
```
|
|
203
203
|
```bash
|
|
204
|
-
canon status
|
|
204
|
+
canon status --json
|
|
205
205
|
```
|
|
206
206
|
```text
|
|
207
207
|
# Flip one task checkbox, gated on real evidence (fails closed)
|
|
208
208
|
canon task done <TASK_ID> [--input]
|
|
209
209
|
```
|
|
210
210
|
```bash
|
|
211
|
-
canon task done add-login#1
|
|
211
|
+
canon task done add-login#1 --json
|
|
212
212
|
```
|
|
213
213
|
```text
|
|
214
214
|
# Follow a finding's review loop in time order: review, finding, fix, re-review, evidence
|
|
215
215
|
canon trace <ID>
|
|
216
216
|
```
|
|
217
217
|
```bash
|
|
218
|
-
canon trace add-login_1_1
|
|
218
|
+
canon trace add-login_1_1 --json
|
|
219
219
|
```
|
|
220
220
|
<!-- canon:generated commands-implementer end -->
|
|
221
221
|
|
|
222
222
|
After the first `status`, follow `meta.next` of each write; do not call
|
|
223
|
-
`canon status` again to learn the next step. Every record you write takes
|
|
223
|
+
`canon status` again to learn the next step. Each `meta.next` entry is runnable: run `canon` + its `argv`; guidance that needs a value you must fill in is in the error `hint` or the report text, not in `meta.next`. Every record you write takes
|
|
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
|
|
@@ -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 (`/items/1/case`).
|
|
256
|
-
`canon schema scenario new --json` shows the
|
|
256
|
+
`canon schema scenario new --json` shows `input`: the schema of one document and a complete `example`.
|
|
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
|
|
@@ -371,7 +371,7 @@ not another evidence step.
|
|
|
371
371
|
## Retry safety
|
|
372
372
|
|
|
373
373
|
`evidence add` is content-keyed: repeating it with identical input returns
|
|
374
|
-
the existing record with `
|
|
374
|
+
the existing record with `data.unchanged: true` instead of a duplicate (a
|
|
375
375
|
batch reports that element `unchanged`). After a timeout or a lost
|
|
376
376
|
response, run the same command again. `scenario new` is not: an existing
|
|
377
377
|
scenario id is refused (`SCENARIO_TAG_EXISTS`) and nothing changes, so check
|