@journeykit/canon 0.26.0 → 0.27.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.
|
@@ -58,21 +58,19 @@ bytes no longer match the approved digest, or the approval cannot be read,
|
|
|
58
58
|
the gate fails closed: the violation is reported and the exit is `1` (see
|
|
59
59
|
`canon-policy`).
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
`<root>` is stale and could not be refreshed (…); `canon inventory sync`
|
|
75
|
-
lists the problems to fix` and exits 1, since the index it would grade
|
|
61
|
+
The gate is a read command: it writes nothing. A scenario index that is
|
|
62
|
+
stale (a `.feature` file added, edited or deleted since the last sync) is
|
|
63
|
+
graded as the refresh would leave it, built in memory from the changed
|
|
64
|
+
files with the code `canon inventory sync` runs; the index on disk is
|
|
65
|
+
brought up to date by the next command that writes (`canon evidence add`,
|
|
66
|
+
`canon review add`, `canon subject status`) or by `canon inventory sync`.
|
|
67
|
+
It prints no refresh line.
|
|
68
|
+
|
|
69
|
+
A root that fails to sync (format violations, a duplicate id) cannot be
|
|
70
|
+
graded in memory either, and the gate fails closed: it adds
|
|
71
|
+
`uncovered-cell <root> — the scenario index for spec root `<root>` is
|
|
72
|
+
stale and could not be refreshed (…); `canon inventory sync` lists the
|
|
73
|
+
problems to fix` and exits 1, since the index it would grade
|
|
76
74
|
does not hold the edits. The `verifying → shipped` guard refuses with
|
|
77
75
|
the same violation, and `canon status` lists the sync as its only step.
|
|
78
76
|
Fix what the sync lists and run the gate again. See `canon-storage`
|
|
@@ -6,21 +6,25 @@ records every downstream stage joins against.
|
|
|
6
6
|
|
|
7
7
|
## You rarely run it yourself
|
|
8
8
|
|
|
9
|
-
Since 0.16 the commands that read the index
|
|
10
|
-
`
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
Since 0.16 the commands that read the index see added, edited and deleted
|
|
10
|
+
`.feature` files without a sync step. `canon evidence add`, `canon review
|
|
11
|
+
add` and `canon subject status` refresh the index on disk first, with the
|
|
12
|
+
same code this command runs, scoped to the changed files, and say so in one
|
|
13
|
+
stderr line:
|
|
14
14
|
|
|
15
15
|
```
|
|
16
|
-
canon
|
|
16
|
+
canon evidence add: refreshed the scenario index from 1 changed feature file(s) (.canon/specs/kind=feature/area=cart/add.feature): 1 record(s) written
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
+
`canon status` and `canon gate check` are read commands and write nothing:
|
|
20
|
+
they grade the index as that refresh would leave it, built in memory, and
|
|
21
|
+
print no line.
|
|
22
|
+
|
|
19
23
|
So the working loop has no sync step and no `canon format` step: write the
|
|
20
24
|
scenario (`canon scenario new` writes it format-clean) and run the next
|
|
21
25
|
command. Run `canon inventory sync` when:
|
|
22
26
|
|
|
23
|
-
- a
|
|
27
|
+
- a command prints `NOT refreshed` — a root has a format violation (a
|
|
24
28
|
hand-written `Feature:`/`Scenario:` header with no `# canon:` provenance
|
|
25
29
|
comment, an emptied file, …) or a duplicate id, so its files were not
|
|
26
30
|
indexed. `canon gate check` then fails (`uncovered-cell <root>`),
|
|
@@ -57,7 +61,7 @@ and the openspec source `canon init` wrote is removed only after every
|
|
|
57
61
|
pointer brief is written and nothing unread is left under
|
|
58
62
|
`openspec/changes/` (each unread directory is named).
|
|
59
63
|
|
|
60
|
-
The
|
|
64
|
+
The refresh treats a file as stale when its latest index
|
|
61
65
|
generation has another `source_digest` or `scenario_digest`. A
|
|
62
66
|
generation written before 0.15 has no `scenario_digest`, so a repo that
|
|
63
67
|
kept an old index gets it rewritten on the first read.
|
|
@@ -68,7 +72,7 @@ kept an old index gets it rewritten on the first read.
|
|
|
68
72
|
author .feature corpus (canon scenario new)
|
|
69
73
|
│
|
|
70
74
|
▼
|
|
71
|
-
scenario index # refreshed by
|
|
75
|
+
scenario index # refreshed by the writers; `canon inventory sync` rebuilds it
|
|
72
76
|
│
|
|
73
77
|
▼
|
|
74
78
|
canon review add # attests a review — see canon-inventory downstream / canon-gate
|
|
@@ -272,21 +272,27 @@ fails those commands (exit `1`), and `canon init --check-config` reports
|
|
|
272
272
|
|
|
273
273
|
`canon inventory sync` materializes one `Scenario` record per
|
|
274
274
|
`(project_id, scenario_id)` under `.canon/ledger/kind=scenario/`. The
|
|
275
|
-
index is derived — a pure function of the `.feature` files
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
`canon
|
|
283
|
-
|
|
275
|
+
index is derived — a pure function of the `.feature` files. The index is
|
|
276
|
+
stale when a `.feature` file holds a scenario with no live index record,
|
|
277
|
+
or one whose recorded source digest differs from the file's current bytes,
|
|
278
|
+
or when the index holds a scenario of a spec root that no `.feature` file
|
|
279
|
+
of it declares any more.
|
|
280
|
+
|
|
281
|
+
The commands that write records (`canon subject status`, `canon review
|
|
282
|
+
add` and `canon evidence add`) rebuild a stale index on disk first: they
|
|
283
|
+
run `canon inventory sync`'s code on the changed files (validation still
|
|
284
|
+
covers the whole root) and print one stderr line:
|
|
284
285
|
|
|
285
286
|
```
|
|
286
|
-
canon
|
|
287
|
+
canon evidence add: refreshed the scenario index from 1 changed feature file(s) (.canon/specs/kind=feature/area=cart/add.feature): 1 record(s) written
|
|
287
288
|
```
|
|
288
289
|
|
|
289
|
-
|
|
290
|
+
The commands that only read (`canon gate check`, `canon status`) write
|
|
291
|
+
nothing: they grade a stale index as the refresh would leave it, built in
|
|
292
|
+
memory, and print no refresh line. `canon query --kind scenario` and the
|
|
293
|
+
report panels read the index on disk as it is.
|
|
294
|
+
|
|
295
|
+
A deleted scenario is not erased: `canon inventory sync` — and a writer's
|
|
290
296
|
refresh, identically — appends a tombstone, a new generation of its
|
|
291
297
|
record with `removed: true`. The gate, `canon status`, `canon query` and
|
|
292
298
|
the report panels then treat it as absent; re-adding the scenario writes
|
|
@@ -294,7 +300,7 @@ a live generation that supersedes the tombstone. A root that fails to
|
|
|
294
300
|
sync writes no tombstone either.
|
|
295
301
|
|
|
296
302
|
```
|
|
297
|
-
canon
|
|
303
|
+
canon evidence add: refreshed the scenario index from 1 scenario(s) no longer in any feature file (cart.pay.01): 1 record(s) written
|
|
298
304
|
```
|
|
299
305
|
|
|
300
306
|
`canon inventory sync` and every refresh hold an OS file lock on
|
|
@@ -303,17 +309,16 @@ index one change twice; a refresh that waited checks staleness again and
|
|
|
303
309
|
is silent if another run already did the work. The lock is released when
|
|
304
310
|
its holder exits, however it exits, so it never goes stale; a writer
|
|
305
311
|
gives up after 30 s with a message naming the file (`canon inventory
|
|
306
|
-
sync` exits `2`; a
|
|
312
|
+
sync` exits `2`; a writer's refresh is skipped and the command still runs).
|
|
307
313
|
|
|
308
314
|
A fresh index prints nothing. A root that fails to sync (format
|
|
309
315
|
violations, a duplicate id) is named and left as it was, and the command
|
|
310
316
|
still runs; `canon gate check` then fails with `uncovered-cell <root>`,
|
|
311
317
|
the `verifying → shipped` guard refuses, and `canon status` lists only
|
|
312
|
-
`canon inventory sync
|
|
313
|
-
keep only this line:
|
|
318
|
+
`canon inventory sync`:
|
|
314
319
|
|
|
315
320
|
```
|
|
316
|
-
canon
|
|
321
|
+
canon evidence add: found the scenario index stale for 1 changed feature file(s) (…): 0 record(s) written; NOT refreshed: root `root` (2 format violation(s), 0 sync error(s)) — `canon inventory sync` lists them
|
|
317
322
|
```
|
|
318
323
|
|
|
319
324
|
Nothing is written in a directory without `canon.yaml`. `canon inventory
|
|
@@ -21,11 +21,13 @@ authored in one place:
|
|
|
21
21
|
adopt`.
|
|
22
22
|
- **Scenarios**: the `@subject:<id>` tag on each Gherkin scenario,
|
|
23
23
|
indexed onto `Scenario.subject_id` by the scenario index (rebuilt by
|
|
24
|
-
`canon inventory sync`, and refreshed by
|
|
24
|
+
`canon inventory sync`, and refreshed on disk by the commands that write
|
|
25
|
+
records; `canon status` and `canon gate check` read it as the refresh
|
|
26
|
+
would leave it, without writing).
|
|
25
27
|
The Subject record carries no scenario list — the spec corpus is the
|
|
26
28
|
only source, and the Subjects report panel, `spec_coverage.scope`, and
|
|
27
29
|
the shipped gate all read it from there. To link a scenario, tag it;
|
|
28
|
-
the next `canon status` or `canon gate check`
|
|
30
|
+
the next `canon status` or `canon gate check` reads the tag. There is
|
|
29
31
|
no subject-side command for it.
|
|
30
32
|
|
|
31
33
|
## The 4-step loop
|
|
@@ -609,9 +611,9 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
609
611
|
unreadable one → `canon init --check-config`; a scenario tagged with a
|
|
610
612
|
subject that has no record → `canon subject new <that id>`; no subject
|
|
611
613
|
at all → `canon subject new`; subjects and `.feature` scenarios but no
|
|
612
|
-
scenario records → `canon inventory sync` (status
|
|
613
|
-
|
|
614
|
-
or a duplicate id, which the sync names). Then per subject, verifying
|
|
614
|
+
scenario records → `canon inventory sync` (status reads the index as a
|
|
615
|
+
refresh would leave it, so this means the refresh would be refused on a
|
|
616
|
+
format violation or a duplicate id, which the sync names). Then per subject, verifying
|
|
615
617
|
first, then building, specced, proposed, shipped: an unapproved brief
|
|
616
618
|
(building and later, and proposed once its change has a brief)
|
|
617
619
|
→ the human step below, which is then the subject's
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@journeykit/canon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.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.27.0",
|
|
34
|
+
"@journeykit/canon-core-linux-x64": "0.27.0",
|
|
35
|
+
"@journeykit/canon-core-win32-x64": "0.27.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^20.0.0",
|