@journeykit/canon 0.34.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 +47 -30
- package/dist/skills/reference/canon-artifact-ingest.md +6 -3
- package/dist/skills/reference/canon-authoring.md +9 -5
- package/dist/skills/reference/canon-context.md +6 -3
- package/dist/skills/reference/canon-fmt.md +2 -1
- package/dist/skills/reference/canon-gate.md +29 -21
- package/dist/skills/reference/canon-inventory.md +16 -11
- package/dist/skills/reference/canon-plan-import.md +6 -3
- package/dist/skills/reference/canon-plugins.md +12 -6
- package/dist/skills/reference/canon-policy.md +3 -3
- package/dist/skills/reference/canon-report-dashboard.md +11 -8
- package/dist/skills/reference/canon-review.md +8 -7
- package/dist/skills/reference/canon-session-ingest.md +12 -6
- package/dist/skills/reference/canon-storage.md +47 -17
- package/dist/skills/reference/canon-subject.md +45 -35
- package/dist/skills/reference/role-implementer.md +33 -33
- package/dist/skills/reference/role-orchestrator.md +83 -77
- package/dist/skills/reference/role-planner.md +28 -28
- package/dist/skills/reference/role-reviewer.md +29 -29
- 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 +7 -7
- 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 +5 -5
- 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,30 +211,40 @@ 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: ""`).
|
|
228
238
|
Read the members you know and ignore the ones you do not: a later canon
|
|
229
239
|
adds members, and a value of a closed set you have not seen (a `severity`, an
|
|
230
240
|
`outcome`, a `reason`) is one item to leave out, never a reason to reject the document. A paged list puts
|
|
231
|
-
`meta.page.nextCursor`
|
|
232
|
-
no `nextCursor` means no more.
|
|
241
|
+
`meta.page.nextCursor` in the first entry of the call's `meta.next` as `--cursor=<nextCursor>`
|
|
242
|
+
(run that entry as it is); no `nextCursor` means no more.
|
|
233
243
|
On failure branch on `error.code`, and on `error.reason` where the code has
|
|
234
244
|
reasons (`INPUT_INVALID` says `NOT_JSON`, `UNKNOWN_KEY`, `STDIN_TTY`, … so you
|
|
235
245
|
know whether to fix the JSON or the shell); fix the option `error.field` names
|
|
236
246
|
using the `error.expected` values (`field` is an option name, or a JSON
|
|
237
|
-
pointer such as `/
|
|
247
|
+
pointer such as `/2/scenario` into an `--input` document, `/<index>/<key>` in a batch), and
|
|
238
248
|
follow `error.hint`: it is one runnable command line that starts with `canon`, the
|
|
239
249
|
same with `<PLACEHOLDER>`s you fill in, or one sentence. The codes
|
|
240
250
|
are stable; `canon schema --errors --json` lists them with their reasons and
|
|
@@ -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` and `--
|
|
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.
|
|
@@ -277,11 +287,12 @@ the positional arguments. An object is one invocation; a JSON array (or NDJSON
|
|
|
277
287
|
from a file or stdin) is a batch, run in order and answered with
|
|
278
288
|
`data.items[]` (`index`, `status` of `written`, `unchanged`, `failed` or
|
|
279
289
|
`skipped`, and that element's `data` or `error`). A batch is validated whole
|
|
280
|
-
before anything is written: an invalid element writes nothing and exits 2
|
|
281
|
-
`error.field` pointing at
|
|
282
|
-
|
|
283
|
-
`
|
|
284
|
-
`
|
|
290
|
+
before anything is written, and that check reads no state: an invalid element writes nothing and exits 2 with
|
|
291
|
+
its own code, `error.field` pointing at `/<i>/<key>` and no `data`. An element that fails when it runs (the object
|
|
292
|
+
it names does not exist) stops the batch: exit 1, `BATCH_INCOMPLETE`, `error.field` exactly `/<i>`, the element
|
|
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
|
|
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.
|
|
285
296
|
|
|
286
297
|
```text
|
|
287
298
|
canon scenario new --input '[{"operands":["auth.login.01"],"title":"Logs in","case":"happy"},{"operands":["auth.login.02"],"title":"Wrong password","case":"failure"}]'
|
|
@@ -329,12 +340,18 @@ and `canon context` warn when the repo holds 0.27-era state and put
|
|
|
329
340
|
## Setup and provider projection
|
|
330
341
|
|
|
331
342
|
```bash
|
|
332
|
-
|
|
333
|
-
canon init
|
|
334
|
-
|
|
335
|
-
canon
|
|
336
|
-
canon skills
|
|
337
|
-
canon skills
|
|
343
|
+
# canon.yaml, starter policy (--policy light|standard|strict, default strict; see canon-policy), AGENTS.md block, commented plans examples
|
|
344
|
+
canon init
|
|
345
|
+
# harnesses for the canon skill; without it init takes the detected .claude/.codex/.omp/.pi (it never asks)
|
|
346
|
+
canon init --providers=claude,codex
|
|
347
|
+
# follows canon.yaml skills.providers (else the install lock's, else the detected ones; none detected installs nothing); prunes projected files the bundle no longer ships when their bytes match the lock, keeps a modified one and reports `kept:`
|
|
348
|
+
canon skills install
|
|
349
|
+
# any subset or none; rewrites skills.providers
|
|
350
|
+
canon skills install --providers=claude,codex,omp,pi
|
|
351
|
+
# read-only drift check; exit 1 (SKILLS_CHECK_FAILED) names each orphan, a projected file the bundle no longer ships
|
|
352
|
+
canon skills check
|
|
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
|
|
354
|
+
canon skills doctor
|
|
338
355
|
```
|
|
339
356
|
|
|
340
357
|
`install` writes, per selected harness, a short `SKILL.md` stub (this file's
|
|
@@ -9,9 +9,12 @@ verdicts, and writes idempotently.
|
|
|
9
9
|
## `canon ingest records [--repo <dir>] [--watch]`
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
|
|
13
|
-
canon ingest records
|
|
14
|
-
|
|
12
|
+
# one pass over the repo's artifacts
|
|
13
|
+
canon ingest records
|
|
14
|
+
# a specific repo
|
|
15
|
+
canon ingest records --repo ../svc
|
|
16
|
+
# poll loop
|
|
17
|
+
canon ingest records --watch
|
|
15
18
|
```
|
|
16
19
|
|
|
17
20
|
Source roots resolve from `canon.yaml`'s `artifacts.sources` config
|
|
@@ -92,11 +92,14 @@ a scoped gate.
|
|
|
92
92
|
## The commands — and the one thing you never type
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
-
|
|
95
|
+
# once per surface
|
|
96
|
+
canon feature new checkout.cart --title "Cart"
|
|
97
|
+
# once per behavior
|
|
96
98
|
canon scenario new checkout.cart.01 --title "Adding an item raises the count" \
|
|
97
|
-
--subject checkout-core --lane behavior --case happy
|
|
99
|
+
--subject checkout-core --lane behavior --case happy
|
|
100
|
+
# and its failure path
|
|
98
101
|
canon scenario new checkout.cart.04 --title "Adding an out-of-stock item is refused" \
|
|
99
|
-
--subject checkout-core --lane behavior --case failure
|
|
102
|
+
--subject checkout-core --lane behavior --case failure
|
|
100
103
|
```
|
|
101
104
|
|
|
102
105
|
There is no format or sync step after these: the scaffold writes a
|
|
@@ -111,8 +114,9 @@ Fix it and the next command indexes the files (see `canon-inventory`).
|
|
|
111
114
|
Many scenarios at once: `--input` takes inline JSON, a file or `-`. An
|
|
112
115
|
array (or NDJSON) is a batch, validated whole before anything is written;
|
|
113
116
|
each element holds `operands` (the scenario tag) and the other options as
|
|
114
|
-
camelCase keys. `canon schema scenario new --json` shows `input
|
|
115
|
-
|
|
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`.
|
|
116
120
|
|
|
117
121
|
```text
|
|
118
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"}]'
|
|
@@ -13,9 +13,12 @@ deterministic authoring surface.
|
|
|
13
13
|
## `canon context [--repo <dir>] [--json]`
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
|
|
17
|
-
canon context
|
|
18
|
-
|
|
16
|
+
# compact human outline (prompt-injectable)
|
|
17
|
+
canon context
|
|
18
|
+
# the full machine-readable surface
|
|
19
|
+
canon context --json
|
|
20
|
+
# resolve a specific repo's surface
|
|
21
|
+
canon context --repo ../other
|
|
19
22
|
```
|
|
20
23
|
|
|
21
24
|
The outline opens with a short header, then a blank line, then the
|
|
@@ -9,7 +9,8 @@ rewrites or mutates the corpus — it only validates and reports.
|
|
|
9
9
|
## Running
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
|
|
12
|
+
# e.g. a consumer repo's spec/
|
|
13
|
+
canon format spec
|
|
13
14
|
```
|
|
14
15
|
|
|
15
16
|
With no operand, `canon format` validates every `specs.roots[]` entry of
|
|
@@ -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
|
|
|
@@ -42,8 +42,10 @@ corpus and runs them, printing every violation grouped by failure class.
|
|
|
42
42
|
when `--release` is passed.
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
|
|
46
|
-
canon gate check --repo .
|
|
45
|
+
# ordinary evaluation
|
|
46
|
+
canon gate check --repo .
|
|
47
|
+
# + trust-below-required
|
|
48
|
+
canon gate check --repo . --release
|
|
47
49
|
```
|
|
48
50
|
|
|
49
51
|
Exit `0` clean, `1` gate-red (any violation), `2` usage/load failure
|
|
@@ -223,9 +225,9 @@ canon divergence accept cart.add.01 --project root --reason "known gap" --tracki
|
|
|
223
225
|
|
|
224
226
|
Accepting a scenario whose latest evidence is `divergent` as a known gap
|
|
225
227
|
limited by something outside the change is a human-only act: with a role
|
|
226
|
-
declared (`--as`, `CANON_ROLE`) the leaf is refused with `
|
|
228
|
+
declared (`--as`, `CANON_ROLE`) the leaf is refused with `ACTOR_DENIED`. It is
|
|
227
229
|
never a way to skip a fix.
|
|
228
|
-
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
|
|
229
231
|
divergent and the session and actor differ from the evidence's. The record
|
|
230
232
|
pins that evidence: new evidence for the scenario, or `--expiry` passing,
|
|
231
233
|
ends it. While it holds, the ship guard counts the cell covered and
|
|
@@ -302,10 +304,10 @@ never rides along into a confirming audit. `--drop-attachment` and
|
|
|
302
304
|
The approval is never assumed: the agent writes the brief, shows it to the
|
|
303
305
|
human and asks, and builds nothing for that scope until the human answers.
|
|
304
306
|
`canon evidence add` is the backstop for that rule (0.16 M7). It
|
|
305
|
-
refuses (exit `
|
|
307
|
+
refuses (exit `2`, nothing staged or stored) while a subject the record
|
|
306
308
|
attests for has an enforced, unapproved brief: a change the record
|
|
307
309
|
answers to (below) has a canon `.canon/changes/<change>/brief.md` with no `Approved:`
|
|
308
|
-
line, was edited after its approval (`
|
|
310
|
+
line, was edited after its approval (`BRIEF_APPROVAL_STALE`), or
|
|
309
311
|
there is no canon `brief.md` yet but the change comes from an
|
|
310
312
|
external openspec plan with a `proposal.md` under the plan sources (the
|
|
311
313
|
check `canon status` and the ship guard use; see
|
|
@@ -314,8 +316,8 @@ check `canon status` and the ship guard use; see
|
|
|
314
316
|
`--task`:
|
|
315
317
|
|
|
316
318
|
```stderr
|
|
317
|
-
canon evidence add: unreviewed-promotion demo-subject — evidence for world.demo.01: brief not approved — .canon/changes/c-demo/brief.md has no `Approved:` line, so the human has not answered it; once they do, record their words with `canon brief approve c-demo --approver <the human> --note "<their words>"`
|
|
318
|
-
canon evidence add: refused — stop and get the human's answer to the brief: nothing is built or attested for a subject before its brief is approved. Show it (`canon brief show --body`), ask with the harness question tool, and on their explicit approval record it with `canon brief approve --approver <their name> --note "<their words>" --relayed-via <the question tool> --actor <your actor id> --digest <change>=<the digest shown>` (or they approve on `canon dashboard`); never unset your role to run it; to attest anyway, pass --override-reason <text>, which is recorded on the evidence record
|
|
319
|
+
stderr: canon evidence add: unreviewed-promotion demo-subject — evidence for world.demo.01: brief not approved — .canon/changes/c-demo/brief.md has no `Approved:` line, so the human has not answered it; once they do, record their words with `canon brief approve c-demo --approver <the human> --note "<their words>"`
|
|
320
|
+
stderr: canon evidence add: refused — stop and get the human's answer to the brief: nothing is built or attested for a subject before its brief is approved. Show it (`canon brief show --body`), ask with the harness question tool, and on their explicit approval record it with `canon brief approve --approver <their name> --note "<their words>" --relayed-via <the question tool> --actor <your actor id> --digest <change>=<the digest shown>` (or they approve on `canon dashboard`); never unset your role to run it; to attest anyway, pass --override-reason <text>, which is recorded on the evidence record
|
|
319
321
|
```
|
|
320
322
|
|
|
321
323
|
For a change from an external plan with no canon brief yet, the first
|
|
@@ -459,7 +461,7 @@ mentions. Each bound case is its own attachment with its name and
|
|
|
459
461
|
outcome. `--report-case <name>` (repeatable; a Rust test by its
|
|
460
462
|
function name) ADDS cases; it never hides the scenario's own. No match,
|
|
461
463
|
or a `--report-case` naming no case, refuses (exit 2); a `faithful`
|
|
462
|
-
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
|
|
463
465
|
must be inside the repository, are recorded by relative path, and are
|
|
464
466
|
stored (see Bound evidence stays provable).
|
|
465
467
|
|
|
@@ -515,8 +517,9 @@ report (a JUnit test case's `[[ATTACHMENT|path]]` lines, which Playwright's
|
|
|
515
517
|
JUnit reporter writes; a Cucumber JSON embedding), so a test's screenshot
|
|
516
518
|
stays with its scenario. A file the report does not name goes with
|
|
517
519
|
`--artifact <scenario-id>=<path>`; a bare `--artifact <path>` in a batch is
|
|
518
|
-
refused (`
|
|
519
|
-
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`).
|
|
520
523
|
|
|
521
524
|
It is all or nothing: a claimed `faithful` verdict over a failed case,
|
|
522
525
|
a fabrication marker in `--summary`, an unapproved brief for any
|
|
@@ -534,13 +537,14 @@ or `-`; an array (or NDJSON) is a batch, validated element by element before
|
|
|
534
537
|
the first write (a refusal writes nothing, exit 2). Keys are the option
|
|
535
538
|
names in camelCase plus `operands`: one object per scenario, with
|
|
536
539
|
`scenario`, `class`, `ref` and `role`. `canon schema evidence add --json`
|
|
537
|
-
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`,
|
|
538
542
|
`unchanged` or `failed` in `data.items[]`.
|
|
539
543
|
|
|
540
544
|
`--rev <rev>` names the commit the evidence ran against (default `HEAD`).
|
|
541
545
|
Evidence for uncommitted code is recorded with its `codeTree` and
|
|
542
546
|
`worktreeDirty`; outside git, or with no commit, the add is refused with
|
|
543
|
-
`
|
|
547
|
+
`COMMIT_REQUIRED`.
|
|
544
548
|
|
|
545
549
|
**Done when:** `canon gate check` shows no violation for the scenarios you
|
|
546
550
|
recorded evidence for; each record's own output line says whether it was
|
|
@@ -553,7 +557,7 @@ current pinned review saw, `canon evidence add` prints one line per
|
|
|
553
557
|
review it makes stale (its verdict or checks differ from what the review saw), with the command that re-pins it:
|
|
554
558
|
|
|
555
559
|
```stderr
|
|
556
|
-
canon evidence add: review by `reviewer-2` of cart.add.01 is now stale (this record's verdict or checks differ from what it saw); re-pin it: canon review scenario cart.add.01 --project root --actor reviewer-2 --role reviewer --original-spec-ref specs/kind=feature/area=cart/add.feature
|
|
560
|
+
stderr: canon evidence add: review by `reviewer-2` of cart.add.01 is now stale (this record's verdict or checks differ from what it saw); re-pin it: canon review scenario cart.add.01 --project root --actor reviewer-2 --role reviewer --original-spec-ref specs/kind=feature/area=cart/add.feature
|
|
557
561
|
```
|
|
558
562
|
|
|
559
563
|
The decision is the gate's own (the same stale-review rule `canon gate
|
|
@@ -695,7 +699,7 @@ aggregates every record bound to the task, on one line:
|
|
|
695
699
|
(the latest `--summary`, or a default naming the latest passing record).
|
|
696
700
|
Every other path — missing evidence, a `Divergent` verdict, a fabricated
|
|
697
701
|
note on any of the task's records — leaves the row byte-unchanged and
|
|
698
|
-
exits `
|
|
702
|
+
exits `2` with the blocking violation on stderr. After a flip, the plan
|
|
699
703
|
source is re-ingested so the record store's task status agrees with the
|
|
700
704
|
checkbox (`canon query --kind task` reads `done`); a failed re-ingest is
|
|
701
705
|
a stderr warning naming `canon ingest plans`, never a failed flip.
|
|
@@ -732,13 +736,15 @@ Staging → committed: every well-formed record under
|
|
|
732
736
|
applies, assigned a monotonic per-(role, surface) `run_seq` (gap-free
|
|
733
737
|
within one invocation, continuing from the committed max), and moved into
|
|
734
738
|
the committed ledger. A malformed or unpartitionable candidate is refused
|
|
735
|
-
— 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`
|
|
736
740
|
prints the plan (target path + assigned `run_seq` per candidate) without
|
|
737
741
|
writing or deleting.
|
|
738
742
|
|
|
739
743
|
```bash
|
|
740
|
-
|
|
741
|
-
canon gate promote --repo .
|
|
744
|
+
# land every staged candidate
|
|
745
|
+
canon gate promote --repo .
|
|
746
|
+
# preview only
|
|
747
|
+
canon gate promote --repo . --dry-run
|
|
742
748
|
```
|
|
743
749
|
|
|
744
750
|
Which writes need this step: `evidence add`, `finding add` and `finding
|
|
@@ -785,8 +791,10 @@ It installs no git hook: copy the script into git's `pre-commit` hook
|
|
|
785
791
|
agent hook files and the script, also under `--dry-run`. In `--json`,
|
|
786
792
|
`installed` is true when an agent hook file changed and
|
|
787
793
|
`preCommitScriptWritten` when the script was written. A `--repo` that is not an
|
|
788
|
-
existing directory exits 2 with `
|
|
789
|
-
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.
|
|
790
798
|
|
|
791
799
|
Prefer this over hand-editing `settings.json`/`hooks.json`.
|
|
792
800
|
|
|
@@ -14,7 +14,7 @@ same code this command runs, scoped to the changed files, and say so in one
|
|
|
14
14
|
stderr line:
|
|
15
15
|
|
|
16
16
|
```stderr
|
|
17
|
-
canon artifacts store: refreshed the scenario index from 1 changed feature file(s) (.canon/specs/kind=feature/area=cart/add.feature): 1 record(s) written
|
|
17
|
+
stderr: canon artifacts store: refreshed the scenario index from 1 changed feature file(s) (.canon/specs/kind=feature/area=cart/add.feature): 1 record(s) written
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
`canon status` and `canon gate check` are read commands and write nothing:
|
|
@@ -76,14 +76,14 @@ author .feature corpus (canon scenario new)
|
|
|
76
76
|
scenario index # refreshed by the writers; `canon inventory sync` rebuilds it
|
|
77
77
|
│
|
|
78
78
|
▼
|
|
79
|
-
canon review scenario # attests a review — see canon-inventory downstream / canon-gate
|
|
80
|
-
canon divergence add|resolve|defer|accept|list # tracks/resolves a divergence
|
|
81
|
-
canon gate check [--release] # trust-ladder / staleness / coverage — see canon-gate
|
|
79
|
+
review: canon review scenario # attests a review — see canon-inventory downstream / canon-gate
|
|
80
|
+
diverge: canon divergence add|resolve|defer|accept|list # tracks/resolves a divergence
|
|
81
|
+
gate: canon gate check [--release] # trust-ladder / staleness / coverage — see canon-gate
|
|
82
82
|
│
|
|
83
83
|
▼
|
|
84
|
-
canon ingest records # with artifacts.native_records: true in canon.yaml —
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
ingest: canon ingest records # with artifacts.native_records: true in canon.yaml —
|
|
85
|
+
# feeds review/divergence verdicts into the flywheel
|
|
86
|
+
# (see canon-artifact-ingest)
|
|
87
87
|
```
|
|
88
88
|
|
|
89
89
|
Every stage after the index joins on the SAME `(project_id, scenario_id)`
|
|
@@ -92,9 +92,12 @@ pair it materializes — one identity scheme, no second one.
|
|
|
92
92
|
## `canon inventory sync [--repo <dir>] [--spec-root <dir>]`
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
-
|
|
96
|
-
canon inventory sync
|
|
97
|
-
|
|
95
|
+
# every canon.yaml specs.roots[] entry
|
|
96
|
+
canon inventory sync
|
|
97
|
+
# a specific repo
|
|
98
|
+
canon inventory sync --repo ../svc
|
|
99
|
+
# ad hoc: ignore canon.yaml entirely
|
|
100
|
+
canon inventory sync --spec-root ./specs
|
|
98
101
|
```
|
|
99
102
|
|
|
100
103
|
Per configured root, in order:
|
|
@@ -161,7 +164,9 @@ specs:
|
|
|
161
164
|
whole root aborts, 0 writes, violations reported.
|
|
162
165
|
- **A root on the pre-0.17 layout** (a `.feature` file under
|
|
163
166
|
`<root>/features/`) → a `layout-grammar` violation at path `features`;
|
|
164
|
-
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
|
|
165
170
|
leftover `features/` directory is not a refusal.
|
|
166
171
|
- **A duplicate `scenario_id`** within one root → that root aborts, 0
|
|
167
172
|
writes, reported as a sync error (a distinct lane from fmt violations).
|
|
@@ -64,9 +64,12 @@ canon ingest plans --dialect openspec --plan-source ../other-repo
|
|
|
64
64
|
## 2. Run the import
|
|
65
65
|
|
|
66
66
|
```bash
|
|
67
|
-
|
|
68
|
-
canon ingest plans
|
|
69
|
-
|
|
67
|
+
# .canon/changes/ + every configured source
|
|
68
|
+
canon ingest plans
|
|
69
|
+
# machine-readable outcome
|
|
70
|
+
canon ingest plans --json
|
|
71
|
+
# a specific repo root
|
|
72
|
+
canon ingest plans --repo ../svc
|
|
70
73
|
```
|
|
71
74
|
|
|
72
75
|
Per source the summary reports `changes_parsed`/`tasks_parsed`,
|
|
@@ -49,9 +49,12 @@ overlays:
|
|
|
49
49
|
Drive it through the sync command (never hand-write records):
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
|
-
|
|
53
|
-
canon plugin sync porting
|
|
54
|
-
|
|
52
|
+
# every canon.yaml specs.roots[] entry
|
|
53
|
+
canon plugin sync porting
|
|
54
|
+
# a specific repo
|
|
55
|
+
canon plugin sync porting --repo ../svc
|
|
56
|
+
# ad hoc: ignore canon.yaml
|
|
57
|
+
canon plugin sync porting --spec-root ./specs
|
|
55
58
|
```
|
|
56
59
|
|
|
57
60
|
`canon plugin sync <plugin-id>` resolves the manifest, then for each
|
|
@@ -70,9 +73,12 @@ error; the next step (3) reads the overlay back.
|
|
|
70
73
|
## 3. Project a read
|
|
71
74
|
|
|
72
75
|
```bash
|
|
73
|
-
|
|
74
|
-
canon query --kind scenario --plugin porting
|
|
75
|
-
|
|
76
|
+
# human table, projected fields appended
|
|
77
|
+
canon query --kind scenario --plugin porting
|
|
78
|
+
# merged record bodies
|
|
79
|
+
canon query --kind scenario --plugin porting --json
|
|
80
|
+
# no --plugin: byte-identical to the core view
|
|
81
|
+
canon query --kind scenario
|
|
76
82
|
```
|
|
77
83
|
|
|
78
84
|
`--plugin <id>` folds the plugin's overlay records (latest-by-
|
|
@@ -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
|
|
@@ -40,7 +40,8 @@ Renders the current ten-panel report to `<repo>/.canon/REPORT.md`.
|
|
|
40
40
|
subcommand uses — omit it (or pass `.`) to run from any subdirectory.
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
|
-
|
|
43
|
+
# writes .canon/REPORT.md
|
|
44
|
+
canon report build
|
|
44
45
|
canon report build --repo /path/to/repo
|
|
45
46
|
```
|
|
46
47
|
|
|
@@ -67,7 +68,8 @@ committed `.canon/REPORT.md`:
|
|
|
67
68
|
`canon report build`).
|
|
68
69
|
|
|
69
70
|
```bash
|
|
70
|
-
|
|
71
|
+
# wire into CI exactly like canon format / canon gate check
|
|
72
|
+
canon report check
|
|
71
73
|
```
|
|
72
74
|
|
|
73
75
|
Wire it as a CI step or pre-push hook the same way `canon gate
|
|
@@ -126,7 +128,8 @@ canon report snapshot /tmp/canon-snap
|
|
|
126
128
|
Serves the dashboard web app locally, pointed at a real snapshot:
|
|
127
129
|
|
|
128
130
|
```bash
|
|
129
|
-
|
|
131
|
+
# regenerates a fresh snapshot every run, serves it
|
|
132
|
+
canon dashboard
|
|
130
133
|
canon dashboard --snapshot /tmp/canon-snap --port 8080
|
|
131
134
|
```
|
|
132
135
|
|
|
@@ -140,7 +143,7 @@ canon dashboard --snapshot /tmp/canon-snap --port 8080
|
|
|
140
143
|
- Runs in any repo: the released binary carries the app (in canon's own
|
|
141
144
|
checkout a built `packages/dashboard/dist` is used instead). It prints the
|
|
142
145
|
panels URL and a briefs URL (`/briefs.html`), then serves until Ctrl-C.
|
|
143
|
-
A taken port fails with `
|
|
146
|
+
A taken port fails with `DASHBOARD_PORT_UNAVAILABLE`: pass `--port <n>` or
|
|
144
147
|
`--port 0`.
|
|
145
148
|
- Without the `duckdb` CLI on `PATH` the server still runs; the panels page
|
|
146
149
|
says why there is no snapshot and how to get one (it never shows demo
|
|
@@ -157,11 +160,11 @@ answer once and clicks Approve: one request carries every selected brief with
|
|
|
157
160
|
the sha256 of the file the page read, and records exactly what `canon brief
|
|
158
161
|
approve <id>+ --approver <name> --note <text>` records, the `Approved:` line
|
|
159
162
|
bound to the brief digest and the policy approval, for each. A brief that
|
|
160
|
-
changed after the page loaded (`
|
|
161
|
-
blockers refuses the whole request (409 `
|
|
162
|
-
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
|
|
163
166
|
naming one brief the old way (`changeId`, `sha256`) is still accepted. The server is localhost only and
|
|
164
|
-
refuses requests from other origins (`
|
|
167
|
+
refuses requests from other origins (`DASHBOARD_REQUEST_DENIED`).
|
|
165
168
|
|
|
166
169
|
For an agent: when clean briefs are waiting, show them (`canon brief show
|
|
167
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
|
|
|
@@ -468,14 +469,14 @@ With `require_review` present, `canon subject move <id> --to <state>`
|
|
|
468
469
|
prints on stderr which review checks it ran or skipped:
|
|
469
470
|
|
|
470
471
|
```stderr
|
|
471
|
-
canon subject move: review guard for building → verifying (spec_coverage.require_review, scope: verifying, shipped)
|
|
472
|
+
stderr: canon subject move: review guard for building → verifying (spec_coverage.require_review, scope: verifying, shipped)
|
|
472
473
|
ran unreviewed-promotion — every owned scenario needs a signed review, current with the spec and evidence it pinned, by an actor, and from a session, other than its evidence's
|
|
473
474
|
ran open-blocker — 1 adopted change(s) checked for open blocker findings
|
|
474
475
|
```
|
|
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
|