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.
Files changed (41) hide show
  1. package/CHANGELOG.md +470 -0
  2. package/README.md +220 -79
  3. package/assets/wowbagger-v1-more-whimsical.jpg +0 -0
  4. package/assets/wowbagger-v2-less-whimsical.jpg +0 -0
  5. package/assets/wowbagger-v3-herding-agent-cats.jpg +0 -0
  6. package/assets/wowbagger-v4-robot-agent-herding.jpg +0 -0
  7. package/assets/wowbagger-v5-typing-cats-circuit-staff.jpg +0 -0
  8. package/docs/adapter-contract.md +1 -1
  9. package/docs/host-contract.md +7 -1
  10. package/docs/mutation-contract.md +354 -82
  11. package/docs/work-claim-contract.md +466 -88
  12. package/package.json +8 -3
  13. package/schemas/core-capabilities-response.json +1 -1
  14. package/schemas/core-envelope.json +4 -3
  15. package/schemas/index.json +18 -0
  16. package/schemas/ledger-repair-proposal.json +170 -0
  17. package/schemas/ledger-repair-request.json +61 -0
  18. package/schemas/ledger-repair-response.json +90 -0
  19. package/skills/wowbagger/SKILL.md +250 -56
  20. package/src/adapter/core-probe.js +3 -4
  21. package/src/adapter/process-outcome.js +8 -1
  22. package/src/claim-capabilities.js +3 -3
  23. package/src/claim-coordinator.js +61 -12
  24. package/src/claim-journal.js +212 -7
  25. package/src/claim-prospective.js +1 -28
  26. package/src/claim-publication.js +412 -78
  27. package/src/claim-request.js +9 -0
  28. package/src/claim-store.js +9 -4
  29. package/src/cli.js +302 -56
  30. package/src/extensions.js +1 -0
  31. package/src/git-autocommit.js +106 -43
  32. package/src/git-reconciliation.js +74 -19
  33. package/src/git-worktrees.js +73 -0
  34. package/src/instrumentation.js +1 -0
  35. package/src/launch.js +2 -2
  36. package/src/ledger-repair.js +1170 -0
  37. package/src/mutation.js +73 -15
  38. package/src/reconciliation-classifier.js +117 -0
  39. package/src/report.js +11 -2
  40. package/src/version-drift.js +98 -0
  41. package/src/worktree-identity.js +165 -0
package/README.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  **The backlog may be infinite. The next item should not be ambiguous.**
4
4
 
5
+ <p align="center">
6
+ <img src="https://raw.githubusercontent.com/lstutzman/wowbagger/main/assets/wowbagger-v5-typing-cats-circuit-staff.jpg" alt="Bowerick Wowbagger directing robotic agent cats typing at consoles with a circuit-lit shepherd's staff">
7
+ </p>
8
+
9
+ **Don't Panic!** The books that helped shape my childhood taught me to meet
10
+ absurd systems with curiosity, humor, and a reliable way to find the next
11
+ step. [Douglas Adams's Hitchhiker's Guide creations](https://douglasadams.com/creations/hhgg.html)
12
+ are part of that inspiration; Wowbagger is an independent work, not an
13
+ official or affiliated project.
14
+
5
15
  Wowbagger is a work ledger for coding agents. Every backlog item is one
6
16
  Markdown file in your repository; every lifecycle change is a reviewable Git
7
17
  diff. There is no database, no hosted service, and no private agent memory to
@@ -20,10 +30,10 @@ agent to use those guarantees instead of hand-editing your Markdown.
20
30
 
21
31
  **Start here:** [install the core and set up a ledger](#start-here).
22
32
 
23
- > **Status: alpha, published, and self-hosted.** `0.1.0-alpha.8` is on npm under
24
- > the `next` tag and on this repository's `v0.1.0-alpha.8` tag. It is the
25
- > version this repository runs its own backlog on. The API is not frozen and the
26
- > version will move before a stable release.
33
+ > **Status: beta, published, and self-hosted.** `0.5.0-beta.0` is on npm under
34
+ > the `next` tag and on this repository's `v0.5.0-beta.0` tag. It is the
35
+ > version this repository runs its own backlog on. The API remains pre-stable
36
+ > and can change before the first stable release.
27
37
  >
28
38
  > **Install with `@next`.** Every published release is a prerelease. The
29
39
  > registry requires a `latest` dist-tag, so `latest` mirrors `next` — a bare
@@ -31,17 +41,25 @@ agent to use those guarantees instead of hand-editing your Markdown.
31
41
  > older build — but `@next` is the documented install and the explicit
32
42
  > statement that you accept a prerelease.
33
43
  >
34
- > **What is proved.** The core validates a Markdown ledger, selects a
35
- > deterministic ready queue, renders a self-contained HTML report, and
36
- > implements guarded `inspect`, `create`, `transition`, and `patch`, plus
37
- > `mint-id`, `capabilities`, `provision`, the `claim` lifecycle,
38
- > `publish-claimed`, `claim-verify`, and `claim-adopt`. The core contract
39
- > version is **3**. Three adapter packages ship — Claude Code, Codex, and
40
- > OpenCode — on one shared engine at adapter contract version 2. Only the Claude
41
- > Code adapter declares a `supported` platform, Darwin, from a native run of all
42
- > 212 conformance assertions across all 16 cases. Every other adapter and
43
- > platform declaration is `unverified`; do not infer support because the CLI
44
- > starts.
44
+ > **What is proved.** Contract version **5** validates the complete Markdown
45
+ > ledger, selects a deterministic ready queue, exposes bounded `list` and
46
+ > lossless `inspect` projections, and publishes guarded `create`, `transition`,
47
+ > `patch`, `parent-migrate`, and `snooze` mutations. Mutations use exact-byte
48
+ > compare-and-swap, atomic no-clobber publication, and explicit reconciliation
49
+ > when a response is lost. Claims, fencing, adoption, prospective merge
50
+ > verification, and publication finalization coordinate cooperating writers
51
+ > without pretending to be an exclusive dispatch lock.
52
+ >
53
+ > `report` is a self-contained sequencing dashboard: **Work next**, **Attention**,
54
+ > facet filters, inline evidence, terminal history, area-diverse batches, and a
55
+ > 3D dependency graph. Version 2 report configurations add named custom views
56
+ > whose statistics, readiness, attention, evidence, graph, and drill-down all
57
+ > describe one filtered subset. Reports remain derived output, not mirrored
58
+ > ledger state.
59
+ >
60
+ > The core ships Claude Code, Codex, and OpenCode adapter packages on one shared
61
+ > engine. Read `capabilities --json` before relying on a target-specific claim;
62
+ > platform support is evidence-based, not inferred from whether a CLI starts.
45
63
  >
46
64
  > **What is not a lock.** A work claim is not an exclusive dispatch lease. On a
47
65
  > provisioned Git-backed ledger, claims coordinate cooperating agents through a
@@ -53,31 +71,85 @@ agent to use those guarantees instead of hand-editing your Markdown.
53
71
  > filesystem writes, hostile processes, other clones, and non-claim-aware tools
54
72
  > still bypass the protocol.
55
73
 
74
+ ## TL;DR for agents
75
+
76
+ Wowbagger is the core authority for a Git-native work ledger. Use it instead
77
+ of editing ledger Markdown by hand.
78
+
79
+ ```sh
80
+ wowbagger --version # require 0.5.0-beta.0
81
+ wowbagger capabilities --json # require contract_version: 5
82
+ wowbagger validate --ledger ledger --json
83
+ wowbagger ready --ledger ledger --as-of YYYY-MM-DD --json
84
+ wowbagger inspect --ledger ledger --number N --json
85
+ ```
86
+
87
+ For a write, inspect immediately before dispatch, send the returned exact-byte
88
+ revision as the compare-and-swap witness, use the explicit core mutation, and
89
+ validate again. On a provisioned ledger, commit each `create`, `transition`,
90
+ `parent-migrate`, `snooze`, `patch`, or `publish-claimed` mutation before the
91
+ next mutating command. Never replay a lost write: reconnect, re-read current
92
+ state, and treat the outcome as unknown until the core or a human resolves it.
93
+ Numbers are the human-facing item identity; `wb_...` ULIDs are internal
94
+ identities.
95
+
96
+ The core owns validation, ready selection, projections, lifecycle, CAS,
97
+ publication, claims, fencing, and reconciliation. The harness or host owns
98
+ dispatch, process safety, routing, and human approval. Claims coordinate
99
+ cooperating writers; they are not exclusive locks.
100
+
56
101
  ## Start here
57
102
 
58
- Install the core CLI, then verify it:
103
+ Install the core CLI, then verify it. The supported runtime is Node.js 24; Node
104
+ 26 remains excluded because of the separate Vitest incompatibility:
59
105
 
60
106
  ```sh
61
- npm install -g wowbagger@next # public npm registry
107
+ npm install -g wowbagger@0.5.0-beta.0 # exact plugin-matched release
62
108
  # or, from this release's Git tag:
63
- # npm install -g github:lstutzman/wowbagger#v0.1.0-alpha.8
64
- wowbagger --version # 0.1.0-alpha.8
65
- wowbagger capabilities --json
109
+ # npm install -g github:lstutzman/wowbagger#v0.5.0-beta.0
110
+ wowbagger --version # 0.5.0-beta.0
111
+ wowbagger capabilities --json # must report contract_version: 5
66
112
  ```
67
113
 
68
- In Claude Code, add the plugin:
114
+ In Claude Code, install the managed plugin:
115
+
116
+ ```sh
117
+ claude plugins install wowbagger
118
+ ```
119
+
120
+ Or, from inside a Claude Code session:
121
+
122
+ ```
123
+ /plugin install wowbagger
124
+ ```
125
+
126
+ This route is available after Wowbagger is listed in Claude Code's official
127
+ marketplace. Until then, or when installing a fork or unreleased revision, use
128
+ the direct repository marketplace:
69
129
 
70
130
  ```
71
131
  /plugin marketplace add lstutzman/wowbagger
72
132
  /plugin install wowbagger@wowbagger
73
133
  ```
74
134
 
75
- The plugin drives the installed core rather than bundling one, so a mismatch is
76
- detectable instead of silent. Its skill reads `wowbagger --version` and
77
- `capabilities`; it requires the same distribution version as the plugin and core
78
- `contract_version: 5`. It refuses an absent or incompatible core. It will not
79
- fall back to editing ledger files by hand, because that would bypass validation
80
- and atomic publication.
135
+ For Codex and other agents, install the editable skill with `skills`:
136
+
137
+ ```sh
138
+ npx skills@latest add lstutzman/wowbagger --skill wowbagger
139
+ ```
140
+
141
+ Choose one route. Do not install both the managed Claude plugin and the
142
+ editable skill, or the skill will be loaded twice.
143
+
144
+ The plugin and `skills` installer drive the separately installed core rather
145
+ than bundling one, so a mismatch is detectable instead of silent. The skill
146
+ reads `wowbagger --version` and `capabilities`; it requires the same
147
+ distribution version as the plugin and core `contract_version: 5`. It refuses
148
+ an absent or incompatible core. It will not fall back to editing ledger files
149
+ by hand, because that would bypass validation and atomic publication.
150
+
151
+ Neither installer adds an MCP server, remote service, hook, or background
152
+ process. The plugin and skill operate on the ledger through the installed core.
81
153
 
82
154
  ### Set the ledger up before the first item
83
155
 
@@ -97,21 +169,45 @@ names — `create` publishes into an existing directory and does not make one.
97
169
  Nothing is renamed after a create. This repository dogfoods that binding: its
98
170
  own items live in [`ledger/items/`](ledger/items/).
99
171
 
100
- If your items mirror an external tracker and carry your own identifier fields,
101
- declare them now too. `<ledger>/.wowbagger/extensions.json` is what makes a
102
- consumer-owned extension member patchable:
172
+ If your items will mirror an external tracker and carry consumer-owned fields,
173
+ declare those fields **before the first item**. The declaration makes each
174
+ named extension member patchable:
103
175
 
104
176
  ```sh
105
177
  echo '{"extensions_version":1,"members":{"external_id":"string"}}' \
106
178
  > path/to/ledger/.wowbagger/extensions.json
107
179
  ```
108
180
 
109
- Each member declares one value type — `string`, `integer`, `boolean`, or
110
- `string-list`. **A ledger without that file has no patchable extension member at
111
- all**, and a `set.extensions` patch against it is refused by name. The
112
- declaration authorizes a write; it never describes the ledger, so `validate`
113
- does not read it. Both files are ledger setup, not runner configuration: commit
114
- them.
181
+ Each member declares one value type: `string`, `integer`, `boolean`, or
182
+ `string-list`. A ledger without the file has no patchable extension member,
183
+ and `set.extensions` refuses the missing declaration by name. The declaration
184
+ authorizes writes; it does not define item validity, so `validate` does not
185
+ read it. Commit the declaration with the other ledger setup.
186
+
187
+ If an existing ledger already carries extension values, do not create the
188
+ declaration by hand. Select every member and type explicitly in a request,
189
+ review a dry run, then publish the same proposal:
190
+
191
+ ```json
192
+ {"members":{"tags":"string-list"}}
193
+ ```
194
+
195
+ ```sh
196
+ wowbagger extensions-provision --ledger path/to/ledger \
197
+ --input declaration.json --json --dry-run
198
+ wowbagger extensions-provision --ledger path/to/ledger \
199
+ --input declaration.json --json
200
+ git add path/to/ledger/.wowbagger/extensions.json
201
+ git commit -m "Declare patchable ledger extensions"
202
+ ```
203
+
204
+ The command first requires a valid complete ledger. It validates every
205
+ occurrence of each selected member, reports occurrence counts, changes no item
206
+ bytes, and publishes one canonical declaration without overwriting a different
207
+ one. Commit that file before the first corresponding `patch`, inspect the
208
+ target for its current revision, then use `set.extensions.tags`. An item that
209
+ writes the selected member with a YAML anchor or alias remains
210
+ `extension-anchored` and requires a reviewed hand-edit.
115
211
 
116
212
  Cores at `0.1.0-alpha.4` and earlier ignore the layout file and publish every
117
213
  item at the ledger root.
@@ -200,8 +296,9 @@ skill exists because four things break when it does.
200
296
  - **Validation is whole-ledger and fail-closed.** One malformed item refuses
201
297
  every read and every guarded mutation on that ledger, including commands that
202
298
  never touch it. A hand-edit finds that out later, and usually in someone
203
- else's session. `create`, `transition`, and `patch` validate the complete
204
- candidate ledger *before* publishing anything, and refuse `unchanged`.
299
+ else's session. `create`, `transition`, `parent-migrate`, `snooze`, and
300
+ `patch` validate the complete candidate ledger *before* publishing anything,
301
+ and refuse `unchanged`.
205
302
  - **A hand-edit has no lost-update guard.** Every guarded write takes the exact
206
303
  SHA-256 revision `inspect` returned and refuses if the bytes moved. An editor
207
304
  writes over whatever is there.
@@ -253,7 +350,7 @@ two supported install routes:
253
350
  registry requires a `latest` tag), so a bare install resolves to the same
254
351
  bytes.
255
352
  - **git tag** —
256
- `npm install -g github:lstutzman/wowbagger#v0.1.0-alpha.8` installs this
353
+ `npm install -g github:lstutzman/wowbagger#v0.5.0-beta.0` installs this
257
354
  release. Installing at a ref installs the core and every adapter that ref
258
355
  carries.
259
356
 
@@ -289,10 +386,10 @@ version.
289
386
 
290
387
  ### Security
291
388
 
292
- - **Read-only by default.** `validate`, `ready`, `report`, `inspect`,
293
- `capabilities`, and `mint-id` never modify anything. Every mutation
294
- (`create`, `transition`, `patch`, and `publish-claimed`) is an explicit,
295
- reviewable write.
389
+ - **Read-only by default.** `validate`, `ready`, `report`, `inspect`, `list`,
390
+ `capabilities`, and `mint-id` never modify anything. Every item mutation
391
+ (`create`, `transition`, `parent-migrate`, `snooze`, `patch`, and
392
+ `publish-claimed`) is an explicit, reviewable write.
296
393
  - **Lock is not a claim.** A short mutation lock serializes writers during one
297
394
  operation. It does not grant a work claim.
298
395
  - **Claims are merge-coordinated, not exclusive.** `claim acquire` uses
@@ -325,7 +422,7 @@ Upgrade the pieces you installed:
325
422
 
326
423
  ```sh
327
424
  npm install -g wowbagger@next # public npm registry
328
- npm install -g github:lstutzman/wowbagger#v0.1.0-alpha.8 # immutable Git release
425
+ npm install -g github:lstutzman/wowbagger#v0.5.0-beta.0 # immutable Git release
329
426
  git pull && npm ci # or: a direct checkout
330
427
  ```
331
428
 
@@ -373,6 +470,16 @@ core, these are the changes most likely to touch you:
373
470
  `create` and refuses a caller-supplied one; `patch` refuses it because it is
374
471
  immutable identity. Keep a legacy identifier in a declared extension member or
375
472
  in the item body.
473
+
474
+ - **Repair duplicate numbers through `ledger-repair` version 1.** Generate a
475
+ read-only proposal with `number-repair-proposal`, review every
476
+ `expected_revision` and `replacement_number`, then apply the complete mapping
477
+ with `number-repair`. The command preserves ULID identities and relations and
478
+ does not change core contract version 5.
479
+
480
+ - **Run `version-drift --json` before mutation.** It compares the installed
481
+ skill pin, required core contract, and running core, and names the stale
482
+ package, plugin cache, or linked checkout with remediation.
376
483
  - **Delete your local ULID generator.** `wowbagger mint-id --json` prints a
377
484
  canonical ID; `--date YYYY-MM-DD` selects the creation date the ID must
378
485
  encode.
@@ -483,7 +590,8 @@ approval never rides the bootstrap request, which the model controls;
483
590
 
484
591
  ## Core commands
485
592
 
486
- The current core requires Node.js 20 or later. From a Wowbagger checkout,
593
+ The current core requires Node.js 24. Node 26 is not in the supported matrix.
594
+ From a Wowbagger checkout,
487
595
  `./bin/wowbagger.js --help` prints the full command inventory,
488
596
  `./bin/wowbagger.js <command> --help` prints that command's usage, and
489
597
  `./bin/wowbagger.js --version` prints the installed package version. The
@@ -496,21 +604,28 @@ npm ci
496
604
  ./bin/wowbagger.js ready --ledger path/to/ledger --as-of 2030-01-15
497
605
  ./bin/wowbagger.js report --ledger path/to/ledger --as-of 2030-01-15 --json
498
606
  ./bin/wowbagger.js capabilities --json
499
- ./bin/wowbagger.js mint-id --json
500
607
  ./bin/wowbagger.js inspect --ledger path/to/ledger --id wb_... --json
501
608
  ./bin/wowbagger.js inspect --ledger path/to/ledger --number 30 --json
609
+ ./bin/wowbagger.js list --ledger path/to/ledger --input query.json --json
502
610
  ./bin/wowbagger.js create --ledger path/to/ledger --input request.json --json
503
611
  ./bin/wowbagger.js transition --ledger path/to/ledger --input request.json --json
612
+ ./bin/wowbagger.js parent-migrate --ledger path/to/ledger --input request.json --json
613
+ ./bin/wowbagger.js snooze --ledger path/to/ledger --input request.json --json
504
614
  ./bin/wowbagger.js patch --ledger path/to/ledger --input request.json --json
615
+ ./bin/wowbagger.js extensions-provision --ledger path/to/ledger --input declaration.json --json
616
+ ./bin/wowbagger.js mint-id --json
617
+ ./bin/wowbagger.js publish-claimed --ledger path/to/ledger --input request.json --json
618
+ ./bin/wowbagger.js claim-merge-verify --ledger path/to/ledger --base main --head feature --json
619
+ ./bin/wowbagger.js claim-sync --ledger path/to/ledger --json
620
+ ./bin/wowbagger.js claim-adopt --ledger path/to/ledger --input request.json --json
621
+ ./bin/wowbagger.js mutation-finalize --ledger path/to/ledger --recovery-token token --json
505
622
  ./bin/wowbagger.js provision --ledger path/to/ledger --json
506
623
  ./bin/wowbagger.js claim capabilities --ledger path/to/ledger --json
507
624
  ./bin/wowbagger.js claim acquire --ledger path/to/ledger --input request.json --json
508
625
  ./bin/wowbagger.js claim read --ledger path/to/ledger --input request.json --json
509
626
  ./bin/wowbagger.js claim renew --ledger path/to/ledger --input request.json --json
510
627
  ./bin/wowbagger.js claim release --ledger path/to/ledger --input request.json --json
511
- ./bin/wowbagger.js publish-claimed --ledger path/to/ledger --input request.json --json
512
- ./bin/wowbagger.js claim-verify --ledger path/to/ledger --json
513
- ./bin/wowbagger.js claim-adopt --ledger path/to/ledger --input request.json --json
628
+ ./bin/wowbagger.js claim-verify --ledger path/to/ledger [--id wb_...] --json
514
629
  ```
515
630
 
516
631
  `validate` writes exactly one JSON result to standard output. A valid ledger
@@ -573,10 +688,12 @@ change is an addition. And **extension members are patchable only where the
573
688
  ledger declares them** — see [Set the ledger up before the first
574
689
  item](#set-the-ledger-up-before-the-first-item).
575
690
 
576
- Which members you own at all is a three-way split — core-owned,
577
- consumer-editable through `patch`, and create-once — stated member by member in
578
- the mutation contract's **frontmatter ownership** table. Read the table; do not
579
- send a patch and interpret the refusal.
691
+ Which members you own at all is a four-way split — core-owned,
692
+ consumer-editable through `patch`, mutable through a dedicated command, and
693
+ create-once — stated member by member in the mutation contract's
694
+ **frontmatter ownership** table. Use `parent-migrate` to repoint an existing
695
+ item to or from an epic, and `snooze` to set or clear `snoozed_until`. Read the
696
+ table; do not send a patch and interpret the refusal.
580
697
 
581
698
  ### An epic's progress is derived, never stored
582
699
 
@@ -601,9 +718,11 @@ command asks you to parse the Markdown by hand:
601
718
  refusal carries `error.details.item`, the complete snapshot of the item you
602
719
  asked for, whenever no validation error names that item's path. A faulted
603
720
  item is withheld; `validate` already names its repair.
604
- - `claim-verify --json` reports `result.ledger_validation`. Exit 0 with
605
- `findings: []` and `ledger_validation.valid: false` says the claim journal is
606
- consistent and validation alone is blocking every mutation.
721
+ - `claim-verify --json` reports `result.ledger_validation`. Bare verification
722
+ is strict repository-wide mode; `--id <item>` keeps all findings visible but
723
+ fails only for that item and global barriers. Exit 0 with an invalid
724
+ `ledger_validation` still means claim state is clean but validation blocks
725
+ mutation.
607
726
 
608
727
  ### Work claims
609
728
 
@@ -633,22 +752,29 @@ operating rule:
633
752
 
634
753
  **Commit each mutation to Git before running the next mutating command.**
635
754
 
636
- The durable claim store validates every recorded mutation against Git `HEAD`,
637
- not against working-tree bytes. That is what makes a recorded mutation durable
638
- rather than a local edit one `git checkout` away from vanishing. An uncommitted
639
- mutation is an unreconciled mutation, so the next `create`, `transition`, or
640
- `patch` refuses instead of writing on top of it.
755
+ The durable claim store reconciles every recorded mutation with Git `HEAD` and
756
+ the working tree. The next mutation refuses when that reconciliation finds an
757
+ `unauthorized-revision`, requires Git finalization, or requires synchronization
758
+ for the item the command targets. A synchronization finding on an unrelated
759
+ item remains visible to `claim-verify` but does not block the command.
760
+
761
+ An existing item's latest authorized working-tree bytes and an earlier
762
+ authorized revision at `HEAD` form an authorized predecessor/successor window.
763
+ That window produces no finding, so another mutation can run before the first
764
+ one is committed. Acceptance of the later mutation does not make either change
765
+ durable. Commit each mutation anyway, then run `claim-verify`.
641
766
 
642
767
  The loop that works:
643
768
 
644
769
  ```sh
645
770
  ./bin/wowbagger.js create --ledger path/to/ledger --input request.json --json
646
771
  git add path/to/ledger && git commit -m "Record the mutation"
647
- ./bin/wowbagger.js claim-verify --ledger path/to/ledger --json
772
+ ./bin/wowbagger.js claim-verify --ledger path/to/ledger --id wb_... --json
648
773
  ./bin/wowbagger.js transition --ledger path/to/ledger --input next.json --json
649
774
  ```
650
775
 
651
- Skip the commit and the next command returns exit 6:
776
+ For example, an authorized new item that is still absent from `HEAD` makes the
777
+ next command return exit 6:
652
778
 
653
779
  ```json
654
780
  {"ok":false,"namespace":"ledger-mutation","command":"create-v1","contract_version":1,
@@ -663,10 +789,16 @@ Skip the commit and the next command returns exit 6:
663
789
  `state: "unchanged"` is exact — nothing was written. **`claim-verify` is the
664
790
  reconciliation procedure.** Read `details.findings`, do what each
665
791
  `remediation` string says, run `claim-verify` until it returns exit 0, then
666
- repeat the refused command.
792
+ repeat the refused command. A `worktree-synchronization-required` finding on an
793
+ unrelated item does not block the requested mutation. The same finding on the
794
+ target item, and every `unauthorized-revision` finding, remains blocking.
667
795
 
668
- Batch work is where this bites. Filing ten items means ten commits, not one
669
- commit at the end.
796
+ Batch work is where this bites. Filing ten items means ten serial
797
+ `create --auto-commit` calls and ten commits, not one batch commit. Wowbagger
798
+ permanently rejects batch create for the direct-Markdown architecture:
799
+ `limits.multi_item_atomicity` remains `false`, request order is the supported
800
+ bulk order, and each create must finish or recover before the next begins. See
801
+ the [batch-create decision](docs/design/2026-08-30-batch-create.md).
670
802
 
671
803
  ### Or fold the commit into the mutation
672
804
 
@@ -679,16 +811,23 @@ ledger only:
679
811
 
680
812
  It is opt-in per invocation. There is no configuration setting or environment
681
813
  default, because a hidden default would make existing automation create Git
682
- commits unexpectedly. The flag is accepted on `create`, `transition`, `patch`,
683
- and `publish-claimed`.
814
+ commits unexpectedly. The flag is accepted on `create`, `transition`,
815
+ `parent-migrate`, `snooze`, `patch`, and `publish-claimed`.
684
816
 
685
817
  What one flagged invocation does: refuse if anything is staged anywhere or any
686
- path under the ledger is dirty; reconcile; run the mutation unchanged; commit
687
- exactly the changed item and at most one
818
+ foreign path under the ledger is dirty; reconcile; run the mutation unchanged;
819
+ commit exactly the changed item and at most one
688
820
  `.wowbagger/reconcile-<namespace>.md` with a fixed subject such as
689
821
  `wowbagger: transition item #7`; verify the commit; then run `claim-verify`
690
- before it answers. On success the result gains `git_commit`, `commit_paths`, and
691
- `claim_verified`.
822
+ before it answers. A command that owns the claim journal may rebuild only its
823
+ derived reconciliation log during preflight. `create` remains strict, and
824
+ every other dirty ledger path still refuses. On success the result gains
825
+ `git_commit`, `commit_paths`, and `claim_verified`.
826
+
827
+ If claim verification refuses, auto-commit preserves its code and reason in
828
+ `claim_verify_code` and `claim_verify_reason`. Only
829
+ `claim_verify_reason: "claim-store-locked"` is retryable; unresolved
830
+ reconciliation is not.
692
831
 
693
832
  Unstaged and untracked files **outside** the ledger are left alone. Hooks and
694
833
  signing are honoured; `--no-verify` is never passed. Nothing is pushed.
@@ -1074,18 +1213,20 @@ the finding as a ledger item rather than leaving it in a transcript.
1074
1213
 
1075
1214
  ### The verification gate
1076
1215
 
1077
- Four commands. All four must pass, and the test commands run on **both** the
1078
- current Node runtime and Node 20:
1216
+ Four commands. All four must pass, and the test commands run on **Node 24.20.0**:
1079
1217
 
1080
1218
  ```sh
1081
- TMPDIR=/tmp node --test test/*.test.js
1082
- TMPDIR=/tmp /opt/homebrew/opt/node@20/bin/node --test test/*.test.js
1083
- TMPDIR=/tmp node spec/run-adapter-implementation.js
1084
- node bin/wowbagger.js validate --ledger ledger --json
1219
+ TMPDIR=/tmp /opt/homebrew/opt/node@24/bin/node --test test/*.test.js
1220
+ TMPDIR=/tmp /opt/homebrew/opt/node@24/bin/node --pending-deprecation --throw-deprecation --test test/*.test.js
1221
+ TMPDIR=/tmp /opt/homebrew/opt/node@24/bin/node spec/run-adapter-implementation.js
1222
+ TMPDIR=/tmp /opt/homebrew/opt/node@24/bin/node bin/wowbagger.js validate --ledger ledger --json
1085
1223
  ```
1086
1224
 
1087
1225
  `TMPDIR=/tmp` is not optional: the default macOS temporary path makes the claim
1088
- lock socket path too long. Substitute your own Node 20 binary path.
1226
+ lock socket path too long. Use an explicit Node 24.20.0 binary path.
1227
+
1228
+ The supported runtime matrix is Node 24.20.0. Node 26 remains excluded until
1229
+ the separate Vitest incompatibility reported by Lee is resolved.
1089
1230
 
1090
1231
  `npm test`, `npm audit --omit=dev`, and `git diff --check` are useful alongside
1091
1232
  it; they are not a substitute for the four commands above.
@@ -1477,7 +1477,7 @@ error registry. It changes only this versioned surface:
1477
1477
  The core capability probe adapter contract version 2 requires is core
1478
1478
  contract version 5. It adds exactly
1479
1479
  `operations.patch: {"supported":true,"write_scope":"single-item","cas_scope":"exact-byte-sha256"}`,
1480
- `operations.work_claim.api_version: 2`, and
1480
+ `operations.work_claim.api_version: 3`, and
1481
1481
  `limits.max_item_source_bytes: 8388608` as the first member of
1482
1482
  `limits`.
1483
1483
  Its mutation backend scope is always
@@ -26,10 +26,13 @@ shell: an absolute Node executable, the absolute `wowbagger.js` the package
26
26
  installed, an argument array, and `shell: false`. Neither path is discovered by
27
27
  searching a global npm directory, and neither is a platform command shim.
28
28
 
29
- Wowbagger requires Node.js 20 or later. The package declares that floor in
29
+ Wowbagger requires Node.js 24 or later. The package declares that floor in
30
30
  `engines.node`, and the launch seam exports it as `MINIMUM_NODE_MAJOR` for a
31
31
  host that resolves its own runtime instead of reusing the one it is running on.
32
32
 
33
+ The supported release matrix is Node 24.20.0. Node 26 is excluded until the
34
+ separate Vitest incompatibility reported by Lee is resolved.
35
+
33
36
  ~~~js
34
37
  import { resolveCoreLaunch } from 'wowbagger';
35
38
 
@@ -258,6 +261,9 @@ not a fetch URL.
258
261
  | `bare-ready-result.json` | bare result | a `ready` success |
259
262
  | `ledger-mutation-refusal.json` | ledger-mutation 1 | the legacy-write fence refusals |
260
263
  | `report-config-v1.json` | report config 1 | `<ledger>/.wowbagger/report.json` at version 1 |
264
+ | `ledger-repair-request.json` | ledger-repair 1 | the strict `number-repair` request |
265
+ | `ledger-repair-proposal.json` | ledger-repair 1 | the read-only `number-repair-proposal` result |
266
+ | `ledger-repair-response.json` | ledger-repair 1 | every `number-repair-proposal` and `number-repair` response |
261
267
  | `report-config-v2.json` | report config 2 | the same file at version 2, which names views |
262
268
 
263
269
  Every schema fixes its root members exactly and pins the version of its own