wowbagger 0.1.0-alpha.8 → 0.5.0-beta.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 +470 -0
- package/README.md +220 -79
- package/assets/wowbagger-v1-more-whimsical.jpg +0 -0
- package/assets/wowbagger-v2-less-whimsical.jpg +0 -0
- package/assets/wowbagger-v3-herding-agent-cats.jpg +0 -0
- package/assets/wowbagger-v4-robot-agent-herding.jpg +0 -0
- package/assets/wowbagger-v5-typing-cats-circuit-staff.jpg +0 -0
- 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 +8 -3
- 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/skills/wowbagger/SKILL.md +250 -56
- 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.js +11 -2
- package/src/version-drift.js +98 -0
- package/src/worktree-identity.js +165 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: wowbagger
|
|
3
|
-
description: Use when coordinating work through a
|
|
3
|
+
description: Use when coordinating work through a Wowbagger ledger — reading deterministic ready work, inspecting lossless revisions, generating HTML reports and named views, filing or mutating items, taking a work claim, or publishing claimed work. Triggers on "ready queue", "ledger report", "report view", "backlog report", "what should I work on", "file a ledger item", "close this item", "claim this work", "publish claimed work", or any mention of a Wowbagger ledger. Not for general backlog talk where no Wowbagger ledger exists.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Wowbagger
|
|
@@ -9,6 +9,23 @@ A work ledger that is plain Markdown in Git. Every item is a file; every change
|
|
|
9
9
|
is a reviewable diff. The core is read-only unless you explicitly ask it to
|
|
10
10
|
publish something.
|
|
11
11
|
|
|
12
|
+
## Setup
|
|
13
|
+
|
|
14
|
+
Install the core separately before using this skill:
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm install -g wowbagger@0.5.0-beta.0
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The core requires Node.js 24 or later. This plugin ships only agent
|
|
21
|
+
instructions; it does not bundle the core, an MCP server, a remote service, a
|
|
22
|
+
hook, or a background process. It operates on the ledger and its Git working
|
|
23
|
+
copy through the core's validated CLI.
|
|
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
|
+
|
|
12
29
|
## Before anything else: check the core
|
|
13
30
|
|
|
14
31
|
This skill does **not** bundle the wowbagger core. It drives an installed one,
|
|
@@ -21,9 +38,9 @@ wowbagger capabilities --json
|
|
|
21
38
|
|
|
22
39
|
Read the plain distribution version from the first command and the top-level
|
|
23
40
|
`contract_version` from the second. **This skill requires distribution version
|
|
24
|
-
`0.
|
|
41
|
+
`0.5.0-beta.0` and core `contract_version: 5`.**
|
|
25
42
|
|
|
26
|
-
The distribution pin names the published `0.
|
|
43
|
+
The distribution pin names the published `0.5.0-beta.0` release; the cut that
|
|
27
44
|
publishes core `contract_version: 5` moves it. Earlier cores report
|
|
28
45
|
`contract_version: 3` or lower and lack behavior this skill requires, including
|
|
29
46
|
the bounded item source, so the version check refuses them. Do not soften
|
|
@@ -50,6 +67,17 @@ either pin to make a check pass.
|
|
|
50
67
|
Run both commands once per session before the first ledger command, not before
|
|
51
68
|
every command.
|
|
52
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
|
+
|
|
53
81
|
You drive the core as an agent, through the commands below. A UI plugin or
|
|
54
82
|
another non-agent consumer drives it as a process instead: absolute Node
|
|
55
83
|
executable, absolute `wowbagger.js`, argument array, `shell: false`. If the
|
|
@@ -171,6 +199,41 @@ work read as ready.
|
|
|
171
199
|
redaction and no access control. Say that plainly if a user asks for a report
|
|
172
200
|
that hides work from a reader.
|
|
173
201
|
|
|
202
|
+
## Every writer must be on the same core before the first create
|
|
203
|
+
|
|
204
|
+
On a provisioned ledger, `create` now records its allocation in the shared
|
|
205
|
+
claim journal before it publishes anything. That grammar is new, so the upgrade
|
|
206
|
+
is a hard cutover with no automatic migration and no mixed-version grace
|
|
207
|
+
period: **upgrade every writer in one Git coordination domain to the current
|
|
208
|
+
core before the first alpha.14 create.** A worktree left on the old core does
|
|
209
|
+
not write a duplicate — it stops making claim-protected mutations, which is the
|
|
210
|
+
safe outcome, not a usable one.
|
|
211
|
+
|
|
212
|
+
An old core cannot read the new create entry and says so badly. It answers
|
|
213
|
+
exit 6, `error.code` `claim-store-unavailable`, message
|
|
214
|
+
`The durable claim store is unavailable.`, and `error.details.reason`
|
|
215
|
+
`claim-store-unreadable`, leaves state unchanged, and writes no item. Read that
|
|
216
|
+
exact combination as **this repository was written by a newer Wowbagger;
|
|
217
|
+
upgrade this worktree to continue**, and say so to the user: the old binary is
|
|
218
|
+
immutable and can never print better guidance. (Item #185 is open for general
|
|
219
|
+
version-drift detection.)
|
|
220
|
+
|
|
221
|
+
Do not confuse that with a full journal. Exit 6
|
|
222
|
+
`claim-store-unavailable` with reason `journal-capacity-exceeded` means the
|
|
223
|
+
65,536-entry or 8,388,608-byte bound was reached before publication. State is
|
|
224
|
+
unchanged and prior history stays intact. Do not upgrade, truncate, compact, or
|
|
225
|
+
hand-edit the journal; no automatic recovery verb exists. Report the capacity
|
|
226
|
+
refusal as the blocker. A real persistence failure remains
|
|
227
|
+
`clock-floor-persistence-failed`, and uncertainty after an intent remains an
|
|
228
|
+
outcome-unknown refusal.
|
|
229
|
+
|
|
230
|
+
Say what the fix does and does not cover. It closes the reported
|
|
231
|
+
PropertyCompass2 collision: cooperating alpha.14 worktrees of one clone that
|
|
232
|
+
share one Git common directory can no longer commit two items carrying the same
|
|
233
|
+
number. Separate clones, separate machines, alpha.13 writers before the hard
|
|
234
|
+
cutover, and noncooperating writes stay outside that fence and still rely on
|
|
235
|
+
branch integration plus `validate`.
|
|
236
|
+
|
|
174
237
|
## Writing
|
|
175
238
|
|
|
176
239
|
Every write is an explicit, reviewable Git change. Show the user the command
|
|
@@ -219,7 +282,9 @@ wowbagger patch --ledger <dir> --input request.json --json
|
|
|
219
282
|
with a `patch` that brings the successor under the bound.
|
|
220
283
|
- `create` starts an empty ledger on schema version 2 and returns the selected
|
|
221
284
|
version at `result.item.core.schema_version`. A non-empty schema-version-1
|
|
222
|
-
ledger stays on version 1 until its complete ledger is migrated.
|
|
285
|
+
ledger stays on version 1 until its complete ledger is migrated. The create
|
|
286
|
+
request name `extensions` is reserved for the patch container; name extension
|
|
287
|
+
members directly on `item`.
|
|
223
288
|
- `transition` changes **one** item. If the change would require touching a
|
|
224
289
|
dependent or a child, it refuses. That refusal is correct — make it a
|
|
225
290
|
reviewable multi-file Git change instead of forcing it.
|
|
@@ -281,21 +346,30 @@ and `number` is refused because it is immutable identity.
|
|
|
281
346
|
are required, so a null one returns `candidate-invalid`, exit 2,
|
|
282
347
|
`unchanged`. Use `[]` for a list; send the corrected string for a title.
|
|
283
348
|
- `priority` takes a non-negative integer.
|
|
349
|
+
- For an item whose status is `done`, `killed`, `archived`, or `deferred`, the
|
|
350
|
+
request date must equal the existing `updated` date for `patch`, `snooze`, and
|
|
351
|
+
`parent-migrate`. Inspect immediately before the mutation and reuse that date;
|
|
352
|
+
an earlier date fails the request floor and a later date violates the
|
|
353
|
+
terminal-date invariant.
|
|
284
354
|
- Patch appends no decision; the Git diff is the audit trail. It never mutates
|
|
285
355
|
a second item, and it cannot touch status or provenance.
|
|
286
356
|
|
|
287
357
|
**Which fields are yours.** Do not discover this by sending a patch and reading
|
|
288
|
-
the refusal — every frontmatter member is in exactly one of
|
|
358
|
+
the refusal — every frontmatter member is in exactly one of four classes:
|
|
289
359
|
|
|
290
|
-
- **Core-owned**, never
|
|
291
|
-
`created`, `updated`, the terminal dates (`completed`, `killed`,
|
|
292
|
-
`deferred`), and `decisions`.
|
|
360
|
+
- **Core-owned**, never directly editable: `schema_version`, `id`, `number`,
|
|
361
|
+
`status`, `created`, `updated`, the terminal dates (`completed`, `killed`,
|
|
362
|
+
`archived`, `deferred`), and `decisions`. The core derives these through
|
|
363
|
+
lifecycle and mutation commands; `patch` cannot name them.
|
|
293
364
|
- **Consumer-editable through `patch`**: `title`, `priority`, `depends_on`,
|
|
294
365
|
`related`, the body, and every extension member the ledger declares.
|
|
295
|
-
- **
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
366
|
+
- **Dedicated mutations**: use `parent-migrate` to repoint an existing item to
|
|
367
|
+
an epic or detach it, and use `snooze` to set or clear `snoozed_until`. Both
|
|
368
|
+
use exact-revision compare-and-swap and accept `--auto-commit`.
|
|
369
|
+
- **Create-once**: `kind` and `provenance`. `kind` is refused deliberately — a
|
|
370
|
+
task-to-epic flip changes which parent and children rules apply and which
|
|
371
|
+
lifecycle edges are allowed, so it needs its own future verb, not a wider
|
|
372
|
+
`set`. Provenance remains byte-identical after create.
|
|
299
373
|
|
|
300
374
|
**Extension members are patchable only where the ledger declares them.**
|
|
301
375
|
`tags`, `tier`, and a consumer's own identifier fields are consumer-owned. Send
|
|
@@ -394,17 +468,26 @@ On a **provisioned** ledger (`claim capabilities` reports
|
|
|
394
468
|
```sh
|
|
395
469
|
wowbagger create --ledger <dir> --input request.json --json
|
|
396
470
|
git add <dir> && git commit -m "Record the mutation"
|
|
397
|
-
wowbagger claim-verify --ledger <dir> --json
|
|
471
|
+
wowbagger claim-verify --ledger <dir> --id <item> --json
|
|
398
472
|
wowbagger transition --ledger <dir> --input next.json --json
|
|
399
473
|
```
|
|
400
474
|
|
|
401
|
-
The claim store
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
475
|
+
The claim store reconciles every recorded mutation with Git `HEAD` and the
|
|
476
|
+
working tree. It refuses the next mutation when it finds an
|
|
477
|
+
`unauthorized-revision`, requires Git finalization, or requires synchronization
|
|
478
|
+
for the target item. A synchronization finding on an unrelated item remains
|
|
479
|
+
visible to targeted `claim-verify` without blocking that item.
|
|
480
|
+
|
|
481
|
+
One exact window is nonblocking: an existing item's latest authorized
|
|
482
|
+
working-tree bytes with an earlier authorized revision at `HEAD`. That
|
|
483
|
+
authorized predecessor/successor window produces no finding, so another
|
|
484
|
+
mutation can run before the first is committed. Do not mistake acceptance for
|
|
485
|
+
durability. Commit each mutation anyway, then run `claim-verify`.
|
|
486
|
+
|
|
487
|
+
`create` never gets that window. A new item has no earlier authorized revision,
|
|
488
|
+
so Git `HEAD` is the only place its authorized bytes can live, and an
|
|
489
|
+
uncommitted create blocks every later mutation — including the next create —
|
|
490
|
+
with `git-finalization-required`.
|
|
408
491
|
|
|
409
492
|
**`claim-verify` is the reconciliation procedure for that refusal.** Do not go
|
|
410
493
|
looking for another verb; there is none. Read `details.findings`, do exactly
|
|
@@ -412,30 +495,60 @@ what each finding's `remediation` string says (it names the path), run
|
|
|
412
495
|
`claim-verify` until it exits 0, then repeat the refused command. Never hand-
|
|
413
496
|
edit a ledger file to get past it.
|
|
414
497
|
|
|
415
|
-
For
|
|
416
|
-
|
|
498
|
+
For an existing ledger, bootstrap patch authority before managed corrections.
|
|
499
|
+
For standard tags, `declaration.json` is:
|
|
500
|
+
|
|
501
|
+
```json
|
|
502
|
+
{"members":{"tags":"string-list"}}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
Review the proposal, then publish the same declaration:
|
|
417
506
|
|
|
418
507
|
```sh
|
|
419
508
|
wowbagger extensions-provision --ledger <dir> --input declaration.json --json --dry-run
|
|
420
509
|
wowbagger extensions-provision --ledger <dir> --input declaration.json --json
|
|
421
510
|
```
|
|
422
511
|
|
|
423
|
-
The request
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
512
|
+
The request names every selected member and type explicitly. The core requires
|
|
513
|
+
a valid complete ledger, validates every occurrence of each selected member,
|
|
514
|
+
and reports occurrence counts; a member need not appear on every item, but it
|
|
515
|
+
must appear at least once. Dry-run writes nothing. Publication creates one
|
|
516
|
+
canonical declaration without changing item bytes and refuses to overwrite a
|
|
517
|
+
different declaration. Commit only `.wowbagger/extensions.json`, inspect the
|
|
518
|
+
target again, then patch `set.extensions.tags`. A YAML anchor or alias on that
|
|
519
|
+
item still refuses `extension-anchored`.
|
|
427
520
|
|
|
428
|
-
To detach or reparent
|
|
521
|
+
To detach or reparent an item without recreating its identity, use the
|
|
429
522
|
CAS-fenced relation migration:
|
|
430
523
|
|
|
431
524
|
```sh
|
|
432
525
|
wowbagger parent-migrate --ledger <dir> --input relation.json --json [--auto-commit]
|
|
433
526
|
```
|
|
434
527
|
|
|
435
|
-
|
|
436
|
-
|
|
528
|
+
The parent-migrate request is:
|
|
529
|
+
|
|
530
|
+
```json
|
|
531
|
+
{"id":"wb_...","expected_revision":"sha256:...","expected_parent":"wb_...","parent":null,"date":"YYYY-MM-DD"}
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
Every member is required; `expected_parent` and `parent` may be `null`. Inspect
|
|
535
|
+
immediately before sending it. The complete ledger validates old and new parent
|
|
437
536
|
accounting before publication.
|
|
438
537
|
|
|
538
|
+
Set or clear a snooze date with:
|
|
539
|
+
|
|
540
|
+
```sh
|
|
541
|
+
wowbagger snooze --ledger <dir> --input snooze.json --json [--auto-commit]
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
The snooze request is:
|
|
545
|
+
|
|
546
|
+
```json
|
|
547
|
+
{"id":"wb_...","expected_revision":"sha256:...","snoozed_until":"YYYY-MM-DD","date":"YYYY-MM-DD"}
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
Use `snoozed_until: null` to clear it. Every member is required.
|
|
551
|
+
|
|
439
552
|
Successful mutation responses also return `result.changed_paths`: the exact
|
|
440
553
|
ledger-relative paths changed by that invocation. Use this set for manual
|
|
441
554
|
staging; never broaden it to `git add <ledger>` and never treat it as proof of
|
|
@@ -443,23 +556,40 @@ commit. With `--auto-commit`, `changed_paths` matches `commit_paths`, and
|
|
|
443
556
|
`git_commit` proves the commit.
|
|
444
557
|
|
|
445
558
|
Batch work is where this bites: filing ten items means ten commits, not one
|
|
446
|
-
commit at the end. Tell the user that before starting
|
|
559
|
+
commit at the end. Tell the user that before starting. There is permanently no
|
|
560
|
+
batch mutation in the direct-Markdown architecture. The create-then-commit loop,
|
|
561
|
+
implemented most briefly as serial `create --auto-commit` calls, is the
|
|
562
|
+
supported bulk path. Ledger item #186 records this permanent decision. Run calls in
|
|
563
|
+
request order and do not start the next until the previous result or recovery
|
|
564
|
+
is final.
|
|
447
565
|
|
|
448
566
|
### Or use --auto-commit and let one invocation do it
|
|
449
567
|
|
|
450
568
|
On a provisioned ledger, `--auto-commit` performs that whole loop inside one
|
|
451
|
-
invocation. It is accepted on `create`, `transition`, `
|
|
452
|
-
`publish-claimed`, once each, and only with the flag present — there
|
|
453
|
-
setting that turns it on for you.
|
|
569
|
+
invocation. It is accepted on `create`, `transition`, `parent-migrate`, `snooze`,
|
|
570
|
+
`patch`, and `publish-claimed`, once each, and only with the flag present — there
|
|
571
|
+
is no setting that turns it on for you.
|
|
454
572
|
|
|
455
573
|
```sh
|
|
456
574
|
wowbagger transition --ledger <dir> --input next.json --json --auto-commit
|
|
457
575
|
```
|
|
458
576
|
|
|
459
|
-
One flagged invocation refuses if anything is staged anywhere or any
|
|
460
|
-
the ledger is dirty, reconciles, runs the mutation unchanged,
|
|
461
|
-
the changed item plus at most one
|
|
462
|
-
fixed subject, verifies that commit,
|
|
577
|
+
One flagged invocation refuses if anything is staged anywhere or any foreign
|
|
578
|
+
path under the ledger is dirty, reconciles, runs the mutation unchanged,
|
|
579
|
+
commits exactly the changed item plus at most one
|
|
580
|
+
`.wowbagger/reconcile-<namespace>.md` with a fixed subject, verifies that commit,
|
|
581
|
+
and runs `claim-verify` before it answers. A successful `create --auto-commit`
|
|
582
|
+
commits exactly two paths: the created item and that reconciliation log. Every
|
|
583
|
+
command rebuilds its own derived reconciliation log during preflight, but
|
|
584
|
+
`create` refuses a log that was already dirty when you invoked it, and every
|
|
585
|
+
other dirty ledger path still refuses.
|
|
586
|
+
|
|
587
|
+
Preflight and post-commit reconciliation block findings for the requested item.
|
|
588
|
+
An unrelated `worktree-synchronization-required` finding remains visible to
|
|
589
|
+
`claim-verify` without turning a successful mutation into failure. If claim
|
|
590
|
+
verification refuses, the result preserves `claim_verify_code` and
|
|
591
|
+
`claim_verify_reason`; only `claim-store-locked` is retryable.
|
|
592
|
+
|
|
463
593
|
Success adds `git_commit`, `commit_paths`, and `claim_verified` to `result`.
|
|
464
594
|
|
|
465
595
|
Say these limits plainly when you use it:
|
|
@@ -522,7 +652,7 @@ wowbagger provision --ledger <dir> --json
|
|
|
522
652
|
wowbagger claim capabilities --ledger <dir> --json
|
|
523
653
|
wowbagger claim read|acquire|renew|release --ledger <dir> --input request.json --json
|
|
524
654
|
wowbagger publish-claimed --ledger <dir> --input request.json --json [--auto-commit]
|
|
525
|
-
wowbagger claim-verify --ledger <dir> --json
|
|
655
|
+
wowbagger claim-verify --ledger <dir> [--id <item>] --json
|
|
526
656
|
wowbagger claim-sync --ledger <dir> --json
|
|
527
657
|
wowbagger claim-merge-verify --ledger <dir> --base <ref> --head <ref> --json
|
|
528
658
|
```
|
|
@@ -552,26 +682,84 @@ envelope's `limits.cross_worktree_coordination: false` as permission to write
|
|
|
552
682
|
with hostile or noncooperating tools — it only says the core never synchronizes
|
|
553
683
|
checkouts.
|
|
554
684
|
|
|
555
|
-
A recorded `transition`, `patch`, or claimed publication blocks
|
|
556
|
-
targeting that same item with exit 6 `claim-store-unavailable`,
|
|
557
|
-
`publication-reconciliation-required`. An unrelated item mutation may
|
|
558
|
-
when the only finding is `worktree-synchronization-required`.
|
|
559
|
-
|
|
685
|
+
A recorded `create`, `transition`, `patch`, or claimed publication blocks
|
|
686
|
+
mutations targeting that same item with exit 6 `claim-store-unavailable`,
|
|
687
|
+
reason `publication-reconciliation-required`. An unrelated item mutation may
|
|
688
|
+
proceed when the only finding is `worktree-synchronization-required`.
|
|
689
|
+
|
|
690
|
+
`create` is the one exception to that scoping, because it allocates the next
|
|
691
|
+
number from the items this checkout can see. It also refuses when the journal
|
|
692
|
+
records a committed item this worktree does not hold at all: that item carries
|
|
693
|
+
a number nobody here can read, so the next number allocated here might already
|
|
694
|
+
be taken. A stale revision of an item this worktree does hold is not a blocker
|
|
695
|
+
for `create` — a number is immutable, so the local maximum is still right. The
|
|
696
|
+
refusal is the same exit 6 `claim-store-unavailable` with reason
|
|
697
|
+
`publication-reconciliation-required`, state `unchanged`, and no item file
|
|
698
|
+
written; integrate the missing item, run `claim-verify` until it exits 0, and
|
|
699
|
+
resend the same request, which then takes the next number.
|
|
700
|
+
|
|
701
|
+
That fence stops new collisions; it does not repair old ones through core
|
|
702
|
+
version 5 or claim operations. Existing duplicate numbers are item #182
|
|
703
|
+
recovery work. Use the separate `ledger-repair` contract:
|
|
704
|
+
`number-repair-proposal --ledger <dir> --json` is read-only and writes no item
|
|
705
|
+
file; `number-repair --ledger <dir> --input <repair.json> --json` applies a
|
|
706
|
+
reviewed complete mapping under the shared namespace fence. Number-only repair
|
|
707
|
+
preserves ULID identities and relation values. Never hand-edit the ledger:
|
|
708
|
+
arbitrary edits can damage IDs, paths, or references.
|
|
560
709
|
|
|
561
710
|
Read `error.details.findings[0].reason` and act on the named item:
|
|
562
711
|
|
|
563
712
|
- `git-finalization-required` — you wrote the item here and have not committed.
|
|
564
713
|
Commit, then `claim-verify`.
|
|
565
|
-
- `worktree-synchronization-required` — another worktree wrote the item.
|
|
714
|
+
- `worktree-synchronization-required` — another worktree wrote the item.
|
|
715
|
+
`owner_ref` names an **active named worktree** and nothing else: it is always
|
|
716
|
+
the branch of a live worktree that carries the expected revision. If the
|
|
566
717
|
finding names `owner_ref` and `owner_commit`, WAIT for that owner to publish,
|
|
567
|
-
then synchronize this checkout and run `claim-verify`.
|
|
568
|
-
`
|
|
569
|
-
|
|
718
|
+
then synchronize this checkout and run `claim-verify`. `owner_unavailable:
|
|
719
|
+
true` means no such worktree exists, and it covers three cases: the expected
|
|
720
|
+
revision is not reachable at all, a live sibling holds it on a detached
|
|
721
|
+
`HEAD`, or it is reachable only from a tag, a remote-tracking ref, or a
|
|
722
|
+
branch no worktree has checked out. Reachability is not ownership; a ref you
|
|
723
|
+
can see is not a worktree that can publish. Follow the `remediation`, which
|
|
724
|
+
separates those cases. A revision that is **not yet reachable** means WAIT for
|
|
725
|
+
the owning worktree to commit, then synchronize. A revision that is
|
|
726
|
+
**reachable in Git while no active named worktree owner is established** —
|
|
727
|
+
a tag, a remote-tracking ref, an unchecked-out branch, or a detached sibling
|
|
728
|
+
carries it — is not a wait at all: inspect that reachable history, then
|
|
729
|
+
restore the authorized bytes or use explicit `claim-adopt` after review.
|
|
730
|
+
Ownership that **cannot be established from reachable refs** — the item has
|
|
731
|
+
never existed in this checkout — calls for inspecting reachable or dangling
|
|
732
|
+
commits with the same explicit restore or `claim-adopt`. Never merge unrelated
|
|
733
|
+
live work.
|
|
570
734
|
- `unauthorized-revision` — the item changed outside the protocol. Two remedies
|
|
571
735
|
are explicit: **restore** the authorized revision and run `claim-verify` to
|
|
572
736
|
discard the edit, or **adopt** the committed revision and run `claim-verify`
|
|
573
737
|
to keep it. Ask before discarding reviewed work.
|
|
574
738
|
|
|
739
|
+
Two live worktrees answering to one identity, or a worktree roster the
|
|
740
|
+
coordinator could not finish reading, refuse before anything is classified.
|
|
741
|
+
You get exit 6 `claim-store-unavailable`, reason `claim-store-unreadable`, with
|
|
742
|
+
`error.details.identity_diagnostic`: `duplicate-worktree-identity` naming the
|
|
743
|
+
`worktree_id` and `live_worktree_count`, or `worktree-enumeration-failed` with
|
|
744
|
+
no further member. Auto-commit reports the same diagnostic inside
|
|
745
|
+
`auto-commit-preflight-failed` with `retryable: false`. Neither is retryable
|
|
746
|
+
and neither is yours to repair by editing files. Report the diagnostic verbatim,
|
|
747
|
+
including the `worktree_id` and `live_worktree_count`: a duplicate means two
|
|
748
|
+
live worktrees hold the same identity file, usually because a private Git
|
|
749
|
+
directory was copied, and which worktree keeps the UUID is a person's decision.
|
|
750
|
+
An enumeration failure means a registered worktree path could not be read. The
|
|
751
|
+
identity itself is an opaque UUID a worktree writes once into its private Git
|
|
752
|
+
directory. Never create, copy, or edit it.
|
|
753
|
+
|
|
754
|
+
**Choose verification scope deliberately.** Bare
|
|
755
|
+
`claim-verify --ledger <dir> --json` is strict repository diagnosis: any
|
|
756
|
+
blocking finding anywhere keeps it at exit 6. After working one item, use
|
|
757
|
+
`claim-verify --ledger <dir> --id <item> --json`. It keeps every repository
|
|
758
|
+
finding visible and marks each with `blocks_verification_scope`, but unrelated
|
|
759
|
+
target-scoped findings do not fail that item's gate. Global barriers still
|
|
760
|
+
fail every target. Never adopt or hand-edit a sibling's item to force either
|
|
761
|
+
scope clean.
|
|
762
|
+
|
|
575
763
|
Adoption is per item and per revision explicit. Name the item and both
|
|
576
764
|
revisions, take them from the finding, and commit the edited bytes first:
|
|
577
765
|
|
|
@@ -613,7 +801,7 @@ Use the claimed write path as one complete loop:
|
|
|
613
801
|
not in an accessible Git checkout. Stop before mutation.
|
|
614
802
|
2. Run `provision` once for the ledger. Keep its `ledger_namespace`.
|
|
615
803
|
3. Run `claim capabilities --ledger <dir> --json` again. Require
|
|
616
|
-
`result.operations.work_claim.api_version:
|
|
804
|
+
`result.operations.work_claim.api_version: 3`. Do not compare the claim
|
|
617
805
|
response's top-level `contract_version` with the core version; it is the
|
|
618
806
|
legacy claim-envelope marker. Stop if the namespace is absent or the mode is
|
|
619
807
|
not `merge-coordinated`.
|
|
@@ -625,12 +813,15 @@ Use the claimed write path as one complete loop:
|
|
|
625
813
|
revision, the candidate bytes and digest, and the active claim fence. Never
|
|
626
814
|
retry with only the operation ID; retry the complete request.
|
|
627
815
|
8. Commit the item change, or merge the worker commit into the coordinating
|
|
628
|
-
branch. Do this now, not at the end of a batch
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
816
|
+
branch. Do this now, not at the end of a batch. Acceptance of another command
|
|
817
|
+
does not prove this mutation is durable, and a blocking finding still
|
|
818
|
+
refuses that command.
|
|
819
|
+
9. Run `claim-verify --ledger <dir> --id <item> --json` after the commit or
|
|
820
|
+
merge. It finalizes the Git outcome, repairs response-loss cases, and reports
|
|
821
|
+
later revision drift. Require exit 0 before the next mutating command; exit
|
|
822
|
+
6 means findings block this item, so act on each blocking finding's
|
|
823
|
+
`remediation` and run it again. Unrelated nonblocking findings remain
|
|
824
|
+
visible for repository diagnosis.
|
|
634
825
|
10. Release the claim with its current observed state.
|
|
635
826
|
11. Run `validate` and show the resulting diff.
|
|
636
827
|
|
|
@@ -653,8 +844,11 @@ response envelopes, refusal precedence, and recovery rules.
|
|
|
653
844
|
6. `validate`, then show the diff.
|
|
654
845
|
7. On a provisioned ledger, commit the ledger change now:
|
|
655
846
|
`git add <dir> && git commit`.
|
|
656
|
-
8. On a provisioned ledger, run
|
|
657
|
-
|
|
847
|
+
8. On a provisioned ledger, run
|
|
848
|
+
`claim-verify --ledger <dir> --id <item> --json` and require exit 0 before
|
|
849
|
+
the next `create`, `transition`, `parent-migrate`, `snooze`, `patch`, or
|
|
850
|
+
`publish-claimed`. Use bare verification separately for strict
|
|
851
|
+
repository-wide diagnosis.
|
|
658
852
|
|
|
659
853
|
Write, commit, `claim-verify`, next write. The unclaimed loop obeys the same
|
|
660
854
|
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',
|