@journeykit/canon 0.14.0 → 0.16.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 +92 -30
- package/dist/skills/reference/canon-authoring.md +10 -3
- package/dist/skills/reference/canon-gate.md +238 -19
- package/dist/skills/reference/canon-inventory.md +35 -8
- package/dist/skills/reference/canon-policy.md +114 -7
- package/dist/skills/reference/canon-review.md +198 -21
- package/dist/skills/reference/canon-storage.md +124 -1
- package/dist/skills/reference/canon-subject.md +173 -45
- package/package.json +4 -4
|
@@ -20,11 +20,13 @@ authored in one place:
|
|
|
20
20
|
- **Changes**: `change_ids` on the Subject, appended by `canon subject
|
|
21
21
|
adopt`.
|
|
22
22
|
- **Scenarios**: the `@subject:<id>` tag on each Gherkin scenario,
|
|
23
|
-
indexed onto `Scenario.subject_id` by
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
indexed onto `Scenario.subject_id` by the scenario index (rebuilt by
|
|
24
|
+
`canon inventory sync`, and refreshed by every command that reads it).
|
|
25
|
+
The Subject record carries no scenario list — the spec corpus is the
|
|
26
|
+
only source, and the Subjects report panel, `spec_coverage.scope`, and
|
|
27
|
+
the shipped gate all read it from there. To link a scenario, tag it;
|
|
28
|
+
the next `canon status` or `canon gate check` indexes the tag. There is
|
|
29
|
+
no subject-side command for it.
|
|
28
30
|
|
|
29
31
|
## The 4-step loop
|
|
30
32
|
|
|
@@ -81,9 +83,10 @@ canon retrieve --role dev --domain dev --subject subject-domain-loop --k 5
|
|
|
81
83
|
### 3. Work → pin every artifact to `subject_id`
|
|
82
84
|
|
|
83
85
|
- **Scenarios**: `canon scenario new <tag> --subject <subject-id>` emits
|
|
84
|
-
the `@subject:<subject-id>` tag;
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
the `@subject:<subject-id>` tag; the scenario index maps the tag onto
|
|
87
|
+
the scenario's `subject_id` the next time a command reads it (no sync
|
|
88
|
+
step; see `canon-inventory`). A malformed/absent tag leaves it unset
|
|
89
|
+
(fail-soft), never an error. See `canon-authoring`.
|
|
87
90
|
- **Changes**: adopt imported plan changes under the Subject (see
|
|
88
91
|
[Adopt flow](#adopt-flow)).
|
|
89
92
|
- **Reviews / evidence / divergences**: authored as usual (`canon review
|
|
@@ -145,6 +148,36 @@ empty set; so is one whose `scenario` records route away from the
|
|
|
145
148
|
gate's rung. Each refusal prints by failure class (`uncovered-cell`),
|
|
146
149
|
exits 1, and the status stays `verifying`. `retired` is not gated.
|
|
147
150
|
|
|
151
|
+
**The brief (0.16):** `verifying → shipped` also refuses where a brief
|
|
152
|
+
exists and is not approved, read exactly as `canon status` reads it (one
|
|
153
|
+
shared check, so status says `ship` only when this passes): the subject's
|
|
154
|
+
newest adopted change has a `proposal.md` under the openspec plan sources,
|
|
155
|
+
and it carries no `Approved:` line outside HTML comments and code fences.
|
|
156
|
+
It runs with or without a policy. The refusal is an `unreviewed-promotion`
|
|
157
|
+
naming the subject, and says what to do:
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
canon subject status: unreviewed-promotion demo-subject — verifying → shipped: brief not approved — openspec/changes/c-demo/proposal.md has no `Approved:` line; a human must answer the brief, and the agent records `Approved: <who> <when> — "<their words>"` there only from that answer
|
|
161
|
+
canon subject status: refused — get the human's answer to the brief and record it as its `Approved:` line, or pass --override-reason <text> to move anyway; the waiver is recorded on the subject
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Never write the line without the human's answer. When there is no brief to
|
|
165
|
+
answer (no openspec plan source, no adopted change, or a change with no
|
|
166
|
+
`proposal.md`), the move is not refused: it prints
|
|
167
|
+
`canon subject status: advisory: <id>'s brief is not approved — <why>, so
|
|
168
|
+
there is no brief to answer and shipping is not refused`, and status shows
|
|
169
|
+
the brief as not approved, as an advisory. `subjects[].brief.enforced` in
|
|
170
|
+
`canon status --json` says which case applies. A brief that says the human
|
|
171
|
+
ships changes who runs the transition, not the check.
|
|
172
|
+
|
|
173
|
+
This refusal is a backstop, and so is the evidence one: shipping is not
|
|
174
|
+
the first thing an unapproved brief stops. The agent writes the brief,
|
|
175
|
+
then stops and reports it, and nothing is built or attested for the
|
|
176
|
+
subject until the human answers. `canon evidence add` refuses (exit 1,
|
|
177
|
+
nothing staged) a scenario whose `@subject` owner, or a task whose change
|
|
178
|
+
an adopting subject, has an enforced, unapproved brief, through the same
|
|
179
|
+
check; see `canon-gate`.
|
|
180
|
+
|
|
148
181
|
### The review guard (`spec_coverage.require_review`, opt-in)
|
|
149
182
|
|
|
150
183
|
When `.canon/policy.yaml` sets `spec_coverage.require_review` (see
|
|
@@ -162,16 +195,21 @@ unreviewed-promotion — `specced` is not in require_review.scope`. A
|
|
|
162
195
|
transition INTO an in-scope status with gaps — an owned scenario with no
|
|
163
196
|
qualifying review (`unreviewed-promotion`), or an open blocker finding
|
|
164
197
|
on an adopted change (`open-blocker`) — prints the violations, exits 1,
|
|
165
|
-
leaves the record unchanged, and names `--override-reason`.
|
|
198
|
+
leaves the record unchanged, and names `--override-reason`. `shipped`
|
|
199
|
+
also refuses a `false-success` (a scenario whose latest audit is
|
|
200
|
+
`refuted`) and, when `require_audit.scope` covers `shipped`, an owed
|
|
201
|
+
sampled audit; see `canon-gate`.
|
|
166
202
|
|
|
167
203
|
```bash
|
|
168
204
|
canon subject status demo-subject verifying \
|
|
169
205
|
--override-reason "reviewer out until Monday" --actor-id lead
|
|
170
206
|
```
|
|
171
207
|
|
|
172
|
-
`--override-reason "<one line>"` waives ONLY `unreviewed-promotion`
|
|
173
|
-
`open-blocker` — never a ship-gate
|
|
174
|
-
|
|
208
|
+
`--override-reason "<one line>"` waives ONLY `unreviewed-promotion` (the
|
|
209
|
+
review gaps and the brief check) and `open-blocker` — never a ship-gate
|
|
210
|
+
verdict or case gap, never unreadable routing. A waived brief is recorded
|
|
211
|
+
as `{ class: unreviewed-promotion, subject: <subject id> }`. It prints
|
|
212
|
+
the `waived ...` lines and `override recorded by
|
|
175
213
|
`lead` for the N violation(s) above: <reason>`, and records on the new
|
|
176
214
|
Subject record exactly the violations it let through:
|
|
177
215
|
|
|
@@ -189,13 +227,14 @@ subject's next status write, so it never outlives the status it was
|
|
|
189
227
|
granted for. While it stands, `canon gate check` lists the recorded gaps
|
|
190
228
|
as advisories instead of failing; a gap it did not record (a blocker
|
|
191
229
|
raised later, a scenario tagged later) still fails the gate. Without
|
|
192
|
-
`require_review`, nothing is printed and nothing changes
|
|
230
|
+
`require_review`, nothing is printed and nothing changes, except that
|
|
231
|
+
`shipped` still runs the brief check above.
|
|
193
232
|
|
|
194
233
|
## Adopt flow
|
|
195
234
|
|
|
196
|
-
Planning docs become change/task records via
|
|
197
|
-
`canon-plan-import`), but that stops at import.
|
|
198
|
-
lifts an imported change into a managed Subject:
|
|
235
|
+
Planning docs written outside canon become change/task records via
|
|
236
|
+
`canon ingest plans` (see `canon-plan-import`), but that stops at import.
|
|
237
|
+
`canon subject adopt` lifts an imported change into a managed Subject:
|
|
199
238
|
|
|
200
239
|
```bash
|
|
201
240
|
canon ingest plans --repo . # import → change/task rows
|
|
@@ -203,6 +242,13 @@ canon subject adopt subject-domain-loop-plan \
|
|
|
203
242
|
--subject subject-domain-loop # link change → subject
|
|
204
243
|
```
|
|
205
244
|
|
|
245
|
+
A change made with `canon change new` (below) is recorded and adopted
|
|
246
|
+
already, and editing its `tasks.md` needs no import either:
|
|
247
|
+
`canon evidence add --task` and `canon gate task` read the file as it is,
|
|
248
|
+
and a flip re-imports that change itself. Run `canon ingest plans` for a
|
|
249
|
+
plan written outside canon, or when `canon query --kind task` must list
|
|
250
|
+
rows nobody has flipped yet.
|
|
251
|
+
|
|
206
252
|
`adopt` stamps the change's `subject_id` and adds it to the Subject's
|
|
207
253
|
`change_ids`, so `canon query --kind change --change-id …` and `canon
|
|
208
254
|
query --kind subject` agree on the link from both ends. It writes only
|
|
@@ -248,9 +294,10 @@ canon change new add-login --subject auth --title "Add login"
|
|
|
248
294
|
exist, when the slug already has a change dir (active or archived) or a
|
|
249
295
|
`change` record, or when `canon.yaml` has no `openspec` plans source.
|
|
250
296
|
|
|
251
|
-
Add task rows to `tasks.md` as `- [ ] <n> <title>`,
|
|
252
|
-
|
|
253
|
-
|
|
297
|
+
Add task rows to `tasks.md` as `- [ ] <n> <title>`, and flip each with
|
|
298
|
+
`canon gate task <slug>#<n>` once evidence exists. `canon evidence add
|
|
299
|
+
--task` and the flip read `tasks.md` as it is, so a new row needs no
|
|
300
|
+
`canon ingest plans` run.
|
|
254
301
|
|
|
255
302
|
## Where are we: `canon status`
|
|
256
303
|
|
|
@@ -274,29 +321,92 @@ uses, so status and the gate cannot disagree about a gap:
|
|
|
274
321
|
scenarios it owns through `@subject:` (after `exclude_lanes`, which
|
|
275
322
|
are counted separately), how many carry a ledger verdict (the
|
|
276
323
|
`verifying → shipped` gate's reading; divergent ones are counted too),
|
|
277
|
-
how many carry a review that satisfies `require_review` (any
|
|
278
|
-
when it is off; with `distinct_actor`, a self-review does
|
|
279
|
-
open blocker findings on its adopted changes, and each
|
|
280
|
-
missing a `require_cases` case. `(N due)` marks reviews
|
|
281
|
-
transition will require
|
|
324
|
+
how many carry a review that satisfies `require_review` (any current
|
|
325
|
+
signed review when it is off; with `distinct_actor`, a self-review does
|
|
326
|
+
not count), open blocker findings on its adopted changes, and each
|
|
327
|
+
feature surface missing a `require_cases` case. `(N due)` marks reviews
|
|
328
|
+
the next transition will require; `N stale review(s)` and `N unsigned
|
|
329
|
+
review(s)` (printed when non-zero) count scenarios whose review went
|
|
330
|
+
stale or whose latest reviews are all `indeterminate`/`unavailable`
|
|
331
|
+
(see `canon-review`), and the `canon review add` step names both. With
|
|
332
|
+
`require_review` on, a `warning:` line counts the in-effect reviews that
|
|
333
|
+
predate review pinning (0.15), checked against the commit each pinned:
|
|
334
|
+
current, stale (named) and undecidable.
|
|
335
|
+
- **Brief** (0.16) — for each `building`, `verifying` or `shipped`
|
|
336
|
+
subject, and each `proposed` subject whose newest adopted change has a
|
|
337
|
+
`proposal.md`, a `brief:` line under it says whether the brief is approved:
|
|
338
|
+
`brief: approved in <proposal.md> — <the recorded words>`, or
|
|
339
|
+
`brief: not approved (…)`. Approval is an `Approved:` line in the
|
|
340
|
+
`proposal.md` of the subject's newest adopted change (the last one
|
|
341
|
+
adopted): a line that starts with `Approved:` (indent allowed), says
|
|
342
|
+
something after it, and sits outside HTML comments (`<!-- … -->`,
|
|
343
|
+
multi-line included) and fenced code blocks (```` ``` ```` or `~~~`),
|
|
344
|
+
written by the agent once the human answers, as
|
|
345
|
+
`Approved: <who> <when> — "<the human's words>"`. Fixes and follow-ups
|
|
346
|
+
live as tasks in the approved change, so a newly adopted change is a
|
|
347
|
+
new scope: an older change's approval does not cover it. Status reads
|
|
348
|
+
the line from the change dir under the repo's `openspec` plans sources,
|
|
349
|
+
in config order (the first source holding the change owns it, a live
|
|
350
|
+
dir before an archived one; with no `plans:` section, the `openspec`
|
|
351
|
+
source rooted at the repo that `canon gate task` also falls back to).
|
|
352
|
+
There is no record kind for it; the file is the record.
|
|
282
353
|
- **Unowned** — scenarios with no `@subject:` tag.
|
|
283
|
-
-
|
|
354
|
+
- **Audits** — how many scenarios are sampled for
|
|
355
|
+
`spec_coverage.require_audit`, confirmed, owed (no audit or
|
|
356
|
+
`indeterminate`) and refuted (`false-success`). An owed or
|
|
357
|
+
refuted audit adds a `next:` step suggesting `canon evidence add
|
|
358
|
+
--kind audit …` (recorded from an external evaluator; canon never runs
|
|
359
|
+
one).
|
|
360
|
+
- **Dropped bindings** — `dropped bindings (N):` lists every recorded
|
|
361
|
+
`--drop-attachment` (scenario, paths, reason); `drops[]` in `--json`.
|
|
362
|
+
- **Brief overrides** — a `warning:` line per evidence record attested
|
|
363
|
+
with `canon evidence add --override-reason` while its subject's brief
|
|
364
|
+
was not approved: what it attests, who, when, the subject and the
|
|
365
|
+
reason (see `canon-gate`).
|
|
366
|
+
- **`next:`** — at most five steps, each with a one-line reason; the
|
|
284
367
|
rest are counted. Rules, in order: no `canon.yaml` → `canon init`; an
|
|
285
368
|
unreadable one → `canon init --check-config`; a scenario tagged with a
|
|
286
369
|
subject that has no record → `canon subject new <that id>`; no subject
|
|
287
|
-
at all → `canon subject new`; subjects
|
|
288
|
-
`canon inventory sync
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
`canon
|
|
295
|
-
`
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
370
|
+
at all → `canon subject new`; subjects and `.feature` scenarios but no
|
|
371
|
+
scenario records → `canon inventory sync` (status refreshes the index
|
|
372
|
+
itself first, so this means the refresh refused on a format violation
|
|
373
|
+
or a duplicate id, which the sync names). Then per subject, verifying
|
|
374
|
+
first, then building, specced, proposed, shipped: an unapproved brief
|
|
375
|
+
(building and later, and proposed once its change has a `proposal.md`)
|
|
376
|
+
→ the human step below, which is then the subject's
|
|
377
|
+
only step; no scenario → `canon scenario new … --subject <id>` (and, when no
|
|
378
|
+
`.feature` file holds a scenario yet, `canon feature new` first, unless
|
|
379
|
+
every subject waits on its brief); a missing case → `canon scenario new
|
|
380
|
+
<surface>.<next nn> … --case <case>`; (building and later) an
|
|
381
|
+
unevidenced or divergent scenario → `canon evidence add --scenario-id
|
|
382
|
+
…` (its reason adds "then `canon gate promote`" only under
|
|
383
|
+
`write.promote: manual`); an open blocker → `canon finding close …`; a
|
|
384
|
+
due, unreviewed, evidenced scenario → `canon review add …` from another
|
|
385
|
+
session; none of these → `canon subject status <id> <next status>`.
|
|
386
|
+
Last, unowned scenarios → `canon status`, after tagging them in their
|
|
387
|
+
`.feature` files (status re-indexes the edit; no sync step). With more
|
|
388
|
+
than one `specs.roots[]` entry, every suggested `canon scenario new`
|
|
389
|
+
carries `--project`: the owning root for a missing case, `<root-id>`
|
|
390
|
+
(the reason lists the roots) for a subject that owns no scenario yet.
|
|
391
|
+
- **The one human step.** Every step is the agent's to run except one:
|
|
392
|
+
a subject whose brief is enforced (its newest change has a
|
|
393
|
+
`proposal.md` with no `Approved:` line) gets
|
|
394
|
+
`human: stop and report the brief in <proposal.md>; build and attest nothing for <id> until the human answers (one answer approves brief and policy)`,
|
|
395
|
+
whose reason names that `proposal.md`, says `canon evidence add`
|
|
396
|
+
refuses the subject's scenarios and tasks until the line is recorded,
|
|
397
|
+
and names `canon policy approve --by <the human> --note "<their words>"`.
|
|
398
|
+
It is the subject's only step, whatever its status: nothing suggests
|
|
399
|
+
`canon feature new`, `canon scenario new`, `canon evidence add`, a
|
|
400
|
+
review or a move-on for it before the human answers, and
|
|
401
|
+
`canon subject status <id> shipped` refuses on the same check. The
|
|
402
|
+
approval is never assumed. A subject with no brief to answer gets no human step;
|
|
403
|
+
its `brief:` line says
|
|
404
|
+
`not approved (no adopted change; advisory, nothing to approve yet)` or
|
|
405
|
+
``not approved (change `<id>` has no proposal.md; advisory, nothing to
|
|
406
|
+
approve yet)`` and nothing is withheld (a `proposed` subject with no
|
|
407
|
+
`proposal.md`, and a `specced` subject, show no `brief:` line at all). Once nothing blocks, a
|
|
408
|
+
ship-ready verifying subject gets the agent's own
|
|
409
|
+
`canon subject status <id> shipped`; status never asks a human to ship.
|
|
300
410
|
|
|
301
411
|
Status fails closed rather than suggest progress the gate would refuse:
|
|
302
412
|
|
|
@@ -314,19 +424,24 @@ Status fails closed rather than suggest progress the gate would refuse:
|
|
|
314
424
|
|
|
315
425
|
```json
|
|
316
426
|
{
|
|
317
|
-
"statusVersion":
|
|
318
|
-
"canonVersion": "0.
|
|
427
|
+
"statusVersion": 2,
|
|
428
|
+
"canonVersion": "0.16.0",
|
|
319
429
|
"policy": { "present": true, "spec_coverage": { "require_evidence": true, "scope": [], "exclude_lanes": [], "require_cases": ["failure"], "require_review": { "scope": ["verifying", "shipped"], "distinct_actor": true, "block_on_findings": true } } },
|
|
320
430
|
"warnings": [],
|
|
321
431
|
"subjects": [
|
|
322
432
|
{ "id": "cart", "title": "Cart", "status": "building", "scenarios": 2, "excluded": 0, "evidenced": 2, "divergent": 0,
|
|
323
|
-
"reviewed": 1, "reviewDue": true, "openBlockers": 1, "missingCases": []
|
|
433
|
+
"reviewed": 1, "staleReviews": 0, "unsignedReviews": 0, "reviewDue": true, "openBlockers": 1, "missingCases": [],
|
|
434
|
+
"brief": { "approved": true, "enforced": false, "change": "c-cart", "proposal": "openspec/changes/c-cart/proposal.md", "approval": "Journey 2026-10-11 — \"approved\"" } },
|
|
435
|
+
{ "id": "promo", "title": "Promo", "status": "verifying", "scenarios": 1, "excluded": 0, "evidenced": 1, "divergent": 0,
|
|
436
|
+
"reviewed": 1, "staleReviews": 0, "unsignedReviews": 0, "reviewDue": true, "openBlockers": 0, "missingCases": [],
|
|
437
|
+
"brief": { "approved": false, "enforced": true, "change": "c-promo", "proposal": "openspec/changes/c-promo/proposal.md" } }
|
|
324
438
|
],
|
|
325
439
|
"unowned": ["cart.promo.01"],
|
|
326
440
|
"next": [
|
|
327
|
-
{ "command": "
|
|
328
|
-
{ "command": "canon
|
|
329
|
-
{ "command": "canon
|
|
441
|
+
{ "command": "stop and report the brief in openspec/changes/c-promo/proposal.md; build and attest nothing for promo until the human answers (one answer approves brief and policy)", "why": "promo: its newest adopted change's proposal.md carries no `Approved:` line …", "actor": "human" },
|
|
442
|
+
{ "command": "canon finding close --change-id c-cart --round 1 --seq 1 --disposition fixed --resolution-sha <sha> --actor-id <unit> --session-id <session>", "why": "cart: 1 open blocker finding(s) (first: …); fix it, commit, then close it", "actor": "agent" },
|
|
443
|
+
{ "command": "canon review add --project-id root --scenario-id cart.add.02 --reviewer <reviewer> --actor-id <reviewer> --session-id <review-session> --role reviewer --pin <sha> --original-spec-ref \"<feature file>\"", "why": "cart: 1 of 2 scenario(s) lack a qualifying review; …", "actor": "agent" },
|
|
444
|
+
{ "command": "canon status", "why": "1 scenario(s) carry no @subject tag (first: cart.promo.01); add `@subject:<id>` above each in its .feature file, then check again: …", "actor": "agent" }
|
|
330
445
|
],
|
|
331
446
|
"nextOmitted": 0
|
|
332
447
|
}
|
|
@@ -335,9 +450,22 @@ Status fails closed rather than suggest progress the gate would refuse:
|
|
|
335
450
|
Each `missingCases` entry is `{ "projectId", "surface", "case" }`: the
|
|
336
451
|
spec root, the `<area>.<surface>`, and the required case it lacks.
|
|
337
452
|
|
|
453
|
+
`brief` is present for `building`, `verifying` and `shipped` subjects,
|
|
454
|
+
and for a `proposed` subject whose newest adopted change has a
|
|
455
|
+
`proposal.md`. `change` is the newest adopted change (omitted when the
|
|
456
|
+
subject adopts none), `proposal` its `proposal.md` (omitted when no
|
|
457
|
+
`openspec` source holds one), `approval` the text after `Approved:`, and
|
|
458
|
+
`enforced` whether the missing approval blocks (a `proposal.md` exists to
|
|
459
|
+
carry it).
|
|
460
|
+
|
|
461
|
+
Each `next` entry's `actor` is `agent` (its `command` is a canon command
|
|
462
|
+
line) or `human` (its `command` says what to get from the human).
|
|
463
|
+
|
|
338
464
|
`policy.spec_coverage` has the shape `canon context --json` prints
|
|
339
465
|
(`null` when absent, `{"invalid": …}` when unusable). `statusVersion`
|
|
340
|
-
changes only when a field changes meaning or is removed.
|
|
466
|
+
changes only when a field changes meaning or is removed. It is `2`
|
|
467
|
+
since 0.16, when `next[].command` stopped always being a command line
|
|
468
|
+
(`actor` tells which); `brief` was added alongside.
|
|
341
469
|
|
|
342
470
|
`subject new`, `adopt` and `status` write their records directly; the
|
|
343
471
|
human-readable success line ends `— written directly; nothing to
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@journeykit/canon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.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.16.0",
|
|
34
|
+
"@journeykit/canon-core-linux-x64": "0.16.0",
|
|
35
|
+
"@journeykit/canon-core-win32-x64": "0.16.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^20.0.0",
|