@journeykit/canon 0.31.0 → 0.33.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.
Files changed (125) hide show
  1. package/dist/index.js +4 -0
  2. package/dist/skills/SKILL.src.md +52 -25
  3. package/dist/skills/reference/brief-align.md +2 -2
  4. package/dist/skills/reference/brief-clarify.md +2 -2
  5. package/dist/skills/reference/brief-harden.md +2 -2
  6. package/dist/skills/reference/brief-polish.md +4 -4
  7. package/dist/skills/reference/brief-shape.md +2 -2
  8. package/dist/skills/reference/canon-context.md +1 -1
  9. package/dist/skills/reference/canon-gate.md +5 -5
  10. package/dist/skills/reference/canon-policy.md +7 -4
  11. package/dist/skills/reference/canon-report-dashboard.md +7 -4
  12. package/dist/skills/reference/canon-review.md +2 -2
  13. package/dist/skills/reference/canon-storage.md +4 -3
  14. package/dist/skills/reference/canon-subject.md +18 -16
  15. package/dist/skills/reference/role-implementer.md +12 -10
  16. package/dist/skills/reference/role-orchestrator.md +44 -29
  17. package/dist/skills/reference/role-planner.md +68 -29
  18. package/dist/skills/reference/role-reviewer.md +24 -16
  19. package/man/canon-adapter-authorize.1 +2 -2
  20. package/man/canon-adapter-validate.1 +2 -2
  21. package/man/canon-adapter.1 +2 -2
  22. package/man/canon-artifacts-move.1 +3 -3
  23. package/man/canon-artifacts-store.1 +2 -2
  24. package/man/canon-artifacts-verify.1 +2 -2
  25. package/man/canon-artifacts.1 +2 -2
  26. package/man/canon-brief-approve.1 +12 -3
  27. package/man/canon-brief-check.1 +2 -2
  28. package/man/canon-brief-show.1 +6 -3
  29. package/man/canon-brief.1 +2 -2
  30. package/man/canon-change-new.1 +2 -2
  31. package/man/canon-change.1 +2 -2
  32. package/man/canon-completion.1 +2 -2
  33. package/man/canon-context-pack-add.1 +2 -2
  34. package/man/canon-context-pack-show.1 +2 -2
  35. package/man/canon-context-pack-verify.1 +2 -2
  36. package/man/canon-context-pack.1 +2 -2
  37. package/man/canon-context.1 +2 -2
  38. package/man/canon-dashboard.1 +2 -2
  39. package/man/canon-demo-init.1 +2 -2
  40. package/man/canon-demo-review.1 +2 -2
  41. package/man/canon-demo.1 +2 -2
  42. package/man/canon-dispatch-begin.1 +2 -2
  43. package/man/canon-dispatch-diff.1 +2 -2
  44. package/man/canon-dispatch-end.1 +2 -2
  45. package/man/canon-dispatch.1 +2 -2
  46. package/man/canon-divergence-accept.1 +12 -3
  47. package/man/canon-divergence-add.1 +2 -2
  48. package/man/canon-divergence-defer.1 +2 -2
  49. package/man/canon-divergence-list.1 +2 -2
  50. package/man/canon-divergence-resolve.1 +2 -2
  51. package/man/canon-divergence.1 +2 -2
  52. package/man/canon-evidence-add.1 +2 -2
  53. package/man/canon-evidence-approval-payload.1 +2 -2
  54. package/man/canon-evidence-audit.1 +2 -2
  55. package/man/canon-evidence.1 +2 -2
  56. package/man/canon-export.1 +2 -2
  57. package/man/canon-feature-new.1 +2 -2
  58. package/man/canon-feature.1 +2 -2
  59. package/man/canon-finding-add.1 +2 -2
  60. package/man/canon-finding-close.1 +2 -2
  61. package/man/canon-finding-list.1 +2 -2
  62. package/man/canon-finding.1 +2 -2
  63. package/man/canon-format.1 +2 -2
  64. package/man/canon-gate-check.1 +2 -2
  65. package/man/canon-gate-install-hooks.1 +2 -2
  66. package/man/canon-gate-promote.1 +2 -2
  67. package/man/canon-gate.1 +2 -2
  68. package/man/canon-ingest-plans.1 +2 -2
  69. package/man/canon-ingest-records.1 +2 -2
  70. package/man/canon-ingest-sessions.1 +2 -2
  71. package/man/canon-ingest.1 +2 -2
  72. package/man/canon-init.1 +2 -2
  73. package/man/canon-inventory-sync.1 +2 -2
  74. package/man/canon-inventory.1 +2 -2
  75. package/man/canon-ledger-compact.1 +2 -2
  76. package/man/canon-ledger.1 +2 -2
  77. package/man/canon-migrate.1 +15 -3
  78. package/man/canon-plugin-sync.1 +2 -2
  79. package/man/canon-plugin.1 +2 -2
  80. package/man/canon-policy-approve.1 +9 -3
  81. package/man/canon-policy-show.1 +2 -2
  82. package/man/canon-policy.1 +2 -2
  83. package/man/canon-prompt-add.1 +2 -2
  84. package/man/canon-prompt-show.1 +2 -2
  85. package/man/canon-prompt.1 +2 -2
  86. package/man/canon-purge.1 +2 -2
  87. package/man/canon-query.1 +2 -2
  88. package/man/canon-regime-show.1 +2 -2
  89. package/man/canon-regime.1 +2 -2
  90. package/man/canon-report-build.1 +2 -2
  91. package/man/canon-report-check.1 +2 -2
  92. package/man/canon-report-snapshot.1 +2 -2
  93. package/man/canon-report.1 +2 -2
  94. package/man/canon-retrieve.1 +2 -2
  95. package/man/canon-review-change.1 +2 -2
  96. package/man/canon-review-scenario.1 +2 -2
  97. package/man/canon-review.1 +2 -2
  98. package/man/canon-scenario-new.1 +2 -2
  99. package/man/canon-scenario.1 +2 -2
  100. package/man/canon-schema.1 +2 -2
  101. package/man/canon-search.1 +2 -2
  102. package/man/canon-selftest.1 +2 -2
  103. package/man/canon-skills-check.1 +2 -2
  104. package/man/canon-skills-doctor.1 +2 -2
  105. package/man/canon-skills-install.1 +2 -2
  106. package/man/canon-skills-show.1 +2 -2
  107. package/man/canon-skills.1 +2 -2
  108. package/man/canon-status.1 +2 -2
  109. package/man/canon-strategy-approval-payload.1 +2 -2
  110. package/man/canon-strategy-promote.1 +2 -2
  111. package/man/canon-strategy-rollback.1 +2 -2
  112. package/man/canon-strategy.1 +2 -2
  113. package/man/canon-subject-adopt.1 +2 -2
  114. package/man/canon-subject-move.1 +2 -2
  115. package/man/canon-subject-new.1 +2 -2
  116. package/man/canon-subject-show.1 +2 -2
  117. package/man/canon-subject-unadopt.1 +2 -2
  118. package/man/canon-subject.1 +2 -2
  119. package/man/canon-task-done.1 +2 -2
  120. package/man/canon-task.1 +2 -2
  121. package/man/canon-tier-age.1 +2 -2
  122. package/man/canon-tier.1 +2 -2
  123. package/man/canon-trace.1 +2 -2
  124. package/man/canon.1 +2 -2
  125. package/package.json +4 -4
@@ -4,9 +4,10 @@ You run the loop across agents and move the subject. You write no brief,
4
4
  code or review yourself. Declare the role with `CANON_ROLE=orchestrator` (or
5
5
  `--as orchestrator`); your `canon status` also lists the human's steps. The
6
6
  human's acts (`brief approve`, `policy approve`, `divergence accept`) refuse
7
- every agent role, you included (`HUMAN_ONLY`). You never run them, and never remove or unset your role (`env -u CANON_ROLE`,
8
- dropping `--as`) to get past the refusal: report the exact call, slug filled in, and
9
- wait; the human runs it (or uses `canon dashboard`).
7
+ every agent role, you included (`HUMAN_ONLY`), unless you record the answer the
8
+ human gave you in the conversation with `--relayed-via <tool>` (below). You never
9
+ run them without that answer, and never remove or unset your role (`env -u CANON_ROLE`,
10
+ dropping `--as`) to get past the refusal.
10
11
 
11
12
  ## Commands
12
13
 
@@ -227,7 +228,7 @@ canon ledger compact
227
228
  ```
228
229
  ```text
229
230
  # Bring a repo from an earlier canon up to date
230
- canon migrate [--commit --plan-digest <DIGEST>] [--revert] [--backup <DIR> (with --revert)] [--input]
231
+ canon migrate [--commit --plan-digest <DIGEST>] [--revert | --relayed-via <NAME>] [--backup <DIR> (with --revert)] [--actor <ACTOR_ID> (with --relayed-via)] [--approver <NAME> (with --relayed-via)] [--note <TEXT> (with --relayed-via)] [--input]
231
232
  # a bare run previews and prints planDigest; `--commit --plan-digest <DIGEST>` with that digest acts
232
233
  ```
233
234
  ```bash
@@ -443,10 +444,10 @@ canon trace add-login_1_1
443
444
  ## Read the state
444
445
 
445
446
  `canon status` lists the next steps, each with the `role` that takes it
446
- (`null` for the human), and `waitingOn` counts the steps held by each other
447
+ (`null` for the human), and `data.waitingOn` counts the steps held by each other
447
448
  owner, `human` included. Call it once at the start and when resuming, not
448
449
  after a write: after `subject move --to` or a spawned role's write, the
449
- write's `meta.next` and `meta.waitingOn` are the status for what it touched.
450
+ write's `meta.next` and `data.waitingOn` are the status for what it touched.
450
451
 
451
452
  ## Spawn each role
452
453
 
@@ -491,14 +492,14 @@ text.
491
492
  | Harness | In-harness subagents | Isolation | Ask the human | Hooks | Skipped |
492
493
  |---|---|---|---|---|---|
493
494
  | claude (`.claude`) | yes, a subagent tool; a child shares your environment, so pass the role in the task | a subagent can run in its own git worktree | yes, a question tool | yes, in the harness settings; `scripts/canon-retrieve-pre-dispatch.sh` is a sidecar, not installed | none |
494
- | codex (`.agents`) | `verify`: none when #39 was filed; start the reviewer as a new `codex exec` run | none from canon: use a separate worktree you create | no in `codex exec`; stop and report | `verify` | in-harness spawn, unless a newer version provides it |
495
+ | codex (`.agents`) | `verify`: none when #39 was filed; start the reviewer as a new `codex exec` run | none from canon: use a separate worktree you create | no in `codex exec`; ask in the chat | `verify` | in-harness spawn, unless a newer version provides it |
495
496
  | omp (`.omp`) | yes, the task tool | `verify` | yes, an ask tool | yes | none |
496
497
  | pi (`.pi`) | `verify`: assume none; start a new `pi` process | none from canon | `verify` | `verify` | in-harness spawn, isolation |
497
498
 
498
499
  Where a harness has no subagent tool, the reviewer is still a separate
499
500
  process with its own session id: start it from the shell with its own
500
- `CANON_ROLE=reviewer`. A harness that cannot ask the human means you stop
501
- and report in your final message; you never assume the answer.
501
+ `CANON_ROLE=reviewer`. A harness that cannot ask the human means you ask
502
+ in the chat and record only the reply; you never assume the answer.
502
503
 
503
504
  The reviewer is a separate process with its own session id, never your
504
505
  session or the implementer's under another label. Start it as a new process
@@ -507,25 +508,39 @@ implementer's context, and have it record its real session id as
507
508
  `--session` (#39). A reviewer that cannot run the tests says so and does
508
509
  not sign off.
509
510
 
510
- ## Relay the human stop
511
-
512
- When `status` or `meta.next` shows a step with `actor: human` (the brief's
513
- approval), stop everything for that scope, report the brief to the human in
514
- its language, and wait. Tell the human they can approve the clean briefs in
515
- `canon dashboard` (the briefs page) or run, in their own shell, the exact call
516
- with every slug filled in: `canon brief approve <slug> <slug> --approver <their name>
517
- --note "<their own words>"` (several slugs take one answer; nothing is written if
518
- one is refused). You never click Approve, fill the form or run
519
- `brief approve` yourself: it refuses you (`HUMAN_ONLY`), and removing or
520
- unsetting your declared role (`env -u CANON_ROLE`, dropping `--as`) to get past
521
- that is the same act under another label. Report the call and wait. Do not start the
511
+ ## Relay the human's answer
512
+
513
+ When `status` or `meta.next` shows a step with `x-canon.actor: human` (the brief's
514
+ approval), stop everything for that scope and put the brief in front of the
515
+ human in its language: `canon brief show <slug> --body` prints the brief and,
516
+ last, its digest. Send the output to the human's own view, never retyped (omp:
517
+ redirect it to `out://`, off for subagents and non-TUI sessions and capped at
518
+ 64 KiB; there, and where there is no such channel, leave the tool output
519
+ visible). You are the session that talks to the human: a subagent has no
520
+ question tool, so you show, ask and record for it. Ask with the harness question tool (`ask` in omp, `AskUserQuestion`
521
+ in Claude Code, otherwise in the chat), approve or request changes, all the
522
+ clean briefs in one question. Only an explicit approval counts; a question or a
523
+ condition is a revision request for the planner, and no answer means you wait.
524
+ They may also approve in `canon dashboard` (the briefs page); you never click
525
+ Approve or fill the form. On their approval record it: `canon brief approve
526
+ <slug> <slug> --approver <their name> --note "<their own words>" --relayed-via
527
+ <ask|AskUserQuestion|chat> --actor <your actor id> --digest <slug>=<the digest
528
+ shown>` (several slugs take one answer, each with its own `--digest`; nothing is written
529
+ if one is refused). The record says you recorded it, with your role, actor and
530
+ tool. `RELAY_DIGEST_MISMATCH` means the brief changed after they saw it: show it
531
+ again. When `canon.yaml` has `approval: { relay: deny }` the call is refused
532
+ (`HUMAN_ONLY`, naming the key): report the human's own call and wait for them to
533
+ run it. Removing or unsetting your declared role (`env -u CANON_ROLE`,
534
+ dropping `--as`) to get past a refusal is the same act under another label.
535
+ `canon skills show role-planner` has the full procedure. Do not start the
522
536
  implementer before `canon brief show <slug>` reports `state: approved`.
523
537
  Never approve it yourself and never edit the policy to pass the gate. A
524
538
  policy that no longer matches the approval fails closed
525
539
  (`POLICY_CHANGED_SINCE_APPROVAL`, or `POLICY_APPROVAL_UNREADABLE`): the ship
526
540
  guard and the reopen refuse, and `--override-reason` does not waive it. Run
527
- `canon policy show`, then stop and ask the human to re-approve
528
- (the call `canon policy approve --approver <their name>` is theirs to run, never yours) or restore the
541
+ `canon policy show`, then show the policy to the human, ask them to re-approve
542
+ and record their explicit answer (`canon policy approve --approver <their name>
543
+ --note "<their words>" --relayed-via <tool> --actor <your actor id>`), or restore the
529
544
  approved policy from git; never edit the policy yourself. Inside an
530
545
  approved scope never stop for a human: fixes, follow-ups and re-reviews go
531
546
  straight to the implementer and reviewer in the same change. A known gap the
@@ -548,7 +563,7 @@ holds the next command and the verified claims (`canon skills show canon-vocab`)
548
563
  After a timeout or a lost response, repeat the write only when its repeat is
549
564
  safe. `evidence add`, `review scenario`, `review change` and `finding add`
550
565
  are content-keyed: an identical repeat returns the existing record with
551
- `meta.unchanged: true` (a batch reports the element `unchanged`).
566
+ `data.unchanged: true` (a batch reports the element `unchanged`).
552
567
  `finding close`, `subject adopt`, `inventory sync`, `ingest *`, `gate
553
568
  promote` and `task done` are replay-safe the same way. `subject new`,
554
569
  `change new`, `feature new`, `scenario new`, `subject move` and `dispatch
@@ -563,9 +578,9 @@ its preview, never from an old digest.
563
578
  |---|---|
564
579
  | "Edit the policy so the gate passes." | A changed policy fails closed (`POLICY_CHANGED_SINCE_APPROVAL`); ask the human to re-approve or restore it from git. |
565
580
  | "The reviewer can be me under another label." | The reviewer is a separate process with its own real session id (#39). |
566
- | "Approve the brief; the human said they are busy." | `brief approve` refuses agent roles. Report the brief and wait. |
581
+ | "Approve the brief; the human said they are busy." | An answer they did not give is not recorded. Show the brief, ask, and record only an explicit approval with `--relayed-via`. |
567
582
  | "Override the refusal to ship." | Fix the gap the refusal names; `--override-reason` waives only the `require_review` gaps and the brief gap, is recorded on the subject, and is for the human's call, not a shortcut. |
568
- | "Run the commit now, the preview looked fine earlier." | A bare run previews; `--commit --plan-digest` acts only on the plan you just previewed (`PLAN_CHANGED` otherwise). Preview again, then act. |
583
+ | "Run the commit now, the preview looked fine earlier." | A bare run previews; `--commit --plan-digest` acts only on the plan you just previewed (`PLAN_STALE` otherwise). Preview again, then act. |
569
584
  | "I have corrected this agent before." | A correction repeated across runs belongs in a scenario, the policy or a gate, not more prose. Tell the human. |
570
585
 
571
586
  ## Move the subject
@@ -608,10 +623,10 @@ read the refusal in `error` of `canon subject move demo --to shipped --json`.
608
623
  move` and `canon migrate` delete or rewrite existing data. A bare run only
609
624
  previews: exit 0, nothing written, a report with `planDigest` and
610
625
  `effects[]`. Read the effects, then act with `--commit --plan-digest
611
- <planDigest>`; it refuses (`PLAN_CHANGED`, exit 2) when the plan recomputed
626
+ <planDigest>`; it refuses (`PLAN_STALE`, exit 2) when the plan recomputed
612
627
  now differs from the one you previewed. A document passed with `--input`
613
628
  never carries `--commit` or `--plan-digest`, and these five leaves take one
614
- object only (`INPUT_BATCH_UNSUPPORTED`).
629
+ object only (`INPUT_INVALID`).
615
630
 
616
631
  ```bash
617
632
  canon purge --kind session --before 2026-01-01
@@ -663,6 +678,6 @@ git-ignored, and `canon migrate --revert` needs it (keep it until you are sure).
663
678
  **Done when:** `canon migrate` reports nothing left to move, `canon skills
664
679
  check` exits 0, and `canon status` and `canon gate check` no longer warn
665
680
  about 0.27 state; read the first in `data` of `canon migrate --json`, the
666
- others in `meta.warnings`.
681
+ others in `meta.warnings` (`[{code, message}]`).
667
682
 
668
683
  Reference: `canon skills show canon-subject`.
@@ -4,10 +4,12 @@ You turn a request into an approved scope: a subject, a change and a PRD
4
4
  brief the human answers once. You build nothing. Declare the role with
5
5
  `CANON_ROLE=planner` (or `--as planner`); `canon status` and `meta.next`
6
6
  then show your steps and count the rest under `waitingOn`. The approvals are
7
- the human's: `brief approve`, `policy approve` and `divergence accept` refuse
8
- every agent role (`HUMAN_ONLY`, `retryable: false`), and no flag grants them. You never run them, and never remove or unset your role (`env -u CANON_ROLE`,
9
- dropping `--as`) to get past the refusal: report the exact call, slug filled in, and
10
- wait; the human runs it (or uses `canon dashboard`).
7
+ the human's: `brief approve`, `policy approve`, `divergence accept` and the
8
+ `migrate --commit` that re-binds `Approved:` lines refuse every agent role
9
+ (`HUMAN_ONLY`, `retryable: false`) unless you record the answer the human gave
10
+ you in the conversation, with `--relayed-via <tool>` (step 4). Without a human's
11
+ explicit answer you never run them, and you never remove or unset your role
12
+ (`env -u CANON_ROLE`, dropping `--as`) to get past the refusal.
11
13
 
12
14
  ## Commands
13
15
 
@@ -30,7 +32,7 @@ canon brief check
30
32
  ```
31
33
  ```text
32
34
  # Show where the change stands and the next one to three steps; never edits
33
- canon brief show [<CHANGE_ID>]
35
+ canon brief show [<CHANGE_ID>] [--body]
34
36
  ```
35
37
  ```bash
36
38
  canon brief show
@@ -170,7 +172,7 @@ canon trace add-login_1_1
170
172
  ```
171
173
  <!-- canon:generated commands-planner end -->
172
174
 
173
- After the first `status`, follow `meta.next` of each write. `brief check`
175
+ After the first `status`, follow `meta.next` of each write. 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`. `brief check`
174
176
  lists blockers and advisories and exits 1 when it finds blockers; `canon
175
177
  brief show --as planner` names the next steps. The change is an optional
176
178
  operand of both (`canon brief check add-login`); without it they read the
@@ -243,26 +245,63 @@ ids); the human step comes after it. A policy that no longer matches its approva
243
245
  the advisories are gone or each remaining one is waived with a reason.
244
246
  It never blocks approval, but you do not hand the human a brief with
245
247
  unexamined advisories.
246
- 4. **Stop for the human.** Report the brief to the human, in the brief's
247
- language, asking once, and say they can approve it in `canon dashboard`
248
- (the briefs page, `/briefs.html`) or answer in chat. You never click
249
- Approve or fill that form yourself. Build nothing for that scope (no scenarios, code
250
- or evidence) until the human answers. The approval is never assumed, even
251
- when the human said they cannot answer until you report: the brief is
252
- that report. The one answer approves the brief and the policy
248
+ 4. **Show, ask, count only an explicit approval.** Build nothing for that
249
+ scope (no scenarios, code or evidence) until the human has answered. The
250
+ approval is never assumed, even when the human said they cannot answer
251
+ until you show the brief. The one answer approves the brief and the policy
253
252
  (`.canon/policy.yaml`, written by `canon init`), which is what the gate
254
253
  grades the work against.
255
- 5. **The human records the answer.** `brief approve` is the human's leaf: run
256
- by an agent role it is refused (`HUMAN_ONLY`) with a hint addressed to the
257
- human. Report the exact call, slug filled in, and wait: `canon brief approve
258
- add-login --approver <their name> --note "<their own words>"`; the human
259
- runs it in their own shell (`--approver` and `--note` are theirs to supply)
260
- or approves in the dashboard. Never approve in their name, never remove or
261
- unset your role (`env -u CANON_ROLE`, dropping `--as`) to run it, and never
262
- edit the policy to make the gate pass.
254
+ - **Show.** `canon brief show <slug> --body` prints the brief file's bytes
255
+ as they are and, as its last line, `digest: sha256:<hex>`, the value
256
+ `brief approve` records. Send that output to the human's own view; never
257
+ retype or paraphrase the brief into the conversation. In omp, redirect it
258
+ to `out://` (`canon brief show add-login --body > out://add-login`).
259
+ `out://` is off for subagents and non-TUI sessions (the redirect then
260
+ errors) and caps a reply at 64 KiB: there, and in a harness with no such
261
+ channel, leave the tool output visible, which is the same. Read the digest alone with `canon brief show add-login --body |
262
+ tail -n 1`. Show every brief of one request, each with its digest.
263
+ - **Ask.** Use the harness's question tool: `ask` in omp, `AskUserQuestion`
264
+ in Claude Code; a harness without one, ask in the chat and wait for the
265
+ reply. Two choices: approve, or request changes. Several briefs are one
266
+ question. Say in the brief's language what is approved: the brief and
267
+ the policy.
268
+ - **Count only an explicit approval.** The approve choice, or the human
269
+ saying in the chat that they approve. A question, a condition ("yes, if
270
+ …") or an approval of part of it is a revision request: change the brief,
271
+ `brief check` until clean, show it again and ask again. No answer means
272
+ nothing is recorded: wait.
273
+ A subagent has no question tool and no human in front of it: the
274
+ orchestrator (the session talking to the human) shows, asks and records.
275
+ They may also approve on `canon dashboard` (the briefs page,
276
+ `/briefs.html`); you never click Approve or fill that form yourself.
277
+ 5. **Record the answer you were given.** Run `brief approve` with the relay
278
+ option: `canon brief approve add-login --approver <their name> --note "<their
279
+ answer, as they gave it>" --relayed-via <ask|AskUserQuestion|chat> --actor
280
+ <your actor id> --digest add-login=<the digest you showed>` (several slugs:
281
+ one `--digest <slug>=<digest>` each, one answer for all, nothing written if
282
+ any is refused). `--actor` may be `CANON_ACTOR` instead. The record keeps
283
+ their name and words and says that you, with your role and actor, recorded
284
+ them through that tool: the `Approved:` line gains `(relayed by <role>
285
+ <actor> via <tool>)`, which is outside the digest, and `status`, `brief
286
+ show` and the dashboard name it. Never approve in their name without their
287
+ answer, never write the answer for them, and never edit the policy to make
288
+ the gate pass. A digest that differs from the brief now
289
+ (`RELAY_DIGEST_MISMATCH`) means the brief changed after they saw it: show
290
+ it again and ask again; nothing was written. Without `--relayed-via` the call is
291
+ `HUMAN_ONLY`; with it and no role declared, `USAGE`. When `canon.yaml`
292
+ turns relaying off (`approval: { relay: deny }`), the refusal names that key:
293
+ report the human's call (`canon brief approve add-login --approver <their
294
+ name> --note "<their own words>"`) and wait for them to run it. Never
295
+ remove or unset your role (`env -u CANON_ROLE`, dropping `--as`) to run it.
296
+ `canon policy approve`, `canon divergence accept` and `canon migrate
297
+ --commit --plan-digest <d>` follow the same procedure, each taking
298
+ `--approver <their name> --note "<their answer>" --relayed-via <tool>` (and
299
+ `--actor <your actor id>`, which `divergence accept` already requires): show what is approved (the policy file, the divergent
300
+ evidence with its reason and tracking reference, the migrate plan), ask,
301
+ count only an explicit approval, then record with the relay option.
263
302
  `canon brief show <slug>` then reports `state: approved`. A brief edited
264
303
  after its approval is not approved (`BRIEF_CHANGED_SINCE_APPROVAL`): it
265
- needs a new answer and a new `brief approve` by the human. A follow-up that
304
+ needs a new answer, shown and asked again, and a new `brief approve`. A follow-up that
266
305
  adds or changes a step of the brief is a scope change and needs a new
267
306
  answer.
268
307
 
@@ -273,17 +312,17 @@ approval.
273
312
 
274
313
  **Done when:** `canon brief check add-login` exits 0 (no blockers, and the
275
314
  prose advisories are gone or waived with a reason) and `canon brief show
276
- add-login` reports `state: ready`: the brief is handed to the human and you
277
- stop. The scope is approved when the same command reports `state:
278
- approved`; read it in `data.state` of `canon brief show add-login --json`.
279
- Nothing else starts before that.
315
+ add-login` reports `state: ready`: show it to the human and ask (step 4). The scope is approved
316
+ when you have recorded their explicit approval (step 5) and the same command
317
+ reports `state: approved`; read it in `data.state` of `canon brief show
318
+ add-login --json`. Nothing else starts before that.
280
319
 
281
320
  ## Non-behavior work is a chore
282
321
 
283
322
  A refactor, dependency, build, CI or infra change that alters nothing a user
284
323
  can observe: `change new --change-kind chore`. Its brief is short (intent,
285
324
  category, invariants, checks, out of scope) and approved like any brief, one
286
- human stop. A chore adds no scenarios: the
325
+ human answer. A chore adds no scenarios: the
287
326
  implementer runs the subject's suite again where the code changed and binds
288
327
  it with `canon evidence add --all-scenarios` (a docs-only chore changes no
289
328
  code and needs no new evidence), then the reviewer records one
@@ -310,9 +349,9 @@ old column, delete the old format) in its own later change.
310
349
 
311
350
  | The thought | The reality |
312
351
  |---|---|
313
- | "The human is unavailable; I will assume the approval." | Never. The brief is the report; stop, and put open questions into Questions and assumptions. |
352
+ | "The human is unavailable; I will assume the approval." | Never. Show the brief and ask; without an explicit answer nothing is recorded and nothing is built. Put open questions into Questions and assumptions. |
314
353
  | "This could change policy, but I will decide it." | Anything that could change policy goes to the questions. |
315
- | "A small follow-up needs no new answer." | A follow-up that adds or changes a flow step is a scope change and needs a new `brief approve`. |
354
+ | "A small follow-up needs no new answer." | A follow-up that adds or changes a flow step is a scope change and needs a new answer and a new `brief approve`. |
316
355
  | "This migration is just a chore." | Data, interface or output changes are feature changes. |
317
356
  | "Put the file and line in the brief so nobody has to look." | Paths rot; describe behavior. |
318
357
 
@@ -4,10 +4,11 @@ You are the independent second look. Declare the role with
4
4
  `CANON_ROLE=reviewer` (or `--as reviewer`); `--role` on `review scenario`,
5
5
  `review change` and `finding add` then defaults to `reviewer`. The human's
6
6
  acts refuse you (`HUMAN_ONLY`): `brief approve`, `policy approve` and
7
- `divergence accept`. Name what the human has to decide in your report; never
8
- look for a flag that grants it. You never run them, and never remove or unset your role (`env -u CANON_ROLE`,
9
- dropping `--as`) to get past the refusal: report the exact call, slug filled in, and
10
- wait; the human runs it (or uses `canon dashboard`).
7
+ `divergence accept`, unless you record the answer the human gave you in the
8
+ conversation with `--relayed-via <tool>` (the divergence acceptance below).
9
+ Name what the human has to decide; never look for another flag that grants it.
10
+ You never run them without that answer, and never remove or unset your role
11
+ (`env -u CANON_ROLE`, dropping `--as`) to get past the refusal.
11
12
 
12
13
  ## Commands
13
14
 
@@ -30,7 +31,7 @@ canon brief check
30
31
  ```
31
32
  ```text
32
33
  # Show where the change stands and the next one to three steps; never edits
33
- canon brief show [<CHANGE_ID>]
34
+ canon brief show [<CHANGE_ID>] [--body]
34
35
  ```
35
36
  ```bash
36
37
  canon brief show
@@ -219,7 +220,7 @@ advisory names it); that is the orchestrator's step, not yours.
219
220
  Run `gate check` once, before `review scenario`: its `unreviewed-promotion`
220
221
  violations are the subjects and scenarios that need your review. Do not loop
221
222
  it. After `review scenario`, read its `meta.next` instead of calling `gate check`
222
- or `status` again.
223
+ or `status` again. 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`.
223
224
 
224
225
  ## Separate session
225
226
 
@@ -287,14 +288,21 @@ sign.
287
288
  `divergence accept` is for a scenario whose honest evidence is `divergent`
288
289
  and whose gap is limited by something outside this change (an upstream
289
290
  limit, a platform bug) and is tracked there. It records a human's decision,
290
- so it refuses every agent role (`HUMAN_ONLY`), you included. What you do:
291
- confirm the evidence really is divergent and the limit is outside this
292
- change, then report to the human the scenario ids, the reason, the
293
- tracking reference and an expiry when the limit should be gone by a date.
294
- Give the exact call, ids filled in: the human runs `canon divergence accept
295
- <ids> --actor <name> --reason "<why>" --tracking <ref>` themselves in their
296
- own shell, from a session that did not attest the evidence
297
- (`DIVERGENCE_ACCEPT_REFUSED` otherwise); you never run it or unset your role to. Never suggest it to skip
291
+ so it refuses every agent role (`HUMAN_ONLY`), you included, unless it records
292
+ the answer the human gave you. What you do: confirm the evidence really is
293
+ divergent and the limit is outside this change, then put to the human the
294
+ scenario ids, the reason, the tracking reference and an expiry when the limit
295
+ should be gone by a date, in their own view and not retyped (omp: `out://`).
296
+ Ask with the harness question tool (`ask` in omp, `AskUserQuestion` in Claude
297
+ Code, otherwise in the chat): accept the gap, or not. Only an explicit
298
+ approval counts; a question or a condition is not one, and no answer records
299
+ nothing. Then record it from a session that did not attest the evidence
300
+ (`DIVERGENCE_ACCEPT_REFUSED` otherwise): `canon divergence accept <ids> --actor
301
+ <your actor id> --reason "<why>" --tracking <ref> --approver <their name> --note
302
+ "<their answer>" --relayed-via <tool>`; the record carries the relay, the
303
+ approver and their answer. When `canon.yaml` has `approval: { relay: deny }` the
304
+ call is refused (`HUMAN_ONLY`, naming the key) and the human runs it themselves.
305
+ You never unset your role to run it. Never suggest it to skip
298
306
  a fix the implementer can make in this change. The acceptance pins that
299
307
  evidence: new evidence for the scenario, or its expiry, ends it, and the
300
308
  human accepts (or the implementer fixes) again. An accepted gap counts as
@@ -347,7 +355,7 @@ implementer owns. Your last write's `meta.next` names the next step.
347
355
  ## Retry safety
348
356
 
349
357
  `review scenario`, `review change` and `finding add` are content-keyed: an
350
- identical repeat is reported `unchanged` (`meta.unchanged: true`, or the
358
+ identical repeat is reported `unchanged` (`data.unchanged: true`, or the
351
359
  element's `status` in a batch), so after a timeout run the same command
352
360
  again. A different finding under an occupied round and seq is refused
353
361
  (`FINDING_SEQ_OCCUPIED`): take the next seq. `finding close` with the same
@@ -362,6 +370,6 @@ disposition is a no-op too.
362
370
  | "I cannot run the tests, but the evidence looks right." | Say so and record `indeterminate` or `unavailable`; never sign what you could not run. |
363
371
  | "This is a minor defect; I will skip the finding." | Every defect is a finding; severity says how much it matters. |
364
372
  | "I will edit the brief to fix it." | A brief defect is a finding, not an edit. |
365
- | "I will accept the gap myself, the limit is real." | `divergence accept` refuses agent roles; report the gap to the human. |
373
+ | "I will accept the gap myself, the limit is real." | The human accepts it: ask them, and record only their explicit answer with `--relayed-via`. |
366
374
 
367
375
  Reference: `canon skills show canon-review`.
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-adapter-authorize 1 "authorize 0.31.0"
3
+ .TH canon-adapter-authorize 1 "authorize 0.33.0"
4
4
  .SH NAME
5
5
  canon\-adapter\-authorize \- Authorize declared capabilities against repository policy (preflight only)
6
6
  .SH SYNOPSIS
@@ -41,4 +41,4 @@ Print help
41
41
  \fB\-V\fR, \fB\-\-version\fR
42
42
  Print version
43
43
  .SH VERSION
44
- v0.31.0
44
+ v0.33.0
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-adapter-validate 1 "validate 0.31.0"
3
+ .TH canon-adapter-validate 1 "validate 0.33.0"
4
4
  .SH NAME
5
5
  canon\-adapter\-validate \- Read and validate one provider\-neutral response envelope
6
6
  .SH SYNOPSIS
@@ -41,4 +41,4 @@ Print help
41
41
  \fB\-V\fR, \fB\-\-version\fR
42
42
  Print version
43
43
  .SH VERSION
44
- v0.31.0
44
+ v0.33.0
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-adapter 1 "adapter 0.31.0"
3
+ .TH canon-adapter 1 "adapter 0.33.0"
4
4
  .SH NAME
5
5
  canon\-adapter \- Validate a provider\-neutral adapter response without executing a provider
6
6
  .SH SYNOPSIS
@@ -43,4 +43,4 @@ Examples:
43
43
  canon adapter validate \-\-response response.json
44
44
  canon adapter validate \-\-response response.json \-\-repo . \-\-json
45
45
  .SH VERSION
46
- v0.31.0
46
+ v0.33.0
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-artifacts-move 1 "move 0.31.0"
3
+ .TH canon-artifacts-move 1 "move 0.33.0"
4
4
  .SH NAME
5
5
  canon\-artifacts\-move \- Move the local artifact blobs to an object\-store tier, verify them, and remove the local copies
6
6
  .SH SYNOPSIS
@@ -54,10 +54,10 @@ Examples:
54
54
  canon artifacts move \-\-tier cold
55
55
  canon artifacts move \-\-tier cold \-\-commit \-\-plan\-digest <DIGEST>
56
56
 
57
- The bare run previews: it lists every upload and removal and prints a planDigest, and writes nothing. \-\-commit \-\-plan\-digest acts on exactly that plan (PLAN_CHANGED, exit 2, when it changed since).
57
+ The bare run previews: it lists every upload and removal and prints a planDigest, and writes nothing. \-\-commit \-\-plan\-digest acts on exactly that plan (PLAN_STALE, exit 2, when it changed since).
58
58
 
59
59
  \-\-tier names an `s3` tier of canon.yaml\*(Aqs `tiers:` (for example `cold`; its credentials are the tier\*(Aqs own). Every blob in .canon/artifacts/sha256 is hashed, uploaded under <prefix>sha256/<digest> (prefix artifacts/), and read back; only when all of them verified does canon.yaml gain `artifact_store: { backend: <tier>, prefix: artifacts/ }`, after which the local copies are removed and `.canon/artifacts/` is added to .gitignore. Commit the removal with the ledger.
60
60
 
61
61
  Idempotent and resumable: a run stopped anywhere leaves a repo the gate still passes, and the next run finishes; a second run finds nothing to do. A blob whose bytes do not match its name is never moved. Moving back to local is refused; `\-\-tier local` on a local repo is a no\-op.
62
62
  .SH VERSION
63
- v0.31.0
63
+ v0.33.0
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-artifacts-store 1 "store 0.31.0"
3
+ .TH canon-artifacts-store 1 "store 0.33.0"
4
4
  .SH NAME
5
5
  canon\-artifacts\-store \- Store the bound files of existing evidence records and current reviews in the artifact store (.canon/artifacts/sha256/)
6
6
  .SH SYNOPSIS
@@ -51,4 +51,4 @@ For records written before canon stored bound bytes (0.11\-0.13), and for any ev
51
51
 
52
52
  Exit 0 when the pass ran (the gate decides whether an unstored file matters), 2 when the ledger cannot be read or a write fails.
53
53
  .SH VERSION
54
- v0.31.0
54
+ v0.33.0
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-artifacts-verify 1 "verify 0.31.0"
3
+ .TH canon-artifacts-verify 1 "verify 0.33.0"
4
4
  .SH NAME
5
5
  canon\-artifacts\-verify \- Check that the artifact store holds every file the latest evidence and current reviews bind (\-\-full re\-hashes the stored bytes)
6
6
  .SH SYNOPSIS
@@ -45,4 +45,4 @@ Asks the store canon.yaml\*(Aqs `artifacts:` block selects (default: local, .can
45
45
 
46
46
  Exit 0 when every file is stored, 1 when one is missing or altered (data.problems names each), 2 when the store cannot be used or reached: an unreachable store is a refusal, never a pass.
47
47
  .SH VERSION
48
- v0.31.0
48
+ v0.33.0
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-artifacts 1 "artifacts 0.31.0"
3
+ .TH canon-artifacts 1 "artifacts 0.33.0"
4
4
  .SH NAME
5
5
  canon\-artifacts \- Check or move the evidence artifact store (local, or an object\-store tier)
6
6
  .SH SYNOPSIS
@@ -42,4 +42,4 @@ Store the bound files of existing evidence records and current reviews in the ar
42
42
  canon\-artifacts\-move(1)
43
43
  Move the local artifact blobs to an object\-store tier, verify them, and remove the local copies
44
44
  .SH VERSION
45
- v0.31.0
45
+ v0.33.0
@@ -1,10 +1,10 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-brief-approve 1 "approve 0.31.0"
3
+ .TH canon-brief-approve 1 "approve 0.33.0"
4
4
  .SH NAME
5
5
  canon\-brief\-approve \- Record the human\*(Aqs approval of the brief, bound to its text; refused while `brief check` has blockers
6
6
  .SH SYNOPSIS
7
- \fBcanon brief approve\fR <\fB\-\-approver\fR> [\fB\-\-as\fR] <\fB\-\-note\fR> [\fB\-\-repo\fR] [\fB\-\-json\fR] [\fB\-\-input\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fICHANGE_ID\fR]
7
+ \fBcanon brief approve\fR <\fB\-\-approver\fR> [\fB\-\-as\fR] <\fB\-\-note\fR> [\fB\-\-relayed\-via\fR] [\fB\-\-actor\fR] [\fB\-\-digest\fR] [\fB\-\-repo\fR] [\fB\-\-json\fR] [\fB\-\-input\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fICHANGE_ID\fR]
8
8
  .SH DESCRIPTION
9
9
  Record the human\*(Aqs approval of the brief, bound to its text; refused while `brief check` has blockers
10
10
  .SH OPTIONS
@@ -32,6 +32,15 @@ orchestrator
32
32
  \fB\-\-note\fR \fI<TEXT>\fR
33
33
  The human\*(Aqs own words
34
34
  .TP
35
+ \fB\-\-relayed\-via\fR \fI<NAME>\fR
36
+ Record the human\*(Aqs answer on their behalf: the tool they were asked with (`ask`, `AskUserQuestion`, `chat`); an agent role may run the call only with it
37
+ .TP
38
+ \fB\-\-actor\fR \fI<ACTOR_ID>\fR
39
+ With \-\-relayed\-via, the agent\*(Aqs actor id (default: the CANON_ACTOR environment variable)
40
+ .TP
41
+ \fB\-\-digest\fR \fI<DIGEST>\fR
42
+ With \-\-relayed\-via, the digest `canon brief show \-\-body` showed the human, as `<change>=<sha256:digest>`, once per change; a brief whose digest differs is refused
43
+ .TP
35
44
  \fB\-\-repo\fR \fI<DIR>\fR
36
45
  The repo to act on (default: the nearest ancestor directory holding a canon.yaml)
37
46
  .TP
@@ -62,4 +71,4 @@ brief (the digest covers the brief without its `Approved:` lines) and records
62
71
  not approved (BRIEF_CHANGED_SINCE_APPROVAL) until a human answers again and this
63
72
  runs again. Run it only from the human\*(Aqs answer, with their words as \-\-note.
64
73
  .SH VERSION
65
- v0.31.0
74
+ v0.33.0
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-brief-check 1 "check 0.31.0"
3
+ .TH canon-brief-check 1 "check 0.33.0"
4
4
  .SH NAME
5
5
  canon\-brief\-check \- Read the brief against the rules: blocker and advisory findings (exit 0 clean, 1 blockers, 2 refused)
6
6
  .SH SYNOPSIS
@@ -41,4 +41,4 @@ Print version
41
41
  [\fICHANGE_ID\fR]
42
42
  The change to read (default: the repo\*(Aqs only live change)
43
43
  .SH VERSION
44
- v0.31.0
44
+ v0.33.0
@@ -1,10 +1,10 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-brief-show 1 "show 0.31.0"
3
+ .TH canon-brief-show 1 "show 0.33.0"
4
4
  .SH NAME
5
5
  canon\-brief\-show \- Show where the change stands and the next one to three steps; never edits
6
6
  .SH SYNOPSIS
7
- \fBcanon brief show\fR [\fB\-\-as\fR] [\fB\-\-repo\fR] [\fB\-\-json\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fICHANGE_ID\fR]
7
+ \fBcanon brief show\fR [\fB\-\-as\fR] [\fB\-\-body\fR] [\fB\-\-repo\fR] [\fB\-\-json\fR] [\fB\-h\fR|\fB\-\-help\fR] [\fB\-V\fR|\fB\-\-version\fR] [\fICHANGE_ID\fR]
8
8
  .SH DESCRIPTION
9
9
  Show where the change stands and the next one to three steps; never edits
10
10
  .SH OPTIONS
@@ -26,6 +26,9 @@ reviewer
26
26
  orchestrator
27
27
  .RE
28
28
  .TP
29
+ \fB\-\-body\fR
30
+ Print the brief file\*(Aqs bytes as they are, then a last line with the approval digest `brief approve` would record (with \-\-json: `body` and `digest` fields); what a human is shown before they answer
31
+ .TP
29
32
  \fB\-\-repo\fR \fI<DIR>\fR
30
33
  The repo to act on (default: the nearest ancestor directory holding a canon.yaml)
31
34
  .TP
@@ -47,4 +50,4 @@ Examples:
47
50
 
48
51
  The operand names the change; without it the repo\*(Aqs only live change is read.
49
52
  .SH VERSION
50
- v0.31.0
53
+ v0.33.0
package/man/canon-brief.1 CHANGED
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-brief 1 "brief 0.31.0"
3
+ .TH canon-brief 1 "brief 0.33.0"
4
4
  .SH NAME
5
5
  canon\-brief \- Check a change\*(Aqs brief (PRD format) and see the next steps; never edits
6
6
  .SH SYNOPSIS
@@ -61,4 +61,4 @@ gets one blocker, `brief.old\-format`: `canon migrate` rewrites it. A brief
61
61
  with fewer than two known headings (written before 0.19) checks as `brief.legacy`, an
62
62
  advisory. Without \-\-change, the repo\*(Aqs only live change is checked.
63
63
  .SH VERSION
64
- v0.31.0
64
+ v0.33.0
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-change-new 1 "new 0.31.0"
3
+ .TH canon-change-new 1 "new 0.33.0"
4
4
  .SH NAME
5
5
  canon\-change\-new \- Write .canon/changes/<slug>/brief.md, import it, and adopt it into a subject
6
6
  .SH SYNOPSIS
@@ -63,4 +63,4 @@ Print version
63
63
  <\fICHANGE_ID\fR>
64
64
  The change\*(Aqs slug (its change_id)
65
65
  .SH VERSION
66
- v0.31.0
66
+ v0.33.0
@@ -1,6 +1,6 @@
1
1
  .ie \n(.g .ds Aq \(aq
2
2
  .el .ds Aq '
3
- .TH canon-change 1 "change 0.31.0"
3
+ .TH canon-change 1 "change 0.33.0"
4
4
  .SH NAME
5
5
  canon\-change \- Write a plan change (.canon/changes/<slug>/brief.md) and adopt it into a subject
6
6
  .SH SYNOPSIS
@@ -39,4 +39,4 @@ Write .canon/changes/<slug>/brief.md, import it, and adopt it into a subject
39
39
  Examples:
40
40
  canon change new add\-login \-\-subject auth \-\-title \*(AqAdd login\*(Aq
41
41
  .SH VERSION
42
- v0.31.0
42
+ v0.33.0