wowbagger 0.1.0-alpha.9 → 0.5.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/CHANGELOG.md +509 -0
- package/README.md +272 -136
- package/docs/adapter-contract.md +1 -1
- package/docs/host-contract.md +7 -1
- package/docs/mutation-contract.md +354 -82
- package/docs/work-claim-contract.md +466 -88
- package/package.json +2 -2
- package/schemas/core-capabilities-response.json +1 -1
- package/schemas/core-envelope.json +4 -3
- package/schemas/index.json +18 -0
- package/schemas/ledger-repair-proposal.json +170 -0
- package/schemas/ledger-repair-request.json +61 -0
- package/schemas/ledger-repair-response.json +90 -0
- package/schemas/report-config-v1.json +4 -0
- package/schemas/report-config-v2.json +5 -0
- package/skills/wowbagger/SKILL.md +242 -59
- package/src/adapter/core-probe.js +3 -4
- package/src/adapter/process-outcome.js +8 -1
- package/src/claim-capabilities.js +3 -3
- package/src/claim-coordinator.js +61 -12
- package/src/claim-journal.js +212 -7
- package/src/claim-prospective.js +1 -28
- package/src/claim-publication.js +412 -78
- package/src/claim-request.js +9 -0
- package/src/claim-store.js +9 -4
- package/src/cli.js +302 -56
- package/src/extensions.js +1 -0
- package/src/git-autocommit.js +106 -43
- package/src/git-reconciliation.js +74 -19
- package/src/git-worktrees.js +73 -0
- package/src/instrumentation.js +1 -0
- package/src/launch.js +2 -2
- package/src/ledger-repair.js +1170 -0
- package/src/mutation.js +73 -15
- package/src/reconciliation-classifier.js +117 -0
- package/src/report-evidence.js +158 -41
- package/src/report-graph.js +201 -73
- package/src/report-html.js +358 -155
- package/src/report-impact.js +106 -0
- package/src/report-selection.js +97 -0
- package/src/report-sequencing.js +4 -4
- package/src/report-svg.js +74 -20
- package/src/report-view.js +14 -1
- package/src/report.js +109 -23
- package/src/version-drift.js +98 -0
- package/src/worktree-identity.js +165 -0
|
@@ -14,14 +14,18 @@ publish something.
|
|
|
14
14
|
Install the core separately before using this skill:
|
|
15
15
|
|
|
16
16
|
```sh
|
|
17
|
-
npm install -g wowbagger@0.
|
|
17
|
+
npm install -g wowbagger@0.5.0
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
The core requires Node.js
|
|
20
|
+
The core requires Node.js 24 or later. This plugin ships only agent
|
|
21
21
|
instructions; it does not bundle the core, an MCP server, a remote service, a
|
|
22
22
|
hook, or a background process. It operates on the ledger and its Git working
|
|
23
23
|
copy through the core's validated CLI.
|
|
24
24
|
|
|
25
|
+
The supported runtime matrix is Node 24.20.0. Node 26 remains excluded until
|
|
26
|
+
the separate Vitest incompatibility reported by Lee is resolved; do not certify
|
|
27
|
+
Node 26 based on ambient availability.
|
|
28
|
+
|
|
25
29
|
## Before anything else: check the core
|
|
26
30
|
|
|
27
31
|
This skill does **not** bundle the wowbagger core. It drives an installed one,
|
|
@@ -34,9 +38,9 @@ wowbagger capabilities --json
|
|
|
34
38
|
|
|
35
39
|
Read the plain distribution version from the first command and the top-level
|
|
36
40
|
`contract_version` from the second. **This skill requires distribution version
|
|
37
|
-
`0.
|
|
41
|
+
`0.5.0` and core `contract_version: 5`.**
|
|
38
42
|
|
|
39
|
-
The distribution pin names the published `0.
|
|
43
|
+
The distribution pin names the published `0.5.0` release; the cut that
|
|
40
44
|
publishes core `contract_version: 5` moves it. Earlier cores report
|
|
41
45
|
`contract_version: 3` or lower and lack behavior this skill requires, including
|
|
42
46
|
the bounded item source, so the version check refuses them. Do not soften
|
|
@@ -63,6 +67,17 @@ either pin to make a check pass.
|
|
|
63
67
|
Run both commands once per session before the first ledger command, not before
|
|
64
68
|
every command.
|
|
65
69
|
|
|
70
|
+
Run the read-only drift preflight before the first ledger mutation:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
wowbagger version-drift --json
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
It compares the installed skill pin with the required distribution and core
|
|
77
|
+
contract, then compares those requirements with the running core. If it refuses,
|
|
78
|
+
do not mutate the ledger. Update the stale package, plugin cache, or linked
|
|
79
|
+
checkout named by `result.error.details.provenance`, then rerun the preflight.
|
|
80
|
+
|
|
66
81
|
You drive the core as an agent, through the commands below. A UI plugin or
|
|
67
82
|
another non-agent consumer drives it as a process instead: absolute Node
|
|
68
83
|
executable, absolute `wowbagger.js`, argument array, `shell: false`. If the
|
|
@@ -131,8 +146,10 @@ the absolute `result.output`. On failure, require `ok: false` and inspect
|
|
|
131
146
|
publication preserves the prior report. Do not parse the generated HTML and do
|
|
132
147
|
not parse human output: the JSON result is the only machine surface.
|
|
133
148
|
|
|
134
|
-
The report
|
|
135
|
-
|
|
149
|
+
The report is one shared Items, Flow, and Dependencies workspace. The
|
|
150
|
+
Dependencies section holds the 3D dependency graph of the items the artifact
|
|
151
|
+
covers, under the same scope as Items and Flow. Its renderer is a pinned,
|
|
152
|
+
checksummed `3d-force-graph` build
|
|
136
153
|
vendored at `vendor/3d-force-graph/` and inlined at generation time, so the
|
|
137
154
|
report is still one self-contained file that fetches nothing — it is roughly
|
|
138
155
|
1.3 MB larger for it. A browser without WebGL shows the graph section's plain
|
|
@@ -184,6 +201,41 @@ work read as ready.
|
|
|
184
201
|
redaction and no access control. Say that plainly if a user asks for a report
|
|
185
202
|
that hides work from a reader.
|
|
186
203
|
|
|
204
|
+
## Every writer must be on the same core before the first create
|
|
205
|
+
|
|
206
|
+
On a provisioned ledger, `create` now records its allocation in the shared
|
|
207
|
+
claim journal before it publishes anything. That grammar is new, so the upgrade
|
|
208
|
+
is a hard cutover with no automatic migration and no mixed-version grace
|
|
209
|
+
period: **upgrade every writer in one Git coordination domain to the current
|
|
210
|
+
core before the first alpha.14 create.** A worktree left on the old core does
|
|
211
|
+
not write a duplicate — it stops making claim-protected mutations, which is the
|
|
212
|
+
safe outcome, not a usable one.
|
|
213
|
+
|
|
214
|
+
An old core cannot read the new create entry and says so badly. It answers
|
|
215
|
+
exit 6, `error.code` `claim-store-unavailable`, message
|
|
216
|
+
`The durable claim store is unavailable.`, and `error.details.reason`
|
|
217
|
+
`claim-store-unreadable`, leaves state unchanged, and writes no item. Read that
|
|
218
|
+
exact combination as **this repository was written by a newer Wowbagger;
|
|
219
|
+
upgrade this worktree to continue**, and say so to the user: the old binary is
|
|
220
|
+
immutable and can never print better guidance. (Item #185 is open for general
|
|
221
|
+
version-drift detection.)
|
|
222
|
+
|
|
223
|
+
Do not confuse that with a full journal. Exit 6
|
|
224
|
+
`claim-store-unavailable` with reason `journal-capacity-exceeded` means the
|
|
225
|
+
65,536-entry or 8,388,608-byte bound was reached before publication. State is
|
|
226
|
+
unchanged and prior history stays intact. Do not upgrade, truncate, compact, or
|
|
227
|
+
hand-edit the journal; no automatic recovery verb exists. Report the capacity
|
|
228
|
+
refusal as the blocker. A real persistence failure remains
|
|
229
|
+
`clock-floor-persistence-failed`, and uncertainty after an intent remains an
|
|
230
|
+
outcome-unknown refusal.
|
|
231
|
+
|
|
232
|
+
Say what the fix does and does not cover. It closes the reported
|
|
233
|
+
PropertyCompass2 collision: cooperating alpha.14 worktrees of one clone that
|
|
234
|
+
share one Git common directory can no longer commit two items carrying the same
|
|
235
|
+
number. Separate clones, separate machines, alpha.13 writers before the hard
|
|
236
|
+
cutover, and noncooperating writes stay outside that fence and still rely on
|
|
237
|
+
branch integration plus `validate`.
|
|
238
|
+
|
|
187
239
|
## Writing
|
|
188
240
|
|
|
189
241
|
Every write is an explicit, reviewable Git change. Show the user the command
|
|
@@ -232,7 +284,9 @@ wowbagger patch --ledger <dir> --input request.json --json
|
|
|
232
284
|
with a `patch` that brings the successor under the bound.
|
|
233
285
|
- `create` starts an empty ledger on schema version 2 and returns the selected
|
|
234
286
|
version at `result.item.core.schema_version`. A non-empty schema-version-1
|
|
235
|
-
ledger stays on version 1 until its complete ledger is migrated.
|
|
287
|
+
ledger stays on version 1 until its complete ledger is migrated. The create
|
|
288
|
+
request name `extensions` is reserved for the patch container; name extension
|
|
289
|
+
members directly on `item`.
|
|
236
290
|
- `transition` changes **one** item. If the change would require touching a
|
|
237
291
|
dependent or a child, it refuses. That refusal is correct — make it a
|
|
238
292
|
reviewable multi-file Git change instead of forcing it.
|
|
@@ -294,21 +348,30 @@ and `number` is refused because it is immutable identity.
|
|
|
294
348
|
are required, so a null one returns `candidate-invalid`, exit 2,
|
|
295
349
|
`unchanged`. Use `[]` for a list; send the corrected string for a title.
|
|
296
350
|
- `priority` takes a non-negative integer.
|
|
351
|
+
- For an item whose status is `done`, `killed`, `archived`, or `deferred`, the
|
|
352
|
+
request date must equal the existing `updated` date for `patch`, `snooze`, and
|
|
353
|
+
`parent-migrate`. Inspect immediately before the mutation and reuse that date;
|
|
354
|
+
an earlier date fails the request floor and a later date violates the
|
|
355
|
+
terminal-date invariant.
|
|
297
356
|
- Patch appends no decision; the Git diff is the audit trail. It never mutates
|
|
298
357
|
a second item, and it cannot touch status or provenance.
|
|
299
358
|
|
|
300
359
|
**Which fields are yours.** Do not discover this by sending a patch and reading
|
|
301
|
-
the refusal — every frontmatter member is in exactly one of
|
|
360
|
+
the refusal — every frontmatter member is in exactly one of four classes:
|
|
302
361
|
|
|
303
|
-
- **Core-owned**, never
|
|
304
|
-
`created`, `updated`, the terminal dates (`completed`, `killed`,
|
|
305
|
-
`deferred`), and `decisions`.
|
|
362
|
+
- **Core-owned**, never directly editable: `schema_version`, `id`, `number`,
|
|
363
|
+
`status`, `created`, `updated`, the terminal dates (`completed`, `killed`,
|
|
364
|
+
`archived`, `deferred`), and `decisions`. The core derives these through
|
|
365
|
+
lifecycle and mutation commands; `patch` cannot name them.
|
|
306
366
|
- **Consumer-editable through `patch`**: `title`, `priority`, `depends_on`,
|
|
307
367
|
`related`, the body, and every extension member the ledger declares.
|
|
308
|
-
- **
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
368
|
+
- **Dedicated mutations**: use `parent-migrate` to repoint an existing item to
|
|
369
|
+
an epic or detach it, and use `snooze` to set or clear `snoozed_until`. Both
|
|
370
|
+
use exact-revision compare-and-swap and accept `--auto-commit`.
|
|
371
|
+
- **Create-once**: `kind` and `provenance`. `kind` is refused deliberately — a
|
|
372
|
+
task-to-epic flip changes which parent and children rules apply and which
|
|
373
|
+
lifecycle edges are allowed, so it needs its own future verb, not a wider
|
|
374
|
+
`set`. Provenance remains byte-identical after create.
|
|
312
375
|
|
|
313
376
|
**Extension members are patchable only where the ledger declares them.**
|
|
314
377
|
`tags`, `tier`, and a consumer's own identifier fields are consumer-owned. Send
|
|
@@ -407,17 +470,26 @@ On a **provisioned** ledger (`claim capabilities` reports
|
|
|
407
470
|
```sh
|
|
408
471
|
wowbagger create --ledger <dir> --input request.json --json
|
|
409
472
|
git add <dir> && git commit -m "Record the mutation"
|
|
410
|
-
wowbagger claim-verify --ledger <dir> --json
|
|
473
|
+
wowbagger claim-verify --ledger <dir> --id <item> --json
|
|
411
474
|
wowbagger transition --ledger <dir> --input next.json --json
|
|
412
475
|
```
|
|
413
476
|
|
|
414
|
-
The claim store
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
477
|
+
The claim store reconciles every recorded mutation with Git `HEAD` and the
|
|
478
|
+
working tree. It refuses the next mutation when it finds an
|
|
479
|
+
`unauthorized-revision`, requires Git finalization, or requires synchronization
|
|
480
|
+
for the target item. A synchronization finding on an unrelated item remains
|
|
481
|
+
visible to targeted `claim-verify` without blocking that item.
|
|
482
|
+
|
|
483
|
+
One exact window is nonblocking: an existing item's latest authorized
|
|
484
|
+
working-tree bytes with an earlier authorized revision at `HEAD`. That
|
|
485
|
+
authorized predecessor/successor window produces no finding, so another
|
|
486
|
+
mutation can run before the first is committed. Do not mistake acceptance for
|
|
487
|
+
durability. Commit each mutation anyway, then run `claim-verify`.
|
|
488
|
+
|
|
489
|
+
`create` never gets that window. A new item has no earlier authorized revision,
|
|
490
|
+
so Git `HEAD` is the only place its authorized bytes can live, and an
|
|
491
|
+
uncommitted create blocks every later mutation — including the next create —
|
|
492
|
+
with `git-finalization-required`.
|
|
421
493
|
|
|
422
494
|
**`claim-verify` is the reconciliation procedure for that refusal.** Do not go
|
|
423
495
|
looking for another verb; there is none. Read `details.findings`, do exactly
|
|
@@ -425,30 +497,60 @@ what each finding's `remediation` string says (it names the path), run
|
|
|
425
497
|
`claim-verify` until it exits 0, then repeat the refused command. Never hand-
|
|
426
498
|
edit a ledger file to get past it.
|
|
427
499
|
|
|
428
|
-
For
|
|
429
|
-
|
|
500
|
+
For an existing ledger, bootstrap patch authority before managed corrections.
|
|
501
|
+
For standard tags, `declaration.json` is:
|
|
502
|
+
|
|
503
|
+
```json
|
|
504
|
+
{"members":{"tags":"string-list"}}
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
Review the proposal, then publish the same declaration:
|
|
430
508
|
|
|
431
509
|
```sh
|
|
432
510
|
wowbagger extensions-provision --ledger <dir> --input declaration.json --json --dry-run
|
|
433
511
|
wowbagger extensions-provision --ledger <dir> --input declaration.json --json
|
|
434
512
|
```
|
|
435
513
|
|
|
436
|
-
The request
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
514
|
+
The request names every selected member and type explicitly. The core requires
|
|
515
|
+
a valid complete ledger, validates every occurrence of each selected member,
|
|
516
|
+
and reports occurrence counts; a member need not appear on every item, but it
|
|
517
|
+
must appear at least once. Dry-run writes nothing. Publication creates one
|
|
518
|
+
canonical declaration without changing item bytes and refuses to overwrite a
|
|
519
|
+
different declaration. Commit only `.wowbagger/extensions.json`, inspect the
|
|
520
|
+
target again, then patch `set.extensions.tags`. A YAML anchor or alias on that
|
|
521
|
+
item still refuses `extension-anchored`.
|
|
440
522
|
|
|
441
|
-
To detach or reparent
|
|
523
|
+
To detach or reparent an item without recreating its identity, use the
|
|
442
524
|
CAS-fenced relation migration:
|
|
443
525
|
|
|
444
526
|
```sh
|
|
445
527
|
wowbagger parent-migrate --ledger <dir> --input relation.json --json [--auto-commit]
|
|
446
528
|
```
|
|
447
529
|
|
|
448
|
-
|
|
449
|
-
|
|
530
|
+
The parent-migrate request is:
|
|
531
|
+
|
|
532
|
+
```json
|
|
533
|
+
{"id":"wb_...","expected_revision":"sha256:...","expected_parent":"wb_...","parent":null,"date":"YYYY-MM-DD"}
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
Every member is required; `expected_parent` and `parent` may be `null`. Inspect
|
|
537
|
+
immediately before sending it. The complete ledger validates old and new parent
|
|
450
538
|
accounting before publication.
|
|
451
539
|
|
|
540
|
+
Set or clear a snooze date with:
|
|
541
|
+
|
|
542
|
+
```sh
|
|
543
|
+
wowbagger snooze --ledger <dir> --input snooze.json --json [--auto-commit]
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
The snooze request is:
|
|
547
|
+
|
|
548
|
+
```json
|
|
549
|
+
{"id":"wb_...","expected_revision":"sha256:...","snoozed_until":"YYYY-MM-DD","date":"YYYY-MM-DD"}
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
Use `snoozed_until: null` to clear it. Every member is required.
|
|
553
|
+
|
|
452
554
|
Successful mutation responses also return `result.changed_paths`: the exact
|
|
453
555
|
ledger-relative paths changed by that invocation. Use this set for manual
|
|
454
556
|
staging; never broaden it to `git add <ledger>` and never treat it as proof of
|
|
@@ -456,23 +558,40 @@ commit. With `--auto-commit`, `changed_paths` matches `commit_paths`, and
|
|
|
456
558
|
`git_commit` proves the commit.
|
|
457
559
|
|
|
458
560
|
Batch work is where this bites: filing ten items means ten commits, not one
|
|
459
|
-
commit at the end. Tell the user that before starting
|
|
561
|
+
commit at the end. Tell the user that before starting. There is permanently no
|
|
562
|
+
batch mutation in the direct-Markdown architecture. The create-then-commit loop,
|
|
563
|
+
implemented most briefly as serial `create --auto-commit` calls, is the
|
|
564
|
+
supported bulk path. Ledger item #186 records this permanent decision. Run calls in
|
|
565
|
+
request order and do not start the next until the previous result or recovery
|
|
566
|
+
is final.
|
|
460
567
|
|
|
461
568
|
### Or use --auto-commit and let one invocation do it
|
|
462
569
|
|
|
463
570
|
On a provisioned ledger, `--auto-commit` performs that whole loop inside one
|
|
464
|
-
invocation. It is accepted on `create`, `transition`, `
|
|
465
|
-
`publish-claimed`, once each, and only with the flag present — there
|
|
466
|
-
setting that turns it on for you.
|
|
571
|
+
invocation. It is accepted on `create`, `transition`, `parent-migrate`, `snooze`,
|
|
572
|
+
`patch`, and `publish-claimed`, once each, and only with the flag present — there
|
|
573
|
+
is no setting that turns it on for you.
|
|
467
574
|
|
|
468
575
|
```sh
|
|
469
576
|
wowbagger transition --ledger <dir> --input next.json --json --auto-commit
|
|
470
577
|
```
|
|
471
578
|
|
|
472
|
-
One flagged invocation refuses if anything is staged anywhere or any
|
|
473
|
-
the ledger is dirty, reconciles, runs the mutation unchanged,
|
|
474
|
-
the changed item plus at most one
|
|
475
|
-
fixed subject, verifies that commit,
|
|
579
|
+
One flagged invocation refuses if anything is staged anywhere or any foreign
|
|
580
|
+
path under the ledger is dirty, reconciles, runs the mutation unchanged,
|
|
581
|
+
commits exactly the changed item plus at most one
|
|
582
|
+
`.wowbagger/reconcile-<namespace>.md` with a fixed subject, verifies that commit,
|
|
583
|
+
and runs `claim-verify` before it answers. A successful `create --auto-commit`
|
|
584
|
+
commits exactly two paths: the created item and that reconciliation log. Every
|
|
585
|
+
command rebuilds its own derived reconciliation log during preflight, but
|
|
586
|
+
`create` refuses a log that was already dirty when you invoked it, and every
|
|
587
|
+
other dirty ledger path still refuses.
|
|
588
|
+
|
|
589
|
+
Preflight and post-commit reconciliation block findings for the requested item.
|
|
590
|
+
An unrelated `worktree-synchronization-required` finding remains visible to
|
|
591
|
+
`claim-verify` without turning a successful mutation into failure. If claim
|
|
592
|
+
verification refuses, the result preserves `claim_verify_code` and
|
|
593
|
+
`claim_verify_reason`; only `claim-store-locked` is retryable.
|
|
594
|
+
|
|
476
595
|
Success adds `git_commit`, `commit_paths`, and `claim_verified` to `result`.
|
|
477
596
|
|
|
478
597
|
Say these limits plainly when you use it:
|
|
@@ -535,7 +654,7 @@ wowbagger provision --ledger <dir> --json
|
|
|
535
654
|
wowbagger claim capabilities --ledger <dir> --json
|
|
536
655
|
wowbagger claim read|acquire|renew|release --ledger <dir> --input request.json --json
|
|
537
656
|
wowbagger publish-claimed --ledger <dir> --input request.json --json [--auto-commit]
|
|
538
|
-
wowbagger claim-verify --ledger <dir> --json
|
|
657
|
+
wowbagger claim-verify --ledger <dir> [--id <item>] --json
|
|
539
658
|
wowbagger claim-sync --ledger <dir> --json
|
|
540
659
|
wowbagger claim-merge-verify --ledger <dir> --base <ref> --head <ref> --json
|
|
541
660
|
```
|
|
@@ -565,26 +684,84 @@ envelope's `limits.cross_worktree_coordination: false` as permission to write
|
|
|
565
684
|
with hostile or noncooperating tools — it only says the core never synchronizes
|
|
566
685
|
checkouts.
|
|
567
686
|
|
|
568
|
-
A recorded `transition`, `patch`, or claimed publication blocks
|
|
569
|
-
targeting that same item with exit 6 `claim-store-unavailable`,
|
|
570
|
-
`publication-reconciliation-required`. An unrelated item mutation may
|
|
571
|
-
when the only finding is `worktree-synchronization-required`.
|
|
572
|
-
|
|
687
|
+
A recorded `create`, `transition`, `patch`, or claimed publication blocks
|
|
688
|
+
mutations targeting that same item with exit 6 `claim-store-unavailable`,
|
|
689
|
+
reason `publication-reconciliation-required`. An unrelated item mutation may
|
|
690
|
+
proceed when the only finding is `worktree-synchronization-required`.
|
|
691
|
+
|
|
692
|
+
`create` is the one exception to that scoping, because it allocates the next
|
|
693
|
+
number from the items this checkout can see. It also refuses when the journal
|
|
694
|
+
records a committed item this worktree does not hold at all: that item carries
|
|
695
|
+
a number nobody here can read, so the next number allocated here might already
|
|
696
|
+
be taken. A stale revision of an item this worktree does hold is not a blocker
|
|
697
|
+
for `create` — a number is immutable, so the local maximum is still right. The
|
|
698
|
+
refusal is the same exit 6 `claim-store-unavailable` with reason
|
|
699
|
+
`publication-reconciliation-required`, state `unchanged`, and no item file
|
|
700
|
+
written; integrate the missing item, run `claim-verify` until it exits 0, and
|
|
701
|
+
resend the same request, which then takes the next number.
|
|
702
|
+
|
|
703
|
+
That fence stops new collisions; it does not repair old ones through core
|
|
704
|
+
version 5 or claim operations. Existing duplicate numbers are item #182
|
|
705
|
+
recovery work. Use the separate `ledger-repair` contract:
|
|
706
|
+
`number-repair-proposal --ledger <dir> --json` is read-only and writes no item
|
|
707
|
+
file; `number-repair --ledger <dir> --input <repair.json> --json` applies a
|
|
708
|
+
reviewed complete mapping under the shared namespace fence. Number-only repair
|
|
709
|
+
preserves ULID identities and relation values. Never hand-edit the ledger:
|
|
710
|
+
arbitrary edits can damage IDs, paths, or references.
|
|
573
711
|
|
|
574
712
|
Read `error.details.findings[0].reason` and act on the named item:
|
|
575
713
|
|
|
576
714
|
- `git-finalization-required` — you wrote the item here and have not committed.
|
|
577
715
|
Commit, then `claim-verify`.
|
|
578
|
-
- `worktree-synchronization-required` — another worktree wrote the item.
|
|
716
|
+
- `worktree-synchronization-required` — another worktree wrote the item.
|
|
717
|
+
`owner_ref` names an **active named worktree** and nothing else: it is always
|
|
718
|
+
the branch of a live worktree that carries the expected revision. If the
|
|
579
719
|
finding names `owner_ref` and `owner_commit`, WAIT for that owner to publish,
|
|
580
|
-
then synchronize this checkout and run `claim-verify`.
|
|
581
|
-
`
|
|
582
|
-
|
|
720
|
+
then synchronize this checkout and run `claim-verify`. `owner_unavailable:
|
|
721
|
+
true` means no such worktree exists, and it covers three cases: the expected
|
|
722
|
+
revision is not reachable at all, a live sibling holds it on a detached
|
|
723
|
+
`HEAD`, or it is reachable only from a tag, a remote-tracking ref, or a
|
|
724
|
+
branch no worktree has checked out. Reachability is not ownership; a ref you
|
|
725
|
+
can see is not a worktree that can publish. Follow the `remediation`, which
|
|
726
|
+
separates those cases. A revision that is **not yet reachable** means WAIT for
|
|
727
|
+
the owning worktree to commit, then synchronize. A revision that is
|
|
728
|
+
**reachable in Git while no active named worktree owner is established** —
|
|
729
|
+
a tag, a remote-tracking ref, an unchecked-out branch, or a detached sibling
|
|
730
|
+
carries it — is not a wait at all: inspect that reachable history, then
|
|
731
|
+
restore the authorized bytes or use explicit `claim-adopt` after review.
|
|
732
|
+
Ownership that **cannot be established from reachable refs** — the item has
|
|
733
|
+
never existed in this checkout — calls for inspecting reachable or dangling
|
|
734
|
+
commits with the same explicit restore or `claim-adopt`. Never merge unrelated
|
|
735
|
+
live work.
|
|
583
736
|
- `unauthorized-revision` — the item changed outside the protocol. Two remedies
|
|
584
737
|
are explicit: **restore** the authorized revision and run `claim-verify` to
|
|
585
738
|
discard the edit, or **adopt** the committed revision and run `claim-verify`
|
|
586
739
|
to keep it. Ask before discarding reviewed work.
|
|
587
740
|
|
|
741
|
+
Two live worktrees answering to one identity, or a worktree roster the
|
|
742
|
+
coordinator could not finish reading, refuse before anything is classified.
|
|
743
|
+
You get exit 6 `claim-store-unavailable`, reason `claim-store-unreadable`, with
|
|
744
|
+
`error.details.identity_diagnostic`: `duplicate-worktree-identity` naming the
|
|
745
|
+
`worktree_id` and `live_worktree_count`, or `worktree-enumeration-failed` with
|
|
746
|
+
no further member. Auto-commit reports the same diagnostic inside
|
|
747
|
+
`auto-commit-preflight-failed` with `retryable: false`. Neither is retryable
|
|
748
|
+
and neither is yours to repair by editing files. Report the diagnostic verbatim,
|
|
749
|
+
including the `worktree_id` and `live_worktree_count`: a duplicate means two
|
|
750
|
+
live worktrees hold the same identity file, usually because a private Git
|
|
751
|
+
directory was copied, and which worktree keeps the UUID is a person's decision.
|
|
752
|
+
An enumeration failure means a registered worktree path could not be read. The
|
|
753
|
+
identity itself is an opaque UUID a worktree writes once into its private Git
|
|
754
|
+
directory. Never create, copy, or edit it.
|
|
755
|
+
|
|
756
|
+
**Choose verification scope deliberately.** Bare
|
|
757
|
+
`claim-verify --ledger <dir> --json` is strict repository diagnosis: any
|
|
758
|
+
blocking finding anywhere keeps it at exit 6. After working one item, use
|
|
759
|
+
`claim-verify --ledger <dir> --id <item> --json`. It keeps every repository
|
|
760
|
+
finding visible and marks each with `blocks_verification_scope`, but unrelated
|
|
761
|
+
target-scoped findings do not fail that item's gate. Global barriers still
|
|
762
|
+
fail every target. Never adopt or hand-edit a sibling's item to force either
|
|
763
|
+
scope clean.
|
|
764
|
+
|
|
588
765
|
Adoption is per item and per revision explicit. Name the item and both
|
|
589
766
|
revisions, take them from the finding, and commit the edited bytes first:
|
|
590
767
|
|
|
@@ -626,7 +803,7 @@ Use the claimed write path as one complete loop:
|
|
|
626
803
|
not in an accessible Git checkout. Stop before mutation.
|
|
627
804
|
2. Run `provision` once for the ledger. Keep its `ledger_namespace`.
|
|
628
805
|
3. Run `claim capabilities --ledger <dir> --json` again. Require
|
|
629
|
-
`result.operations.work_claim.api_version:
|
|
806
|
+
`result.operations.work_claim.api_version: 3`. Do not compare the claim
|
|
630
807
|
response's top-level `contract_version` with the core version; it is the
|
|
631
808
|
legacy claim-envelope marker. Stop if the namespace is absent or the mode is
|
|
632
809
|
not `merge-coordinated`.
|
|
@@ -638,12 +815,15 @@ Use the claimed write path as one complete loop:
|
|
|
638
815
|
revision, the candidate bytes and digest, and the active claim fence. Never
|
|
639
816
|
retry with only the operation ID; retry the complete request.
|
|
640
817
|
8. Commit the item change, or merge the worker commit into the coordinating
|
|
641
|
-
branch. Do this now, not at the end of a batch
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
818
|
+
branch. Do this now, not at the end of a batch. Acceptance of another command
|
|
819
|
+
does not prove this mutation is durable, and a blocking finding still
|
|
820
|
+
refuses that command.
|
|
821
|
+
9. Run `claim-verify --ledger <dir> --id <item> --json` after the commit or
|
|
822
|
+
merge. It finalizes the Git outcome, repairs response-loss cases, and reports
|
|
823
|
+
later revision drift. Require exit 0 before the next mutating command; exit
|
|
824
|
+
6 means findings block this item, so act on each blocking finding's
|
|
825
|
+
`remediation` and run it again. Unrelated nonblocking findings remain
|
|
826
|
+
visible for repository diagnosis.
|
|
647
827
|
10. Release the claim with its current observed state.
|
|
648
828
|
11. Run `validate` and show the resulting diff.
|
|
649
829
|
|
|
@@ -666,8 +846,11 @@ response envelopes, refusal precedence, and recovery rules.
|
|
|
666
846
|
6. `validate`, then show the diff.
|
|
667
847
|
7. On a provisioned ledger, commit the ledger change now:
|
|
668
848
|
`git add <dir> && git commit`.
|
|
669
|
-
8. On a provisioned ledger, run
|
|
670
|
-
|
|
849
|
+
8. On a provisioned ledger, run
|
|
850
|
+
`claim-verify --ledger <dir> --id <item> --json` and require exit 0 before
|
|
851
|
+
the next `create`, `transition`, `parent-migrate`, `snooze`, `patch`, or
|
|
852
|
+
`publish-claimed`. Use bare verification separately for strict
|
|
853
|
+
repository-wide diagnosis.
|
|
671
854
|
|
|
672
855
|
Write, commit, `claim-verify`, next write. The unclaimed loop obeys the same
|
|
673
856
|
rule as the claimed one, because both run through the same coordinator. Steps 7
|
|
@@ -19,10 +19,9 @@ export const CORE_COMMAND_ORDER = Object.freeze([
|
|
|
19
19
|
'capabilities', 'create', 'inspect', 'patch', 'ready', 'transition', 'validate',
|
|
20
20
|
]);
|
|
21
21
|
export const CORE_CONTRACT_VERSION = 5;
|
|
22
|
-
//
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
export const WORK_CLAIM_API_VERSION = 2;
|
|
22
|
+
// Work-claim API lives in its own version domain. Version 3 adds optional
|
|
23
|
+
// target-scoped claim verification while preserving strict bare verification.
|
|
24
|
+
export const WORK_CLAIM_API_VERSION = 3;
|
|
26
25
|
// The report configuration versions this core accepts. Version 1 remains
|
|
27
26
|
// supported unchanged; version 2 names views.
|
|
28
27
|
export const REPORT_CONFIG_VERSIONS = Object.freeze([1, 2]);
|
|
@@ -18,6 +18,13 @@ const WOWBAGGER_ID = /^wb_[0-7][0-9A-HJKMNP-TV-Z]{25}$/;
|
|
|
18
18
|
const NAMESPACE_ID = /^wbns_[a-f0-9]{32}$/;
|
|
19
19
|
const CANONICAL_UINT64 = /^(0|[1-9][0-9]*)$/;
|
|
20
20
|
const CONTROL_CHARACTER = /[\u0000-\u001F\u007F]/;
|
|
21
|
+
const LOCK_OWNER_OPERATIONS = new Set([
|
|
22
|
+
'create',
|
|
23
|
+
'transition',
|
|
24
|
+
'parent-migrate',
|
|
25
|
+
'snooze',
|
|
26
|
+
'patch',
|
|
27
|
+
]);
|
|
21
28
|
const MESSAGES = Object.freeze({
|
|
22
29
|
'mutation-outcome-unknown': 'The mutation may have been applied; inspect current state before retrying.',
|
|
23
30
|
'output-limit-exceeded': 'The core output exceeded the requested bound.',
|
|
@@ -1133,7 +1140,7 @@ function validLockHeldDetails(value) {
|
|
|
1133
1140
|
&& hasExactMembers(value.owner, ['lock_version', 'item_id', 'operation', 'writer_id', 'started_at'])
|
|
1134
1141
|
&& value.owner.lock_version === 1
|
|
1135
1142
|
&& value.owner.item_id === value.id
|
|
1136
|
-
&&
|
|
1143
|
+
&& LOCK_OWNER_OPERATIONS.has(value.owner.operation)
|
|
1137
1144
|
&& typeof value.owner.writer_id === 'string'
|
|
1138
1145
|
&& /^[\x21-\x7e]{1,128}$/.test(value.owner.writer_id)
|
|
1139
1146
|
&& isCoreRfc3339Utc(value.owner.started_at);
|
|
@@ -2,7 +2,7 @@ export function resolveWorkClaimCapability({ gitCommonDir, namespace = null }) {
|
|
|
2
2
|
if (!gitCommonDir) {
|
|
3
3
|
return {
|
|
4
4
|
supported: false,
|
|
5
|
-
api_version:
|
|
5
|
+
api_version: 3,
|
|
6
6
|
mode: 'advisory',
|
|
7
7
|
claim_protected_publication: false,
|
|
8
8
|
fencing_enforced_at: 'none',
|
|
@@ -12,7 +12,7 @@ export function resolveWorkClaimCapability({ gitCommonDir, namespace = null }) {
|
|
|
12
12
|
if (!namespace) {
|
|
13
13
|
return {
|
|
14
14
|
supported: true,
|
|
15
|
-
api_version:
|
|
15
|
+
api_version: 3,
|
|
16
16
|
mode: 'advisory',
|
|
17
17
|
claim_protected_publication: false,
|
|
18
18
|
fencing_enforced_at: 'none',
|
|
@@ -21,7 +21,7 @@ export function resolveWorkClaimCapability({ gitCommonDir, namespace = null }) {
|
|
|
21
21
|
}
|
|
22
22
|
return {
|
|
23
23
|
supported: true,
|
|
24
|
-
api_version:
|
|
24
|
+
api_version: 3,
|
|
25
25
|
mode: 'merge-coordinated',
|
|
26
26
|
claim_protected_publication: true,
|
|
27
27
|
fencing_enforced_at: 'git-history-reconciliation',
|