@journeykit/canon 0.11.0 → 0.12.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
CHANGED
|
@@ -36,6 +36,7 @@ installed explicitly with `--source canon/skills-dev`.
|
|
|
36
36
|
- **Capture replayable run inputs / version prompts:** read `reference/canon-context.md`, then use `canon context-pack create|show|verify` and `canon prompt register|show` with explicit repository-relative JSON manifests.
|
|
37
37
|
- **Validate or index specs:** read `reference/canon-fmt.md` and `reference/canon-inventory.md`.
|
|
38
38
|
- **Run evidence gates, flip tasks, install hooks:** read `reference/canon-gate.md`.
|
|
39
|
+
- **Finish a subject (claim work done):** read `reference/canon-review.md`. Order: test-run evidence (`canon evidence add`) → independent review of the adopted change (`canon finding add` per issue, fix, `canon finding close --disposition fixed --resolution-sha <sha>`) → `canon review add` per scenario by a reviewer other than the evidence actor → `canon subject status`. Commit each record with `canon gate promote`.
|
|
39
40
|
- **Ingest artifacts or sessions:** read `reference/canon-artifact-ingest.md`, `reference/canon-session-ingest.md`, or `reference/canon-plan-import.md`.
|
|
40
41
|
- **Configure storage, policy, plugins, or strategy learning:** read `reference/canon-storage.md`, `reference/canon-policy.md`, `reference/canon-plugins.md`, or `reference/canon-learn.md`.
|
|
41
42
|
- **Retrieve dispatch guidance:** read `reference/canon-retrieve.md` and load `scripts/canon-retrieve-pre-dispatch.sh` when wiring hooks.
|
|
@@ -5,7 +5,9 @@ vocabulary registry `canon format`/`canon gate` validate against — never
|
|
|
5
5
|
validation itself. It answers "what CAN I author in this repo, and how?":
|
|
6
6
|
record kinds + their envelope fields, enum domains, join-key grammars,
|
|
7
7
|
partition layout, policy-derived evidence requirements, the typed
|
|
8
|
-
authoring vocabulary,
|
|
8
|
+
authoring vocabulary, the review vocabulary (`review`: finding severities
|
|
9
|
+
and dispositions, Review fields, the active `require_review`; see
|
|
10
|
+
`canon-review`), and the CEL binding surface — folded into one
|
|
9
11
|
deterministic authoring surface.
|
|
10
12
|
|
|
11
13
|
## `canon context [--repo <dir>] [--json]`
|
|
@@ -15,20 +15,21 @@ release-scoped check (below) enforces it. A human-only `flagged` overlay
|
|
|
15
15
|
overrides the ladder — a flagged artifact is never green regardless of
|
|
16
16
|
evidence. (Author `policy.yaml`'s trust/staleness fields via `canon-policy`.)
|
|
17
17
|
|
|
18
|
-
## The
|
|
18
|
+
## The nine failure classes
|
|
19
19
|
|
|
20
20
|
Every violation carries one of these stable, grep-able strings:
|
|
21
21
|
|
|
22
22
|
| Class | Meaning |
|
|
23
23
|
|---|---|
|
|
24
24
|
| `uncovered-cell` | Either a policy-required evidence cell (role × artifact) with no matching record, or — with `spec_coverage` enabled — a spec scenario that is unimplemented or mismatched, or a feature surface missing a `require_cases` case. The detail string distinguishes them. Coverage means "a test exists", not "a test passed": even a `Divergent` verdict satisfies the role-cell form. |
|
|
25
|
-
| `unreviewed-promotion` | An artifact tagged `reviewed` has no matching ledger review record. |
|
|
25
|
+
| `unreviewed-promotion` | An artifact tagged `reviewed` has no matching ledger review record — or, with `spec_coverage.require_review` set, an in-scope scenario has no qualifying `Review` (none at all, or only reviews by its own evidence actor). See `canon-review`. |
|
|
26
26
|
| `trust-below-required` | Achieved trust level is below `policy.yaml`'s `trust_required` for its class — RELEASE-scoped only (`canon gate check --release`); never fires on an ordinary run. |
|
|
27
27
|
| `stale-evidence` | A passing record degraded to stale: its declared surface changed since its `evidence_sha`, or HEAD moved past `staleness.max_commits_behind`. Only degrades an already-green record. |
|
|
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 gate task <task_id>` was asked to flip a checkbox with no matching, non-`Divergent` evidence record. |
|
|
31
31
|
| `fabricated-evidence` | An evidence note contains a blocklisted marker (`"would pass"`, `"TBD"`, `"n/a"`) or a bare `verified` claim with no attached command result. |
|
|
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. Subject string `<change_id>#<round>.<seq>`. See `canon-review`. |
|
|
32
33
|
|
|
33
34
|
## `canon gate check [--repo <dir>] [--release]`
|
|
34
35
|
|
|
@@ -65,6 +66,7 @@ spec_coverage:
|
|
|
65
66
|
scope: [building, verifying] # optional; omit for the whole corpus
|
|
66
67
|
exclude_lanes: [process] # optional
|
|
67
68
|
require_cases: [failure] # optional; see Golden-path only below
|
|
69
|
+
require_review: {} # optional; see Independent review below
|
|
68
70
|
```
|
|
69
71
|
|
|
70
72
|
- **Unimplemented** — no `EvidenceRecord` carries the scenario's
|
|
@@ -89,13 +91,32 @@ spec_coverage:
|
|
|
89
91
|
no case, so an unclassified corpus is reported, not passed. Works with
|
|
90
92
|
`require_evidence: false` too. `canon subject status <id> shipped`
|
|
91
93
|
applies the same rule to the scenarios the subject owns.
|
|
94
|
+
- **Independent review** (`require_review`) — scenarios whose subject is
|
|
95
|
+
in `require_review.scope` (default `[verifying, shipped]`; `[]` = every
|
|
96
|
+
scenario; independent of `scope` above) need a `Review` record
|
|
97
|
+
(`canon review add`), by a reviewer and actor other than the
|
|
98
|
+
scenario's evidence actor when `distinct_actor` (default `true`);
|
|
99
|
+
gaps are `unreviewed-promotion`. With `block_on_findings` (default
|
|
100
|
+
`true`), an open `blocker` Finding on a change an in-scope subject
|
|
101
|
+
adopted is `open-blocker`. `exclude_lanes` also exempts scenarios
|
|
102
|
+
from review. Full contract: `canon-review`.
|
|
103
|
+
|
|
104
|
+
```yaml
|
|
105
|
+
spec_coverage:
|
|
106
|
+
require_evidence: true
|
|
107
|
+
require_review: # absent = nothing changes
|
|
108
|
+
scope: [verifying, shipped] # default
|
|
109
|
+
distinct_actor: true # default
|
|
110
|
+
block_on_findings: true # default
|
|
111
|
+
```
|
|
92
112
|
|
|
93
113
|
Two refusals rather than a silent pass, both surfacing as
|
|
94
114
|
`uncovered-cell` on the subject `spec_coverage`:
|
|
95
115
|
|
|
96
|
-
- A **malformed section** (unknown key, unknown `scope` status
|
|
97
|
-
|
|
98
|
-
|
|
116
|
+
- A **malformed section** (unknown key, unknown `scope` status, or a
|
|
117
|
+
malformed `require_cases`/`require_review` — unknown key, bad status,
|
|
118
|
+
`null`, non-mapping) refuses at check time. It is never treated as
|
|
119
|
+
absent — a typo must not be silently equivalent to not opting in.
|
|
99
120
|
- A **corpus kind routed off the gate's rung** (`scenario`,
|
|
100
121
|
`divergence`, or `subject` sent anywhere but `local`) refuses, because
|
|
101
122
|
the gate reads one tier and would otherwise pass by seeing nothing.
|
|
@@ -104,6 +125,22 @@ Malformed rows in those three kinds do NOT surface as
|
|
|
104
125
|
`malformed-evidence`; they are kept off the evidence violation set on
|
|
105
126
|
purpose, so enabling nothing changes no existing verdict.
|
|
106
127
|
|
|
128
|
+
### Review-waiver advisories
|
|
129
|
+
|
|
130
|
+
A subject moved into a review-scoped status with `canon subject status
|
|
131
|
+
--override-reason` (see `canon-subject`) keeps the `unreviewed-promotion`
|
|
132
|
+
and `open-blocker` gaps its waiver recorded visible without failing the
|
|
133
|
+
gate. Only those exact `(class, subject)` pairs are waived; a gap that
|
|
134
|
+
appears later is a violation. The waived ones print after the
|
|
135
|
+
violations:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
review waivers: 1 advisory(ies) — not failing the gate:
|
|
139
|
+
waived unreviewed-promotion world.demo.01 — no review record ... [waiver: subject `demo-subject` moved to verifying by `lead`: reviewer out until Monday]
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The waiver lasts only until the subject's next status write.
|
|
143
|
+
|
|
107
144
|
## Experimental: evidence binding (`experimental.evidence_binding`, off by default)
|
|
108
145
|
|
|
109
146
|
An evidence record is an attestation: canon never runs `--ref`, and it
|
|
@@ -243,7 +280,8 @@ Prefer this over hand-editing `settings.json`/`hooks.json`.
|
|
|
243
280
|
|
|
244
281
|
## `canon gate selftest`
|
|
245
282
|
|
|
246
|
-
Runs the shipped fixture corpus — one fixture per failure class,
|
|
283
|
+
Runs the shipped fixture corpus — one fixture per failure class (nine,
|
|
284
|
+
including `open-blocker`), each a
|
|
247
285
|
deliberately broken corpus proving that class fires and ONLY that class
|
|
248
286
|
(both under-detection and over-triggering fail the run). Takes no
|
|
249
287
|
`--repo`; self-contained. Run it before trusting any other `canon gate
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
# canon-review
|
|
2
|
+
|
|
3
|
+
Evidence says a test exists and what verdict it recorded. It does not say
|
|
4
|
+
that anyone other than the author looked at the work. Canon records that
|
|
5
|
+
second look as two ledger kinds — a **Finding** per issue a reviewer
|
|
6
|
+
raises, and a **Review** per scenario a reviewer signs off — and the
|
|
7
|
+
opt-in `spec_coverage.require_review` policy makes `canon gate check` and
|
|
8
|
+
`canon subject status` hold a subject until both are in order.
|
|
9
|
+
|
|
10
|
+
Both records are attestations: canon never checks a finding's summary
|
|
11
|
+
against the code, or that a reviewer actually read the scenario. What the
|
|
12
|
+
gate can check is that the records exist, who authored them, and what
|
|
13
|
+
state they are in.
|
|
14
|
+
|
|
15
|
+
## Finish a subject
|
|
16
|
+
|
|
17
|
+
The order an agent follows to claim a subject done:
|
|
18
|
+
|
|
19
|
+
1. **Test-run evidence** per owned scenario (`canon evidence add
|
|
20
|
+
--scenario-id <id> --project-id <root-id> ...`, then `canon gate
|
|
21
|
+
promote`). See `canon-gate`.
|
|
22
|
+
2. **Independent review** of the change(s) the subject adopted. Record
|
|
23
|
+
each issue the reviewer raises as a Finding, fix it, then close it:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
canon finding add --change-id c-demo --round 1 --seq 1 \
|
|
27
|
+
--severity blocker --disposition open --reviewer reviewer-2 \
|
|
28
|
+
--summary "unbounded subprocess wait"
|
|
29
|
+
canon gate promote
|
|
30
|
+
# ... fix, commit ...
|
|
31
|
+
canon finding close --change-id c-demo --round 1 --seq 1 \
|
|
32
|
+
--disposition fixed --resolution-sha "$(git rev-parse HEAD)"
|
|
33
|
+
canon gate promote
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
3. **One Review per scenario**, by someone other than the evidence actor:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
canon review add --project-id root --scenario-id world.demo.01 \
|
|
40
|
+
--reviewer reviewer-2 --actor-id reviewer-2 --role reviewer \
|
|
41
|
+
--pin "$(git rev-parse HEAD)" --upstream-ref "pr#41"
|
|
42
|
+
canon gate promote
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
4. **Move the subject**: `canon subject status <id> verifying`, later
|
|
46
|
+
`shipped`. See `canon-subject`.
|
|
47
|
+
|
|
48
|
+
## `canon finding add` / `canon finding close`
|
|
49
|
+
|
|
50
|
+
A Finding's natural key is `(change_id, round, seq)`: the change under
|
|
51
|
+
review, the 1-based review round, and the 1-based index within that
|
|
52
|
+
round. `seq` is never auto-assigned; `finding add` refuses an occupied
|
|
53
|
+
key, because two different findings under one key are two reviewers'
|
|
54
|
+
work collapsed into one identity.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
canon finding add --change-id <c> --round <n> --seq <n> \
|
|
58
|
+
--severity blocker|should-fix|note --disposition open \
|
|
59
|
+
--reviewer <who> --summary "<one line>" \
|
|
60
|
+
[--reviewed-sha <sha>] [--file-ref path/to/file.rs:120-134] [--actor-id <id>]
|
|
61
|
+
canon finding close --change-id <c> --round <n> --seq <n> \
|
|
62
|
+
--disposition fixed --resolution-sha <sha> # or rejected / deferred / open
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Both stage a candidate; `canon gate promote` commits it. `finding close`
|
|
66
|
+
changes only the disposition (and `resolution_sha` with it); severity,
|
|
67
|
+
reviewer, summary, and refs are copied from the committed record. It
|
|
68
|
+
appends a second version at the same natural key — the first stays.
|
|
69
|
+
|
|
70
|
+
### Severities
|
|
71
|
+
|
|
72
|
+
| Severity | Meaning |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `blocker` | Must be resolved before the work is claimed done. With `require_review`, an open blocker on an adopted change fails the gate (`open-blocker`). |
|
|
75
|
+
| `should-fix` | Worth fixing; may be scheduled for later. Never blocks the gate. |
|
|
76
|
+
| `note` | An observation; no obligation. |
|
|
77
|
+
|
|
78
|
+
Severity is the reviewer's own judgement, never a score canon derives.
|
|
79
|
+
|
|
80
|
+
### Dispositions
|
|
81
|
+
|
|
82
|
+
| Disposition | Meaning |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `open` | Raised and not yet dealt with. The default on `finding add`; `finding close --disposition open` reopens. |
|
|
85
|
+
| `fixed` | Fixed by a commit. Requires `--resolution-sha <sha>` naming a commit this repo holds; only `fixed` may carry one. |
|
|
86
|
+
| `rejected` | The reviewer's point was considered and declined. |
|
|
87
|
+
| `deferred` | Accepted, but postponed to later work. |
|
|
88
|
+
|
|
89
|
+
### How findings fold
|
|
90
|
+
|
|
91
|
+
Every reader takes the **latest version per natural key**
|
|
92
|
+
`(change_id, round, seq)` — the same fold the report's finding panel
|
|
93
|
+
uses. A blocker raised `open` and later closed `fixed` counts as fixed; a
|
|
94
|
+
fixed finding reopened with `--disposition open` counts as open again.
|
|
95
|
+
|
|
96
|
+
## `canon review add`
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
canon review add --project-id <root-id> --scenario-id <id> \
|
|
100
|
+
--reviewer <who> --pin <sha-or-ref> --role <role> \
|
|
101
|
+
(--upstream-ref <ref> | --original-spec-ref <ref>) [--actor-id <id>]
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
One attributed Review record for one scenario, joined on
|
|
105
|
+
`(project_id, scenario_id)` — both are required because two spec roots
|
|
106
|
+
may carry the same scenario id. Exactly one provenance ref is required.
|
|
107
|
+
`--actor-id` defaults to `canon`. A Review carries no verdict; the
|
|
108
|
+
`verifying → shipped` ship gate still refuses missing or `Divergent`
|
|
109
|
+
evidence verdicts on its own. Commit with `canon gate promote`.
|
|
110
|
+
|
|
111
|
+
## The `require_review` policy (opt-in)
|
|
112
|
+
|
|
113
|
+
```yaml
|
|
114
|
+
# .canon/policy.yaml
|
|
115
|
+
spec_coverage:
|
|
116
|
+
require_evidence: true
|
|
117
|
+
require_review: # absent = nothing changes, byte for byte
|
|
118
|
+
scope: [verifying, shipped] # default; [] = every scenario
|
|
119
|
+
distinct_actor: true # default
|
|
120
|
+
block_on_findings: true # default
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`require_review: {}` takes every default.
|
|
124
|
+
|
|
125
|
+
- **`scope`** — the subject statuses whose scenarios need a review. A
|
|
126
|
+
scenario is in scope when its `@subject:<id>` subject is in one of
|
|
127
|
+
them; `[]` means every scenario. It is independent of
|
|
128
|
+
`spec_coverage.scope`. `spec_coverage.exclude_lanes` also exempts
|
|
129
|
+
scenarios from review.
|
|
130
|
+
- **`distinct_actor`** — a review only counts when both its `reviewer`
|
|
131
|
+
and its actor (`--actor-id`) differ from every actor on that
|
|
132
|
+
scenario's evidence records. An agent cannot review its own attested
|
|
133
|
+
work.
|
|
134
|
+
- **`block_on_findings`** — fail on open blocker findings (below).
|
|
135
|
+
|
|
136
|
+
A malformed `require_review` (an unknown key, an unknown status, `null`,
|
|
137
|
+
a non-mapping) poisons the whole `spec_coverage` section: `canon gate
|
|
138
|
+
check` reports it invalid rather than treating it as off, the same as a
|
|
139
|
+
malformed `require_cases`.
|
|
140
|
+
|
|
141
|
+
Canon's own `.canon/policy.yaml` does not enable `require_review`.
|
|
142
|
+
|
|
143
|
+
## How it meets the gate
|
|
144
|
+
|
|
145
|
+
### `unreviewed-promotion`
|
|
146
|
+
|
|
147
|
+
An in-scope scenario with no qualifying review:
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
unreviewed-promotion world.demo.01 — no review record for this scenario; spec_coverage.require_review wants an independent review (`canon review add`) once its subject is claimed done
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
or, when the only reviews are self-reviews:
|
|
154
|
+
|
|
155
|
+
```
|
|
156
|
+
unreviewed-promotion world.demo.01 — every review of this scenario is by an actor that also attested its evidence (`impl-agent`); spec_coverage.require_review.distinct_actor wants a reviewer other than the evidence actor
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### `open-blocker`
|
|
160
|
+
|
|
161
|
+
With `block_on_findings`, a Finding whose latest version is severity
|
|
162
|
+
`blocker` and disposition `open`, on a change listed in an in-scope
|
|
163
|
+
subject's `change_ids` (`canon subject adopt`). The subject string is
|
|
164
|
+
`<change_id>#<round>.<seq>`:
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
open-blocker c-demo#1.1 — open blocker finding by `reviewer-2` on change `c-demo` (subject `demo-subject`): unbounded subprocess wait; fix it and `canon finding close --disposition fixed --resolution-sha <sha>`, or close it as rejected or deferred
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Findings on changes no in-scope subject has adopted do not block.
|
|
171
|
+
|
|
172
|
+
### Review-waiver advisories
|
|
173
|
+
|
|
174
|
+
A subject moved with `--override-reason` (below) has the exact gaps its
|
|
175
|
+
waiver recorded printed after the violations as advisories; the gate
|
|
176
|
+
stays green for those. A gap the waiver did not record (a blocker raised
|
|
177
|
+
later, a scenario tagged to the subject later) is a violation as usual:
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
review waivers: 1 advisory(ies) — not failing the gate:
|
|
181
|
+
waived unreviewed-promotion world.demo.01 — no review record ... [waiver: subject `demo-subject` moved to verifying by `lead`: reviewer out until Monday]
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## The status guard
|
|
185
|
+
|
|
186
|
+
With `require_review` present, `canon subject status <id> <state>`
|
|
187
|
+
prints on stderr which review checks it ran or skipped:
|
|
188
|
+
|
|
189
|
+
```
|
|
190
|
+
canon subject status: review guard for building → verifying (spec_coverage.require_review, scope: verifying, shipped)
|
|
191
|
+
ran unreviewed-promotion — every owned scenario needs a review by an actor other than its evidence actor
|
|
192
|
+
ran open-blocker — 1 adopted change(s) checked for open blocker findings
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
A target status outside the scope prints `skipped unreviewed-promotion —
|
|
196
|
+
`specced` is not in require_review.scope`. A transition into an in-scope
|
|
197
|
+
status with gaps prints the violations, exits 1, leaves the record
|
|
198
|
+
unchanged, and names `--override-reason`.
|
|
199
|
+
|
|
200
|
+
`--override-reason "<one line>"` waives ONLY `unreviewed-promotion` and
|
|
201
|
+
`open-blocker` — never ship-gate verdict or case gaps, never unreadable
|
|
202
|
+
routing. The new Subject record lists exactly the violations it let
|
|
203
|
+
through:
|
|
204
|
+
`status_override: {to, reason, waived: [{class, subject}], actor: {agent_id}}`
|
|
205
|
+
(`subject` is the scenario id, or `<change_id>#<round>.<seq>` for a
|
|
206
|
+
blocker; actor from `--actor-id`, default `canon`). The command prints
|
|
207
|
+
the `waived ...` lines and `override recorded by `lead` for the N
|
|
208
|
+
violation(s) above: <reason>`. A blank or multi-line reason exits 2. The
|
|
209
|
+
waiver covers only what it recorded, and clears on the subject's next
|
|
210
|
+
status write, so it never outlives the status it was granted for.
|
|
211
|
+
|
|
212
|
+
Without `require_review`, the guard prints nothing and changes nothing.
|
|
213
|
+
|
|
214
|
+
## Vocabulary in `canon context`
|
|
215
|
+
|
|
216
|
+
`canon context` (text and `--json`) carries a top-level `review` section:
|
|
217
|
+
`findingSeverities` (`blocker`, `should-fix`, `note`),
|
|
218
|
+
`findingDispositions` (`open`, `fixed`, `rejected`, `deferred`),
|
|
219
|
+
`reviewFields` (the Review kind's fields), and `requireReview` (the
|
|
220
|
+
active policy summary, or absent). The `spec_coverage` summary appends
|
|
221
|
+
` require_review=(scope=... distinct_actor=... block_on_findings=...)`
|
|
222
|
+
when set. Read it before authoring findings or reviews rather than
|
|
223
|
+
guessing the enums.
|
|
@@ -87,8 +87,10 @@ canon retrieve --role dev --domain dev --subject subject-domain-loop --k 5
|
|
|
87
87
|
- **Changes**: adopt imported plan changes under the Subject (see
|
|
88
88
|
[Adopt flow](#adopt-flow)).
|
|
89
89
|
- **Reviews / evidence / divergences**: authored as usual (`canon review
|
|
90
|
-
add`, `canon gate`, `canon divergence …`) against
|
|
91
|
-
scenarios — the join spine carries
|
|
90
|
+
add`, `canon finding add`, `canon gate`, `canon divergence …`) against
|
|
91
|
+
the Subject's scenarios and adopted changes — the join spine carries
|
|
92
|
+
them back through `scenario_id` and `change_id`. See `canon-review`
|
|
93
|
+
for the finish-a-subject order.
|
|
92
94
|
|
|
93
95
|
### 4. Verdicts / trajectories → learn (knowledge out)
|
|
94
96
|
|
|
@@ -98,7 +100,8 @@ this subject and domain — the exact memory step 2 retrieves next time.
|
|
|
98
100
|
|
|
99
101
|
## Status lifecycle + the shipped evidence gate
|
|
100
102
|
|
|
101
|
-
`canon subject status <id> <state
|
|
103
|
+
`canon subject status <id> <state> [--override-reason <text>] [--actor-id <id>]`
|
|
104
|
+
performs a policy-gated transition.
|
|
102
105
|
The legal chain:
|
|
103
106
|
|
|
104
107
|
```
|
|
@@ -141,6 +144,52 @@ empty set; so is one whose `scenario` records route away from the
|
|
|
141
144
|
gate's rung. Each refusal prints by failure class (`uncovered-cell`),
|
|
142
145
|
exits 1, and the status stays `verifying`. `retired` is not gated.
|
|
143
146
|
|
|
147
|
+
### The review guard (`spec_coverage.require_review`, opt-in)
|
|
148
|
+
|
|
149
|
+
When `.canon/policy.yaml` sets `spec_coverage.require_review` (see
|
|
150
|
+
`canon-review`), every status write also runs the review checks and
|
|
151
|
+
prints on stderr which it ran or skipped:
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
canon subject status: review guard for building → verifying (spec_coverage.require_review, scope: verifying, shipped)
|
|
155
|
+
ran unreviewed-promotion — every owned scenario needs a review by an actor other than its evidence actor
|
|
156
|
+
ran open-blocker — 1 adopted change(s) checked for open blocker findings
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
A target outside `require_review.scope` prints `skipped
|
|
160
|
+
unreviewed-promotion — `specced` is not in require_review.scope`. A
|
|
161
|
+
transition INTO an in-scope status with gaps — an owned scenario with no
|
|
162
|
+
qualifying review (`unreviewed-promotion`), or an open blocker finding
|
|
163
|
+
on an adopted change (`open-blocker`) — prints the violations, exits 1,
|
|
164
|
+
leaves the record unchanged, and names `--override-reason`.
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
canon subject status demo-subject verifying \
|
|
168
|
+
--override-reason "reviewer out until Monday" --actor-id lead
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
`--override-reason "<one line>"` waives ONLY `unreviewed-promotion` and
|
|
172
|
+
`open-blocker` — never a ship-gate verdict or case gap, never unreadable
|
|
173
|
+
routing. It prints the `waived ...` lines and `override recorded by
|
|
174
|
+
`lead` for the N violation(s) above: <reason>`, and records on the new
|
|
175
|
+
Subject record exactly the violations it let through:
|
|
176
|
+
|
|
177
|
+
```yaml
|
|
178
|
+
status_override:
|
|
179
|
+
to: verifying
|
|
180
|
+
reason: reviewer out until Monday
|
|
181
|
+
waived:
|
|
182
|
+
- { class: unreviewed-promotion, subject: world.demo.01 }
|
|
183
|
+
actor: { agent_id: lead } # from --actor-id, default `canon`
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
A blank or multi-line reason exits 2. The waiver is cleared on the
|
|
187
|
+
subject's next status write, so it never outlives the status it was
|
|
188
|
+
granted for. While it stands, `canon gate check` lists the recorded gaps
|
|
189
|
+
as advisories instead of failing; a gap it did not record (a blocker
|
|
190
|
+
raised later, a scenario tagged later) still fails the gate. Without
|
|
191
|
+
`require_review`, nothing is printed and nothing changes.
|
|
192
|
+
|
|
144
193
|
## Adopt flow
|
|
145
194
|
|
|
146
195
|
Planning docs become change/task records via `canon ingest plans` (see
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@journeykit/canon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "canon — harness knowledge substrate. JS launcher: platform detection + native binary resolution.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {},
|
|
32
32
|
"optionalDependencies": {
|
|
33
|
-
"@journeykit/canon-core-darwin-arm64": "0.
|
|
34
|
-
"@journeykit/canon-core-linux-x64": "0.
|
|
35
|
-
"@journeykit/canon-core-win32-x64": "0.
|
|
33
|
+
"@journeykit/canon-core-darwin-arm64": "0.12.0",
|
|
34
|
+
"@journeykit/canon-core-linux-x64": "0.12.0",
|
|
35
|
+
"@journeykit/canon-core-win32-x64": "0.12.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^20.0.0",
|