wowbagger 0.1.0-alpha.3 → 0.1.0-alpha.5
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 +268 -1
- package/README.md +215 -20
- package/adapters/claude-code/wowbagger-adapter.json +2 -2
- package/adapters/codex/wowbagger-adapter.json +1 -1
- package/adapters/opencode/wowbagger-adapter.json +1 -1
- package/docs/adapter-contract.md +1359 -0
- package/docs/mutation-contract.md +554 -63
- package/docs/work-claim-contract.md +272 -4
- package/package.json +4 -1
- package/skills/wowbagger/SKILL.md +245 -9
- package/src/adapter/core-probe.js +3 -3
- package/src/adapter/entrypoint-main.js +27 -5
- package/src/adapter/process-outcome.js +158 -8
- package/src/claim-capabilities.js +8 -0
- package/src/claim-coordinator.js +137 -7
- package/src/claim-journal.js +53 -3
- package/src/claim-publication.js +298 -89
- package/src/claim-store.js +20 -8
- package/src/cli.js +153 -18
- package/src/git-reconciliation.js +136 -11
- package/src/ledger.js +162 -2
- package/src/mutation.js +381 -81
- package/src/ready.js +64 -38
- package/src/report-attention.js +102 -0
- package/src/report-evidence.js +303 -0
- package/src/report-graph.js +364 -0
- package/src/report-html.js +317 -0
- package/src/report-markdown.js +171 -0
- package/src/report-sequencing.js +278 -0
- package/src/report-svg.js +342 -0
- package/src/report.js +436 -0
- package/src/schema-migration.js +27 -3
- package/src/validate.js +15 -5
- package/vendor/3d-force-graph/3d-force-graph.min.js +5 -0
- package/vendor/3d-force-graph/LICENSE +21 -0
- package/vendor/3d-force-graph/VERSIONS.json +24 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,274 @@ A change to what a command accepts, refuses, emits, or writes is a behaviour
|
|
|
5
5
|
change even when the commit that carried it was labelled refactor, docs, or
|
|
6
6
|
consolidation. The first tagged release inherits this file.
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## 0.1.0-alpha.5 - 2026-08-16
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **The report draws the whole ledger as a 3D dependency graph.** It sits below
|
|
13
|
+
the evidence layer, under the decision surface. Every item is a node labelled
|
|
14
|
+
`#N`, coloured by readiness or terminal status and sized by the same
|
|
15
|
+
transitive unblocking leverage the recommended order uses; `depends_on` edges
|
|
16
|
+
are straight and arrowed, `parent` edges are curved and unarrowed, and both
|
|
17
|
+
run from the prerequisite to the item it releases. Hovering or clicking a node
|
|
18
|
+
shows its number, title, status, age, leverage, and the same reasons line the
|
|
19
|
+
ranked list prints for it. The renderer is `3d-force-graph` 1.80.0 over
|
|
20
|
+
Three.js r183, vendored at `vendor/3d-force-graph/` with its upstream SHA-256
|
|
21
|
+
recorded beside it and pinned by a test, and inlined at generation time: the
|
|
22
|
+
report stays one self-contained file and fetches nothing at generation or view
|
|
23
|
+
time. It costs roughly 1.3 MB of report size. A browser without WebGL gets the
|
|
24
|
+
section's plain explanation and a per-node roster instead; no
|
|
25
|
+
decision-relevant content exists only in the 3D view.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- **An invalid ledger can now be diagnosed with the documented commands.** One
|
|
30
|
+
invalid item still refuses every read and every guarded mutation on that
|
|
31
|
+
ledger, but the refusals no longer hide what the operator has to read.
|
|
32
|
+
`inspect` keeps refusing exit 3 `ledger-invalid` — handing back a revision
|
|
33
|
+
from a ledger the core has not judged would read as a mutation precondition,
|
|
34
|
+
and there is no flag that skips validation — and its refusal now carries
|
|
35
|
+
`error.details.item`, the same lossless snapshot the success envelope
|
|
36
|
+
defines, for the item the request selected, whenever no validation error
|
|
37
|
+
names that item's path. A faulted item is withheld; `validate` already names
|
|
38
|
+
its repair. `claim-verify` now reports `result.ledger_validation`, carrying
|
|
39
|
+
`valid` and `errors` exactly as the bare `validate` result does, plus a
|
|
40
|
+
`remediation` when the ledger is invalid. Its claim answer is unchanged:
|
|
41
|
+
`findings`, `state`, and the exit status still describe claim state alone, so
|
|
42
|
+
a consistent journal over an invalid ledger is still exit 0 with
|
|
43
|
+
`findings: []` — it just no longer pretends that is a clear road. The report
|
|
44
|
+
costs no extra ledger read. Fixtures extend item #104's misplaced-item
|
|
45
|
+
scenario.
|
|
46
|
+
- **The adapter forwards `inspect` refusals instead of calling them protocol
|
|
47
|
+
errors.** Both the engine and the independent oracle demanded a canonical
|
|
48
|
+
mutation request before they would accept any error details, which no read
|
|
49
|
+
command has, so every `inspect` `item-not-found` and `ledger-invalid` refusal
|
|
50
|
+
was mapped to `core-protocol-error`. The precondition now applies only to
|
|
51
|
+
mutation commands. The same surfaces accept the `expected_path` and
|
|
52
|
+
`remediation` that item #104 added to a validation error, and the optional
|
|
53
|
+
`details.item` on an `inspect` `ledger-invalid` refusal — on `inspect` only;
|
|
54
|
+
a mutation refusal that carries one is still rejected.
|
|
55
|
+
|
|
56
|
+
- **The report's content security policy now also forbids `connect-src`.** The
|
|
57
|
+
report has never opened a connection; the policy now says so.
|
|
58
|
+
|
|
59
|
+
- **The `item-outside-layout` validation error now names the expected path and
|
|
60
|
+
the relocation that repairs it.** It keeps its stable code and its actual
|
|
61
|
+
`path`, and gains `expected_path` plus a `remediation`; its message names
|
|
62
|
+
both paths. A committed item outside the configured items directory refuses
|
|
63
|
+
every read and every guarded mutation on that ledger, including ones that
|
|
64
|
+
never touch the misplaced item, so the refusal has to say where the item
|
|
65
|
+
belongs. The claim fence is not involved: `claim-verify` reports no finding
|
|
66
|
+
on such a ledger, refuting the PropertyCompass2 PR #2184 claim that a
|
|
67
|
+
root-misplaced item makes the fence report `stale-write-detected` with
|
|
68
|
+
`actual_revision: null`. Fixtures pin both configuration orders — layout
|
|
69
|
+
bound first, and layout bound after the item was already committed at the
|
|
70
|
+
root.
|
|
71
|
+
- **The core contract version is now `3`.** Every core command envelope
|
|
72
|
+
(`capabilities`, `inspect`, `create`, `transition`, `patch`, `mint-id`,
|
|
73
|
+
`report`) carries `contract_version: 3`, the shipped adapters require core
|
|
74
|
+
contract version 3, and the installed skill's version check gates on 3. A
|
|
75
|
+
version 1 or version 2 consumer fails closed against this core, which is the
|
|
76
|
+
point of the bump. Version 3 is version 2 plus four deltas against published
|
|
77
|
+
`0.1.0-alpha.4`: the widened `date-before-created` / `date-before-updated`
|
|
78
|
+
issue shape carrying `item_created` and `item_updated` (the delta that forced
|
|
79
|
+
the bump — a version 2 consumer validating issue members exactly refuses the
|
|
80
|
+
six-member shape); the patch field set widening from `number`/`priority` to
|
|
81
|
+
`priority`/`depends_on`/`related`; number as the core-assigned immutable item
|
|
82
|
+
identity on schema version 2, with `create` refusing a supplied number and
|
|
83
|
+
`inspect` accepting `--number`; and `create` deriving its published path from
|
|
84
|
+
a committed `.wowbagger/layout.json`. The mutation contract's "Contract
|
|
85
|
+
versions" section carries the full enumeration. The legacy work-claim,
|
|
86
|
+
ledger-publication, and ledger-mutation envelopes and
|
|
87
|
+
`result.operations.work_claim.api_version` are separate version domains and
|
|
88
|
+
stay at 1; the adapter contract stays at 2.
|
|
89
|
+
|
|
90
|
+
### Added
|
|
91
|
+
|
|
92
|
+
- The README and the installed skill warn that `git mv` refuses a freshly
|
|
93
|
+
created item, because `create` writes an untracked file and the `git add -A`
|
|
94
|
+
behind it in an unchecked batch commits the item at the ledger root instead.
|
|
95
|
+
Both state the safe sequence: plain `mv`, then `git add`, checking every exit
|
|
96
|
+
code before the commit. The warning sits in the `0.1.0-alpha.4` boundary text
|
|
97
|
+
that already tells consumers that core ignores the layout file.
|
|
98
|
+
- **`patch` can replace an item body.** `set.body` takes a JSON string that
|
|
99
|
+
replaces the whole body under `create`'s body rules, so a consumer whose
|
|
100
|
+
items mirror an external card updates them through the managed path instead
|
|
101
|
+
of hand-editing the Markdown. A body patch rewrites no frontmatter byte —
|
|
102
|
+
anchors, aliases, comments, quoting, styles, member order, and extension
|
|
103
|
+
members all survive, and only `updated` changes, as it does for every patch.
|
|
104
|
+
A body may be set in the same `set` as `priority`, `depends_on`, or
|
|
105
|
+
`related`, in one compare-and-swap write. `null` is refused at `/set/body`:
|
|
106
|
+
the body is a region of the file, so removing it means `""`, not null. A
|
|
107
|
+
claimed item, a stale revision, and a non-string body refuse as before. This
|
|
108
|
+
widens the patch request schema inside core contract version 3 and does not
|
|
109
|
+
move the version.
|
|
110
|
+
- One envelope rule now covers every `--json` response. The mutation contract
|
|
111
|
+
states the response domains (core, work-claim, ledger-publication,
|
|
112
|
+
ledger-mutation, and bare result), the dispatch steps a generic consumer
|
|
113
|
+
follows, which domain each command's success and each refusal class answers
|
|
114
|
+
in, and the exact root members of each shape. Both sanctioned exceptions are
|
|
115
|
+
stated with their reasons: `validate` and `ready` stay bare results because
|
|
116
|
+
scripts and fixtures depend on those bytes, and a claim-fenced refusal to
|
|
117
|
+
`create`, `transition`, or `patch` answers in the `ledger-mutation` domain
|
|
118
|
+
with `command: "<command>-v1"` and `contract_version: 1` because it is the
|
|
119
|
+
work-claim contract refusing, not the core contract. The work-claim contract
|
|
120
|
+
now names all three of its `namespace` values.
|
|
121
|
+
`spec/fixtures/envelope-domains/manifest.json` pins all 37 response classes,
|
|
122
|
+
and `test/envelope-dispatch.test.js` walks every one of them through the
|
|
123
|
+
documented dispatch rule and rejects drift in either direction. No emitted
|
|
124
|
+
byte changed and no contract version moved.
|
|
125
|
+
- `report` now renders a sequencing dashboard instead of a state snapshot. The
|
|
126
|
+
HTML opens with **Work next**, the ready set in a recommended order with the
|
|
127
|
+
factors that placed each entry printed beside it; then **Attention**, naming
|
|
128
|
+
blockers by number, the oldest open work with its age, and started work past
|
|
129
|
+
this ledger's own 85th-percentile cycle time; then an evidence layer with
|
|
130
|
+
aging buckets, weekly arrivals against completions, accept-to-complete cycle
|
|
131
|
+
time, and a Monte Carlo forecast as 50 and 85 percent bands. State counts,
|
|
132
|
+
item cards, and swarm batches remain, below that decision surface. Relations
|
|
133
|
+
and readiness reasons inside the drill-down now name items by number.
|
|
134
|
+
Ordering is a report-layer derivation, recomputed from ledger bytes at render
|
|
135
|
+
time and never persisted: `ready --json`, its four-step order, and the
|
|
136
|
+
mutation contract are unchanged. The report file stays self-contained with no
|
|
137
|
+
external runtime dependency.
|
|
138
|
+
- Report configuration accepts two more `fields` mappings, `class` and `due`.
|
|
139
|
+
`class` is a class of service from `expedite | fixed-date | standard |
|
|
140
|
+
intangible`; `expedite` lifts an item above every other ready item, an absent
|
|
141
|
+
value means `standard`, and an unrecognised value is ranked as standard and
|
|
142
|
+
reported in the report rather than dropped. `due` is an ISO calendar date
|
|
143
|
+
ordered by proximity. Both ride the existing extension-member channel, so no
|
|
144
|
+
core field carries them.
|
|
145
|
+
- The commit-per-mutation invariant is documented. On a provisioned ledger,
|
|
146
|
+
every mutation must be committed to Git before the next mutating command,
|
|
147
|
+
and `claim-verify` is the reconciliation procedure for the exit 6
|
|
148
|
+
`publication-reconciliation-required` refusal. The mutation contract, the
|
|
149
|
+
work-claim contract, the README, and the installed skill's claimed and
|
|
150
|
+
unclaimed loops all state the rule and the loop it implies. The mutation
|
|
151
|
+
contract also records why validating against working-tree bytes was
|
|
152
|
+
rejected.
|
|
153
|
+
- `claim capabilities --ledger <dir> --json` now advertises
|
|
154
|
+
`result.backend.write_serialization`. A provisioned Git-journal backend
|
|
155
|
+
reports `scope: "all-worktrees-of-one-repository"` and
|
|
156
|
+
`blocks_until: "peer-commit-visible-in-this-checkout"`; an unprovisioned
|
|
157
|
+
backend reports `scope: "none"`. This makes the serialization the shared
|
|
158
|
+
Git-common-directory journal already performed discoverable instead of
|
|
159
|
+
implied. The core `capabilities` envelope is unchanged; this change is not
|
|
160
|
+
one of the version 3 deltas.
|
|
161
|
+
|
|
162
|
+
- A `date-before-created` or `date-before-updated` issue now carries
|
|
163
|
+
`item_created` and `item_updated` after `related_ids` — the target item's own
|
|
164
|
+
dates at refusal time, both dates on both codes, on `transition` and `patch`
|
|
165
|
+
alike. One refusal now states the whole acceptable date window, so correcting
|
|
166
|
+
the request no longer costs an `inspect` round-trip. No other issue code
|
|
167
|
+
changes shape; a consumer that validates issue members exactly must accept
|
|
168
|
+
six members for these two codes. This widening is the reason the core
|
|
169
|
+
contract version moves to 3 (see Changed, above).
|
|
170
|
+
The mutation contract and the installed skill now also state that `create`
|
|
171
|
+
derives `created` from the ULID timestamp, which is UTC, with the
|
|
172
|
+
across-midnight example that produces this refusal.
|
|
173
|
+
|
|
174
|
+
### Documentation
|
|
175
|
+
|
|
176
|
+
- **`create` stays journal-silent, and the work-claim contract now says why.**
|
|
177
|
+
Section 3.1 already stated that `create` records no claim-journal entry and
|
|
178
|
+
therefore never blocks a sibling worktree. It now records the decision to
|
|
179
|
+
keep that asymmetry and the three reasons behind it: create's publication is
|
|
180
|
+
already atomic, no-clobber, and byte-verified; journaling create would
|
|
181
|
+
serialize every worktree on the highest-volume mutation; and the remaining
|
|
182
|
+
exposure window closes at the item's first `transition` or `patch`. The
|
|
183
|
+
window is stated honestly — until that first journal-visible mutation an
|
|
184
|
+
out-of-protocol overwrite of a created item is not detected, and a commit
|
|
185
|
+
alone does not close the window, because reconciliation compares only the
|
|
186
|
+
revisions the journal expects. `test/create-journal-asymmetry.test.js` pins
|
|
187
|
+
both halves end to end. No behaviour changed.
|
|
188
|
+
|
|
189
|
+
### Fixed
|
|
190
|
+
|
|
191
|
+
- A claim-fence refusal no longer reaches the agent as
|
|
192
|
+
`mutation-outcome-unknown`. Both adapter engines classified every response
|
|
193
|
+
with the core envelope validator, so a fenced refusal — `namespace:
|
|
194
|
+
"ledger-mutation"`, `command: "<command>-v1"`, `contract_version: 1`, `state:
|
|
195
|
+
"unchanged"` — failed core validation and became "the mutation may have been
|
|
196
|
+
applied; inspect current state before retrying", on every fenced refusal on a
|
|
197
|
+
provisioned ledger, about a write that provably never ran. The adapter now
|
|
198
|
+
dispatches on the response domain first, exactly as the mutation contract's
|
|
199
|
+
section 2 rule requires, and validates a fenced refusal on the work-claim
|
|
200
|
+
contract's terms: `claimed-item-write-refused` on `create`,
|
|
201
|
+
`active-claim-write-refused` on `transition` and `patch`, and
|
|
202
|
+
`claim-store-unavailable` on any mutation, each with its pinned message, exit,
|
|
203
|
+
and permitted states, its read-back bound to the item the caller asked to
|
|
204
|
+
write, and its reason plus findings and remediation forwarded verbatim. A
|
|
205
|
+
`claim-store-unavailable` refusal that declares `state: "unknown"` stays an
|
|
206
|
+
unknown outcome, and so does any namespaced envelope the adapter cannot
|
|
207
|
+
classify. Adapter contract section 6.1 states the rule and the honest-outcome
|
|
208
|
+
guarantee; five conformance vectors pin it, the differential test replays each
|
|
209
|
+
through both engines, and no version moved in either domain.
|
|
210
|
+
- A mutation on a claim-protected ledger now reads the complete ledger twice
|
|
211
|
+
instead of three times. Journal reconciliation and the mutation engine's
|
|
212
|
+
pre-lock phase were separate unlocked reads of the same directory inside one
|
|
213
|
+
claim-lock hold, and reconciliation writes nothing a complete load reads, so
|
|
214
|
+
the pre-lock phase reuses reconciliation's snapshot. On a 1,500-item
|
|
215
|
+
provisioned fixture a create fell from about 1.15 s to about 0.89 s and a
|
|
216
|
+
transition from about 1.17 s to about 0.91 s, matching one full load at about
|
|
217
|
+
0.29 s. The read under lock stays: it is what decides the revision
|
|
218
|
+
compare-and-swap and the lock-closure stability check, and every decision
|
|
219
|
+
drawn from the shared snapshot is re-made against it. A lock-closure retry
|
|
220
|
+
still reads fresh. No validation rule changed, and a mutation on a plain
|
|
221
|
+
directory is unaffected.
|
|
222
|
+
- A mutation on a large provisioned ledger no longer spends its wall time in
|
|
223
|
+
process spawns. Git HEAD reconciliation read every committed item with its
|
|
224
|
+
own `git show`, one subprocess per item, serially; it now reads them with
|
|
225
|
+
one `git cat-file --batch` subprocess per 16 MiB of tree content. On a
|
|
226
|
+
1,500-item fixture a create fell from about 15.4 s to about 1.2 s and a
|
|
227
|
+
transition from about 15.4 s to about 1.3 s. The reconciliation reads the
|
|
228
|
+
same bytes for the same items, and no validation is skipped: candidate
|
|
229
|
+
validation still validates the complete ledger.
|
|
230
|
+
|
|
231
|
+
- Every reconciliation finding that blocks a mutation now carries a
|
|
232
|
+
`remediation` string naming the path to act on and `claim-verify`.
|
|
233
|
+
`revision-regression`, `legacy-mutation-outcome-unknown`, and
|
|
234
|
+
`publication-outcome-unknown` previously blocked with no recovery action;
|
|
235
|
+
they now also carry `expected_path` when it is identifiable.
|
|
236
|
+
|
|
237
|
+
- A committed `.wowbagger/layout.json` now binds the ledger's item directory.
|
|
238
|
+
`create` derives its path from that configuration. Validation rejects parsed
|
|
239
|
+
items outside it, special or symbolic layout files, and metadata-directory
|
|
240
|
+
aliases. Malformed configuration fails closed. Ledgers without the file
|
|
241
|
+
retain the root-level `<id>.md` layout.
|
|
242
|
+
- A refused legacy mutation and a clean `claim-verify` now leave the ledger
|
|
243
|
+
working tree byte-identical. The tracked reconciliation log projects only
|
|
244
|
+
journal entries that record a decision, so per-invocation clock entries no
|
|
245
|
+
longer dirty it, and a successful legacy mutation now projects its own
|
|
246
|
+
entries before returning instead of one command later. Batch tooling no
|
|
247
|
+
longer needs to stage the log after a failure.
|
|
248
|
+
- `claim-verify` now classifies stale writes as unauthorized revisions, missing
|
|
249
|
+
Git finalization, worktree synchronization, or pending claimed publication.
|
|
250
|
+
Working-tree deletions of an authorized Git revision are unauthorized.
|
|
251
|
+
Findings name the expected item path and give a direct recovery action.
|
|
252
|
+
- The contracts and the skill now state that a provisioned ledger's claim
|
|
253
|
+
journal serializes every worktree of one repository, and that a recorded
|
|
254
|
+
write blocks mutations in the other worktrees until its commit is visible
|
|
255
|
+
there. `limits.cross_worktree_coordination: false` is documented as "the
|
|
256
|
+
core never synchronizes checkouts", not as independent worktree writes.
|
|
257
|
+
Both stale-write remedies, the moving-`expected_revision` trap, and the
|
|
258
|
+
failed copy-the-item-in workaround are documented and pinned by tests.
|
|
259
|
+
|
|
260
|
+
## 0.1.0-alpha.4 - 2026-08-14
|
|
261
|
+
|
|
262
|
+
### Added
|
|
263
|
+
|
|
264
|
+
- `report` validates a ledger and atomically writes a deterministic,
|
|
265
|
+
self-contained HTML report from `.wowbagger/report.json`. The report includes
|
|
266
|
+
canonical readiness, semantic-field search, filters, sorting, grouping,
|
|
267
|
+
three detail levels, terminal history, and optional area-diverse swarm
|
|
268
|
+
batches. This repository includes a local report configuration and ignores
|
|
269
|
+
the generated artifact.
|
|
270
|
+
|
|
271
|
+
### Fixed
|
|
272
|
+
|
|
273
|
+
- The Claude Code adapter now declares Darwin `supported`. Native Darwin
|
|
274
|
+
conformance passes all 183 common-vector assertions across all 15 cases, so
|
|
275
|
+
configured consumer workspaces can invoke the published adapter read path.
|
|
9
276
|
|
|
10
277
|
## 0.1.0-alpha.3 - 2026-08-12
|
|
11
278
|
|
package/README.md
CHANGED
|
@@ -14,13 +14,15 @@ putting a database or hosted service inside your repository.
|
|
|
14
14
|
> scope is deliberately narrow: cooperative writers in one working copy, one
|
|
15
15
|
> item at a time. A Claude Code adapter and plugin ship from this
|
|
16
16
|
> repository; the adapter answers the negotiation surface of the harness-neutral
|
|
17
|
-
> contract and passes all
|
|
18
|
-
>
|
|
19
|
-
>
|
|
20
|
-
> definitions are not
|
|
17
|
+
> contract and passes all 196 assertions across all 15 cases on native Darwin.
|
|
18
|
+
> The Claude Code adapter declares Darwin `supported`; all other shipped adapter
|
|
19
|
+
> platform declarations remain `unverified`. The shipped core mutation contract
|
|
20
|
+
> and adapter contract are version 2; their frozen version 1 definitions are not
|
|
21
|
+
> silently negotiated.
|
|
21
22
|
>
|
|
22
|
-
>
|
|
23
|
-
>
|
|
23
|
+
> A work claim is not a lock or an exclusive dispatch lease. On Git-backed
|
|
24
|
+
> ledgers, claims coordinate cooperating agents through a durable journal in
|
|
25
|
+
> Git's shared common directory. `claim acquire` uses
|
|
24
26
|
> observed-state compare-and-swap. `publish-claimed` fences one item against
|
|
25
27
|
> the active owner generation and expected revision. `claim-verify` reconciles
|
|
26
28
|
> response-loss and post-merge outcomes. This is **merge-coordinated**, not
|
|
@@ -34,7 +36,7 @@ Install the core CLI, then verify it:
|
|
|
34
36
|
```sh
|
|
35
37
|
npm install -g wowbagger@next # public npm prerelease
|
|
36
38
|
# or, from this release's Git tag:
|
|
37
|
-
# npm install -g github:lstutzman/wowbagger#v0.1.0-alpha.
|
|
39
|
+
# npm install -g github:lstutzman/wowbagger#v0.1.0-alpha.5
|
|
38
40
|
wowbagger capabilities --json
|
|
39
41
|
```
|
|
40
42
|
|
|
@@ -52,6 +54,38 @@ core contract version 2. It refuses an absent or incompatible core. It will not
|
|
|
52
54
|
fall back to editing ledger files by hand, because that would bypass validation
|
|
53
55
|
and atomic publication.
|
|
54
56
|
|
|
57
|
+
Decide where items live **before your first `create`**. A ledger publishes items
|
|
58
|
+
to `<ledger>/<id>.md` unless a committed `<ledger>/.wowbagger/layout.json` binds
|
|
59
|
+
a subdirectory:
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
mkdir -p path/to/ledger/.wowbagger path/to/ledger/items
|
|
63
|
+
echo '{"layout_version":1,"items_directory":"items"}' > path/to/ledger/.wowbagger/layout.json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`layout_version` must be `1` and `items_directory` names the committed item
|
|
67
|
+
directory. `create` then publishes atomically to `<items_directory>/<id>.md`,
|
|
68
|
+
and validation rejects parsed items outside it. Commit the directory the file
|
|
69
|
+
names — `create` publishes into an existing directory and does not make one.
|
|
70
|
+
Nothing is renamed after a create. Cores at `0.1.0-alpha.4` and earlier ignore
|
|
71
|
+
the file and publish every item at the ledger root.
|
|
72
|
+
|
|
73
|
+
On such a core, relocating an item by hand has a trap. `create` writes an
|
|
74
|
+
untracked file, so `git mv` refuses the path it just published; an unchecked
|
|
75
|
+
batch then runs `git add -A` and commits the item at the ledger root, where it
|
|
76
|
+
silently stays. Use plain `mv`, then `git add` both paths, and check the exit
|
|
77
|
+
code of every command before the commit:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
mv path/to/ledger/<id>.md path/to/ledger/items/<id>.md || exit 1
|
|
81
|
+
git add path/to/ledger || exit 1
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
A committed item outside the configured items directory then fails validation
|
|
85
|
+
and refuses every read and every guarded mutation on that ledger, including
|
|
86
|
+
ones that never touch it. The refusal names the expected path and the
|
|
87
|
+
relocation that repairs it.
|
|
88
|
+
|
|
55
89
|
For an isolated consumer pilot, create or select the disposable worktree before
|
|
56
90
|
the agent starts. Then launch a new session with that worktree as its project
|
|
57
91
|
root. Follow the [isolated dogfood pilot runbook](docs/isolated-dogfood-pilot.md);
|
|
@@ -70,7 +104,7 @@ two supported install routes:
|
|
|
70
104
|
- **npm registry** — `npm install -g wowbagger@next` installs the current
|
|
71
105
|
prerelease.
|
|
72
106
|
- **git tag** —
|
|
73
|
-
`npm install -g github:lstutzman/wowbagger#v0.1.0-alpha.
|
|
107
|
+
`npm install -g github:lstutzman/wowbagger#v0.1.0-alpha.5` installs this
|
|
74
108
|
release. Installing at a ref installs the core and every adapter that ref
|
|
75
109
|
carries.
|
|
76
110
|
|
|
@@ -90,10 +124,10 @@ instructions can depend on additive behavior from that release.
|
|
|
90
124
|
|
|
91
125
|
- **Node.js:** 20 and later. The adapter conformance vectors run against Node
|
|
92
126
|
20 and the current runtime before each release.
|
|
93
|
-
- **Platforms:** the core runs wherever Node.js runs
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
because the CLI starts.
|
|
127
|
+
- **Platforms:** the core runs wherever Node.js runs. The Claude Code adapter
|
|
128
|
+
declares Darwin `supported` from native common-vector evidence. Linux,
|
|
129
|
+
Windows, and the other shipped adapter targets remain `unverified`; do not
|
|
130
|
+
infer support only because the CLI starts.
|
|
97
131
|
- **Other tooling:** `wowbagger` manages a Git-tracked Markdown ledger. It
|
|
98
132
|
needs an accessible Git checkout for work-claim and namespace operations.
|
|
99
133
|
Before `provision`, run
|
|
@@ -134,7 +168,7 @@ Upgrade the pieces you installed:
|
|
|
134
168
|
|
|
135
169
|
```sh
|
|
136
170
|
npm install -g wowbagger@next # public npm registry
|
|
137
|
-
npm install -g github:lstutzman/wowbagger#v0.1.0-alpha.
|
|
171
|
+
npm install -g github:lstutzman/wowbagger#v0.1.0-alpha.5 # immutable Git release
|
|
138
172
|
git pull && npm ci # or: a direct checkout
|
|
139
173
|
```
|
|
140
174
|
|
|
@@ -151,12 +185,14 @@ wowbagger capabilities --json
|
|
|
151
185
|
```
|
|
152
186
|
|
|
153
187
|
The plugin requires its exact core distribution version and top-level core
|
|
154
|
-
`contract_version:
|
|
188
|
+
`contract_version: 3`. Direct API consumers must check the contract version
|
|
155
189
|
they support; installed plugin users must also keep the plugin and core
|
|
156
190
|
distribution versions equal.
|
|
157
191
|
|
|
158
192
|
The shipped adapter selects only adapter contract version 2 and requires core
|
|
159
|
-
contract version
|
|
193
|
+
contract version 3. The adapter contract and the core contract are separate
|
|
194
|
+
version domains: the adapter stays at 2 while the core moves to 3. A v1-only
|
|
195
|
+
consumer receives
|
|
160
196
|
`unsupported-adapter-contract-version`; it does not receive v2 behavior. The
|
|
161
197
|
schema-2 transport is available. Ledger migration remains a separate quiesced
|
|
162
198
|
maintenance operation. The
|
|
@@ -190,6 +226,11 @@ core, these are the changes most likely to touch you:
|
|
|
190
226
|
`core.status: "triage"`, and the refusal for a caller-supplied `status`
|
|
191
227
|
names the accepting transition (triage to backlog) that makes an item
|
|
192
228
|
ready.
|
|
229
|
+
- **Bind a subdirectory layout in the ledger, not in each runner.** Commit
|
|
230
|
+
`<ledger>/.wowbagger/layout.json` with
|
|
231
|
+
`{"layout_version":1,"items_directory":"items"}`. `create` then derives
|
|
232
|
+
`<ledger>/items/<id>.md`; validation rejects parsed items outside `items/`.
|
|
233
|
+
Without the file, the compatible layout remains `<ledger>/<id>.md`.
|
|
193
234
|
|
|
194
235
|
## Why the name?
|
|
195
236
|
|
|
@@ -255,9 +296,9 @@ This checkout ships three adapter packages on one shared entrypoint runtime:
|
|
|
255
296
|
[`adapters/claude-code/`](adapters/claude-code/), [`adapters/codex/`](adapters/codex/),
|
|
256
297
|
and [`adapters/opencode/`](adapters/opencode/). Each answers the section 3.3 bootstrap
|
|
257
298
|
wire with its own identity and honest host declaration. The native Darwin
|
|
258
|
-
Claude Code report passes all
|
|
299
|
+
Claude Code report passes all 196 assertions across all 15 cases — run
|
|
259
300
|
`node spec/run-adapter-implementation.js` to see the evidence. Codex and
|
|
260
|
-
OpenCode share the version 2 engine and execute all
|
|
301
|
+
OpenCode share the version 2 engine and execute all 196 assertions with
|
|
261
302
|
`--target codex` or `--target opencode`, but both target reports remain `fail`
|
|
262
303
|
pending target-specific evidence. Invocation forwarding, path and limit guards,
|
|
263
304
|
approval, and context all enter through the shared shipped engine. Platform
|
|
@@ -277,6 +318,7 @@ npm ci
|
|
|
277
318
|
./bin/wowbagger.js validate --ledger path/to/ledger --json
|
|
278
319
|
./bin/wowbagger.js ready --ledger path/to/ledger --as-of 2030-01-15 --json
|
|
279
320
|
./bin/wowbagger.js ready --ledger path/to/ledger --as-of 2030-01-15
|
|
321
|
+
./bin/wowbagger.js report --ledger path/to/ledger --as-of 2030-01-15 --json
|
|
280
322
|
./bin/wowbagger.js capabilities --json
|
|
281
323
|
./bin/wowbagger.js mint-id --json
|
|
282
324
|
./bin/wowbagger.js inspect --ledger path/to/ledger --id wb_... --json
|
|
@@ -316,6 +358,97 @@ directories ending in `.md` remain containers and are traversed. These checks
|
|
|
316
358
|
provide deterministic read hygiene; they are not a sandbox against a privileged
|
|
317
359
|
process racing filesystem changes.
|
|
318
360
|
|
|
361
|
+
`report` validates the complete ledger, reads `.wowbagger/report.json`, and
|
|
362
|
+
atomically publishes one self-contained HTML file. The output must be outside
|
|
363
|
+
the ledger. Relative configured output paths resolve from `.wowbagger/`;
|
|
364
|
+
relative `--out` overrides resolve from the caller's working directory.
|
|
365
|
+
|
|
366
|
+
```json
|
|
367
|
+
{
|
|
368
|
+
"report_version": 1,
|
|
369
|
+
"repository": { "name": "Example repository", "logo": "logo.svg" },
|
|
370
|
+
"title": "Ledger report",
|
|
371
|
+
"output": "../../ledger-report.html",
|
|
372
|
+
"fields": {
|
|
373
|
+
"area": "/priority_area",
|
|
374
|
+
"complexity": "/complexity",
|
|
375
|
+
"rank": "/priority_rank",
|
|
376
|
+
"class": "/class",
|
|
377
|
+
"due": "/due"
|
|
378
|
+
},
|
|
379
|
+
"swarm": { "eligible_complexities": ["small", "medium"] }
|
|
380
|
+
}
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
`repository.logo`, `fields`, and `swarm` are optional. Field values resolve
|
|
384
|
+
from parsed frontmatter with RFC 6901 JSON Pointers. A swarm requires mapped
|
|
385
|
+
`area` and `complexity` fields. The report fetches nothing at view time.
|
|
386
|
+
|
|
387
|
+
The report opens with **Work next**: the ready set in a recommended order,
|
|
388
|
+
each entry carrying the factors that placed it. Below it sit **Attention**
|
|
389
|
+
(blocked work naming its blockers, the oldest open work, and started work past
|
|
390
|
+
this ledger's own 85th-percentile cycle time), the **evidence layer**
|
|
391
|
+
(aging buckets, weekly arrivals against completions, accept-to-complete cycle
|
|
392
|
+
time, and a Monte Carlo forecast as 50 and 85 percent bands), and the **ledger
|
|
393
|
+
graph**. State counts, item cards, filters, grouping, detail levels, terminal
|
|
394
|
+
history, and area-diverse ready batches all remain, demoted below that
|
|
395
|
+
decision surface.
|
|
396
|
+
|
|
397
|
+
### The ledger graph
|
|
398
|
+
|
|
399
|
+
Below the evidence layer the report draws the whole ledger as a force-directed
|
|
400
|
+
3D graph. Every item is a node, labelled `#N`, coloured by readiness for open
|
|
401
|
+
items and by terminal status for closed ones, and sized by the same transitive
|
|
402
|
+
unblocking leverage the recommended order uses. Edges run from a prerequisite
|
|
403
|
+
or a parent to the item it releases: a `depends_on` edge is straight and
|
|
404
|
+
arrowed, a `parent` edge is curved and unarrowed. Hovering or clicking a node
|
|
405
|
+
opens a card with its number, title, status, age, leverage, and the same
|
|
406
|
+
reasons line the ranked list prints for it.
|
|
407
|
+
|
|
408
|
+
The renderer is [`3d-force-graph`](https://github.com/vasturiano/3d-force-graph)
|
|
409
|
+
over Three.js, vendored into `vendor/3d-force-graph/` at a pinned version
|
|
410
|
+
`1.80.0` with its upstream SHA-256 recorded in `VERSIONS.json` and pinned by a
|
|
411
|
+
test. It is inlined into the report at generation time. Nothing is fetched from
|
|
412
|
+
a CDN, at generation time or at view time, and the report's content security
|
|
413
|
+
policy forbids every remote load. The bundle costs roughly 1.3 MB of the
|
|
414
|
+
report's size; the report stays one self-contained file you can attach, open
|
|
415
|
+
offline, and share.
|
|
416
|
+
|
|
417
|
+
Without WebGL the graph section says so and expands its own roster instead: one
|
|
418
|
+
row per node, carrying that node's number, title, status, age, leverage, and
|
|
419
|
+
reasons. No decision-relevant content exists only in the 3D view.
|
|
420
|
+
|
|
421
|
+
The recommended order is a report-layer derivation. It is recomputed from
|
|
422
|
+
ledger bytes at render time, never persisted, never a mutation, and it does not
|
|
423
|
+
change `ready`: the core still selects and sorts by priority, created date,
|
|
424
|
+
then ID. Ordering runs as separate, visible steps rather than one opaque score
|
|
425
|
+
— expedite class, then due proximity, then transitive unblocking leverage over
|
|
426
|
+
`depends_on`, then epic enablement from `parent`, then priority, then age, then
|
|
427
|
+
the mapped `complexity` as a WSJF-style size denominator — and every step that
|
|
428
|
+
placed an entry is printed beside it.
|
|
429
|
+
|
|
430
|
+
Two mapped fields carry the value dimensions the schema deliberately does not:
|
|
431
|
+
|
|
432
|
+
- **`class`** — a class of service, one of `expedite`, `fixed-date`,
|
|
433
|
+
`standard`, or `intangible`. `expedite` lifts an item above every other ready
|
|
434
|
+
item. An absent value means `standard`. An unrecognised value is ranked as
|
|
435
|
+
standard and reported by number in the report, never silently dropped.
|
|
436
|
+
- **`due`** — an ISO calendar date. The nearest due date sorts first and an
|
|
437
|
+
overdue one sorts first of all; an item with no due date sorts behind every
|
|
438
|
+
dated one at that step.
|
|
439
|
+
|
|
440
|
+
Both ride the ordinary extension-member channel, so the core neither reads nor
|
|
441
|
+
validates them. `complexity` weighs `xs`/`s`/`small` as 1, `m`/`medium` as 2,
|
|
442
|
+
`l`/`large` as 3, and `xl`/`extra-large` as 5; any other value carries no
|
|
443
|
+
weight and is shown as written.
|
|
444
|
+
|
|
445
|
+
This repository keeps its report configuration in
|
|
446
|
+
`ledger/.wowbagger/report.json`. Generate the ignored local report with:
|
|
447
|
+
|
|
448
|
+
```sh
|
|
449
|
+
npm run report -- --as-of 2026-08-14
|
|
450
|
+
```
|
|
451
|
+
|
|
319
452
|
`inspect` returns a lossless raw-byte snapshot and its SHA-256 revision.
|
|
320
453
|
`create` publishes only a caller-supplied canonical ID through atomic
|
|
321
454
|
no-clobber publication — `mint-id` prints one, so no consumer writes base32
|
|
@@ -327,6 +460,23 @@ nothing else — under the same lock and compare-and-swap. See
|
|
|
327
460
|
[the mutation contract](docs/mutation-contract.md) for the JSON request,
|
|
328
461
|
response, recovery, and scope details.
|
|
329
462
|
|
|
463
|
+
### Diagnosing an invalid ledger
|
|
464
|
+
|
|
465
|
+
One invalid item refuses every read and every guarded mutation on that ledger,
|
|
466
|
+
including commands that never touch it. That refusal is the diagnosis, and no
|
|
467
|
+
command asks you to parse the Markdown by hand:
|
|
468
|
+
|
|
469
|
+
- `validate --json` lists every error. An error whose repair the validator can
|
|
470
|
+
derive also carries `expected_path` and a `remediation` naming the repair.
|
|
471
|
+
- `inspect` still refuses with exit 3 `ledger-invalid` — a revision from an
|
|
472
|
+
unjudged ledger must never look like a mutation precondition — but the
|
|
473
|
+
refusal carries `error.details.item`, the complete snapshot of the item you
|
|
474
|
+
asked for, whenever no validation error names that item's path. A faulted
|
|
475
|
+
item is withheld; `validate` already names its repair.
|
|
476
|
+
- `claim-verify --json` reports `result.ledger_validation`. Exit 0 with
|
|
477
|
+
`findings: []` and `ledger_validation.valid: false` says the claim journal is
|
|
478
|
+
consistent and validation alone is blocking every mutation.
|
|
479
|
+
|
|
330
480
|
`provision` binds one ledger namespace to the repository. `claim` manages
|
|
331
481
|
durable acquire, read, renew, and release decisions. `publish-claimed` accepts
|
|
332
482
|
the exact candidate item bytes and fences their publication against the active
|
|
@@ -347,6 +497,51 @@ refuses rather than guessing. The shipped plugin skill also requires its exact
|
|
|
347
497
|
core distribution version. Direct checkout use—`./bin/wowbagger.js` from a
|
|
348
498
|
clone—remains supported and is what this repository's own ledger uses.
|
|
349
499
|
|
|
500
|
+
## Commit each mutation before the next one
|
|
501
|
+
|
|
502
|
+
On a **provisioned** ledger — one where `provision` has bound a namespace and
|
|
503
|
+
`claim capabilities` reports `mode: "merge-coordinated"` — there is one
|
|
504
|
+
operating rule:
|
|
505
|
+
|
|
506
|
+
**Commit each mutation to Git before running the next mutating command.**
|
|
507
|
+
|
|
508
|
+
The durable claim store validates every recorded mutation against Git `HEAD`,
|
|
509
|
+
not against working-tree bytes. That is what makes a recorded mutation durable
|
|
510
|
+
rather than a local edit one `git checkout` away from vanishing. An uncommitted
|
|
511
|
+
mutation is an unreconciled mutation, so the next `create`, `transition`, or
|
|
512
|
+
`patch` refuses instead of writing on top of it.
|
|
513
|
+
|
|
514
|
+
The loop that works:
|
|
515
|
+
|
|
516
|
+
```sh
|
|
517
|
+
./bin/wowbagger.js create --ledger path/to/ledger --input request.json --json
|
|
518
|
+
git add path/to/ledger && git commit -m "Record the mutation"
|
|
519
|
+
./bin/wowbagger.js claim-verify --ledger path/to/ledger --json
|
|
520
|
+
./bin/wowbagger.js transition --ledger path/to/ledger --input next.json --json
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
Skip the commit and the next command returns exit 6:
|
|
524
|
+
|
|
525
|
+
```json
|
|
526
|
+
{"ok":false,"namespace":"ledger-mutation","command":"create-v1","contract_version":1,
|
|
527
|
+
"state":"unchanged","error":{"code":"claim-store-unavailable",
|
|
528
|
+
"message":"The durable claim store is unavailable.",
|
|
529
|
+
"details":{"reason":"publication-reconciliation-required","findings":[{
|
|
530
|
+
"code":"stale-write-detected","reason":"git-finalization-required",
|
|
531
|
+
"expected_path":"wb_....md",
|
|
532
|
+
"remediation":"Commit wb_....md in Git, then run claim-verify."}]}}}
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
`state: "unchanged"` is exact — nothing was written. **`claim-verify` is the
|
|
536
|
+
reconciliation procedure.** Read `details.findings`, do what each
|
|
537
|
+
`remediation` string says, run `claim-verify` until it returns exit 0, then
|
|
538
|
+
repeat the refused command.
|
|
539
|
+
|
|
540
|
+
Full rules, the other blocking finding codes, and why validating against
|
|
541
|
+
working-tree bytes was rejected are in
|
|
542
|
+
[the mutation contract](docs/mutation-contract.md) section 12 and
|
|
543
|
+
[the work-claim contract](docs/work-claim-contract.md).
|
|
544
|
+
|
|
350
545
|
## Verify a checkout
|
|
351
546
|
|
|
352
547
|
The development workflow is intentionally self-hosted: edit code and ledger
|
|
@@ -449,9 +644,9 @@ It is the durable work ledger beneath those systems.
|
|
|
449
644
|
- Separate optional reusable mechanisms from consumer-specific policy.
|
|
450
645
|
- Stabilize the machine-readable command contract and compatibility evidence.
|
|
451
646
|
- Ship Claude Code and Codex adapters. **Claude Code, Codex, and OpenCode
|
|
452
|
-
packages share the version 2 engine; the Claude Code
|
|
453
|
-
|
|
454
|
-
declarations remain unverified.**
|
|
647
|
+
packages share the version 2 engine; the Claude Code manifest declares Darwin
|
|
648
|
+
`supported` after passing all 196 native assertions. Other adapter targets and
|
|
649
|
+
platform declarations remain unverified.**
|
|
455
650
|
- Document the generic tool contract for other agent harnesses.
|
|
456
651
|
- Implement merge-coordinated work claims for cooperating Git worktrees.
|
|
457
652
|
**Implemented with durable claim operations, claim-protected single-item
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"adapter_version": "0.1.0",
|
|
5
5
|
"adapter_contract_versions": [2],
|
|
6
6
|
"bootstrap_wire_version": 1,
|
|
7
|
-
"required_core_contract_version":
|
|
7
|
+
"required_core_contract_version": 3,
|
|
8
8
|
"entrypoints": {
|
|
9
9
|
"describe": {
|
|
10
10
|
"kind": "command",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"platforms": {
|
|
21
|
-
"darwin": "
|
|
21
|
+
"darwin": "supported",
|
|
22
22
|
"linux": "unverified",
|
|
23
23
|
"win32": "unverified"
|
|
24
24
|
}
|