wowbagger 0.1.0-alpha.7 → 0.1.0-alpha.8
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 +193 -1
- package/README.md +194 -16
- package/adapters/claude-code/wowbagger-adapter.json +1 -1
- package/adapters/codex/wowbagger-adapter.json +1 -1
- package/adapters/opencode/wowbagger-adapter.json +1 -1
- package/docs/adapter-contract.md +66 -6
- package/docs/host-contract.md +287 -0
- package/docs/mutation-contract.md +558 -17
- package/docs/work-claim-contract.md +56 -24
- package/package.json +14 -1
- package/schemas/bare-ready-result.json +27 -0
- package/schemas/bare-validation-result.json +23 -0
- package/schemas/common.json +470 -0
- package/schemas/core-capabilities-response.json +346 -0
- package/schemas/core-envelope.json +141 -0
- package/schemas/core-inspect-response.json +37 -0
- package/schemas/core-inspect-workbench-response.json +340 -0
- package/schemas/core-list-error-response.json +242 -0
- package/schemas/core-list-query.json +98 -0
- package/schemas/core-list-response.json +140 -0
- package/schemas/core-report-response.json +379 -0
- package/schemas/core-transition-error-response.json +852 -0
- package/schemas/core-transition-request.json +47 -0
- package/schemas/core-transition-response.json +49 -0
- package/schemas/index.json +108 -0
- package/schemas/ledger-mutation-refusal.json +288 -0
- package/schemas/report-config-v1.json +140 -0
- package/schemas/report-config-v2.json +242 -0
- package/skills/wowbagger/SKILL.md +151 -38
- package/src/adapter/core-probe.js +87 -7
- package/src/claim-capabilities.js +4 -5
- package/src/claim-coordinator.js +15 -2
- package/src/claim-prospective.js +151 -0
- package/src/claim-publication.js +49 -9
- package/src/claim-sync.js +66 -0
- package/src/cli.js +671 -49
- package/src/extension-provision.js +33 -0
- package/src/git-autocommit.js +36 -6
- package/src/git-reconciliation.js +53 -9
- package/src/launch.js +52 -0
- package/src/lifecycle.js +153 -0
- package/src/limits.js +39 -0
- package/src/list.js +365 -0
- package/src/mutation.js +145 -118
- package/src/projection.js +39 -0
- package/src/report-graph.js +122 -21
- package/src/report-html.js +219 -51
- package/src/report-view.js +189 -0
- package/src/report.js +145 -15
- package/src/validate.js +4 -1
- package/src/workbench.js +117 -0
package/docs/adapter-contract.md
CHANGED
|
@@ -1082,6 +1082,66 @@ caller-known expected revision with the current revision and state; never
|
|
|
1082
1082
|
retry until that observation is reviewed. This distinction prevents both a
|
|
1083
1083
|
hidden committed mutation and an orphaned duplicate mutation.
|
|
1084
1084
|
|
|
1085
|
+
### 6.2 Response loss and the unknown-outcome envelope
|
|
1086
|
+
|
|
1087
|
+
Losing the response is not the same as observing a failure. A transport between
|
|
1088
|
+
the consumer and the workspace-owning host can drop after the adapter dispatched
|
|
1089
|
+
the core, and a dropped transport observes nothing about the ledger. The adapter
|
|
1090
|
+
therefore reports an unresolved mutation as unresolved, and the consumer answers
|
|
1091
|
+
it with one sequence: Dispatch once, never replay, invalidate the inspected
|
|
1092
|
+
revision, reconnect, then re-read the ledger. Re-reading returns current ledger
|
|
1093
|
+
state only. A later item state never proves that the lost dispatch caused it, so
|
|
1094
|
+
a consumer MUST NOT present it as evidence that the mutation succeeded or failed.
|
|
1095
|
+
|
|
1096
|
+
An unresolved mutation is exactly this envelope. It carries the root
|
|
1097
|
+
`mutation_outcome` member, which no other adapter result has:
|
|
1098
|
+
|
|
1099
|
+
```json
|
|
1100
|
+
{
|
|
1101
|
+
"ok": false,
|
|
1102
|
+
"adapter_contract_version": 2,
|
|
1103
|
+
"request_id": "transition-recovery-0001",
|
|
1104
|
+
"mutation_outcome": "unknown",
|
|
1105
|
+
"error": {
|
|
1106
|
+
"code": "mutation-outcome-unknown",
|
|
1107
|
+
"message": "The mutation may have been applied; inspect current state before retrying.",
|
|
1108
|
+
"details": {
|
|
1109
|
+
"command": "transition",
|
|
1110
|
+
"item_id": "wb_01Q45X474N28T5CY4GNF6YY4HM",
|
|
1111
|
+
"recovery": {
|
|
1112
|
+
"action": "validate-inspect-and-compare-revision",
|
|
1113
|
+
"expected_revision": "sha256:1111111111111111111111111111111111111111111111111111111111111111",
|
|
1114
|
+
"retry": "never-before-current-state-review"
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
},
|
|
1118
|
+
"process": {}
|
|
1119
|
+
}
|
|
1120
|
+
```
|
|
1121
|
+
|
|
1122
|
+
`details.recovery` is the bounded machine-readable form of the recovery rules
|
|
1123
|
+
above, and it has exactly one shape per command:
|
|
1124
|
+
|
|
1125
|
+
| Command | `action` | Other members | `retry` |
|
|
1126
|
+
|---|---|---|---|
|
|
1127
|
+
| `create` | `inspect-caller-known-id` | `validate_ledger_first: true` | `only-after-item-not-found-and-audited-artifact-recovery` |
|
|
1128
|
+
| `transition`, `patch` | `validate-inspect-and-compare-revision` | `expected_revision`, the caller-known revision or `null` | `never-before-current-state-review` |
|
|
1129
|
+
|
|
1130
|
+
`details` also carries `process_issue` naming the contradicted or missing
|
|
1131
|
+
observation member when the observation itself was the reason the outcome is
|
|
1132
|
+
unknown. `process` is the same bounded observation summary every transport
|
|
1133
|
+
failure carries.
|
|
1134
|
+
|
|
1135
|
+
Exit 4 is never response loss. A `revision-conflict` with the core state
|
|
1136
|
+
`unchanged` is a complete observed refusal: the adapter forwards it verbatim
|
|
1137
|
+
with `core_exit_code: 4` and no `mutation_outcome` member. It invalidates the
|
|
1138
|
+
consumer's inspected revision and requires re-inspection; relabelling it
|
|
1139
|
+
`mutation-outcome-unknown` would turn a proven non-write into an unresolved one.
|
|
1140
|
+
|
|
1141
|
+
The adapter adds no operation ID, no durable outcome store, and no replay
|
|
1142
|
+
endpoint. Once-only dispatch plus an honest unresolved outcome need no
|
|
1143
|
+
correlation identity, and adding one requires a new contract decision.
|
|
1144
|
+
|
|
1085
1145
|
## 7. Instruction inputs
|
|
1086
1146
|
|
|
1087
1147
|
The contract does not assume `CLAUDE.md`, `AGENTS.md`, any other filename,
|
|
@@ -1297,7 +1357,7 @@ adapter, so its implementation statuses remain `unverified`.
|
|
|
1297
1357
|
`node spec/run-adapter-implementation.js` accepts the same fixture directory,
|
|
1298
1358
|
evaluates transactions through the shipped Claude Code entrypoint and emits the
|
|
1299
1359
|
same result shape with an evidence platform. Its current native Darwin, Linux,
|
|
1300
|
-
and Windows runs are each `pass`:
|
|
1360
|
+
and Windows runs are each `pass`: 212 of 212 assertions and 16 of 16 cases
|
|
1301
1361
|
pass. That native common-vector evidence earns the Claude Code manifest's
|
|
1302
1362
|
Darwin, Linux, and win32 `supported` declarations.
|
|
1303
1363
|
Codex, Kimi, and generic adapter implementations remain `unverified`.
|
|
@@ -1367,7 +1427,7 @@ unproven, and no count of passing conformance assertions changes that.
|
|
|
1367
1427
|
|
|
1368
1428
|
This contract does not:
|
|
1369
1429
|
|
|
1370
|
-
- adopt Wowbagger in
|
|
1430
|
+
- adopt Wowbagger in a consumer repository;
|
|
1371
1431
|
- add vendor-specific lifecycle logic to the core;
|
|
1372
1432
|
- require an MCP server, daemon, hook, slash command, Gastown, or Beads;
|
|
1373
1433
|
- define work claims, policy ranking, or hidden persistent agent memory;
|
|
@@ -1408,14 +1468,14 @@ error registry. It changes only this versioned surface:
|
|
|
1408
1468
|
| Path or behavior | Version 2 requirement |
|
|
1409
1469
|
|---|---|
|
|
1410
1470
|
| Manifest `adapter_contract_versions` | Exactly `[2]` |
|
|
1411
|
-
| Manifest and describe required core contract | Exactly `
|
|
1471
|
+
| Manifest and describe required core contract | Exactly `5` |
|
|
1412
1472
|
| Describe `selected_adapter_contract_version` | Exactly `2` |
|
|
1413
1473
|
| Describe `core.commands` order | `capabilities`, `create`, `inspect`, `patch`, `ready`, `transition`, `validate` |
|
|
1414
1474
|
| Invoke and result `adapter_contract_version` | Exactly `2` |
|
|
1415
|
-
| Independently probed core `contract_version` | Exactly `
|
|
1475
|
+
| Independently probed core `contract_version` | Exactly `5` |
|
|
1416
1476
|
|
|
1417
1477
|
The core capability probe adapter contract version 2 requires is core
|
|
1418
|
-
contract version
|
|
1478
|
+
contract version 5. It adds exactly
|
|
1419
1479
|
`operations.patch: {"supported":true,"write_scope":"single-item","cas_scope":"exact-byte-sha256"}`,
|
|
1420
1480
|
`operations.work_claim.api_version: 2`, and
|
|
1421
1481
|
`limits.max_item_source_bytes: 8388608` as the first member of
|
|
@@ -1507,6 +1567,6 @@ receives exactly the compact refusal
|
|
|
1507
1567
|
`{"ok":false,"error":{"code":"unsupported-adapter-contract-version"}}` plus
|
|
1508
1568
|
one LF. It receives no v2 describe result and no requested core child is
|
|
1509
1569
|
launched. Conversely, an adapter that requires core contract version 1, 2, or 3 while
|
|
1510
|
-
probing a version
|
|
1570
|
+
probing a version 5 core observes `contract_version: 5` and refuses the
|
|
1511
1571
|
pairing as `core-contract-version-mismatch`; neither direction silently
|
|
1512
1572
|
receives the other version's behavior.
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# Direct-core host contract
|
|
2
|
+
|
|
3
|
+
Status: core contract version 5. This document is the supported way for a
|
|
4
|
+
non-agent consumer — a UI plugin, an editor extension, a service — to resolve,
|
|
5
|
+
launch, bound, and validate the Wowbagger core on the host that owns the
|
|
6
|
+
workspace.
|
|
7
|
+
|
|
8
|
+
It publishes what Wowbagger owns: the package seam, the process tuple, the
|
|
9
|
+
advertised limits, the response domains, the exit meanings, and the packaged
|
|
10
|
+
JSON Schemas. It states, and does not claim, what the host owns: executable
|
|
11
|
+
discovery, working directory selection, timeout, cancellation, process-tree
|
|
12
|
+
containment, stream caps, consent, and routing. Wowbagger documents these
|
|
13
|
+
requirements and their outcomes; it does not claim these facilities, because it
|
|
14
|
+
cannot enforce them from inside a child process the host started.
|
|
15
|
+
|
|
16
|
+
The behaviour this document describes is defined normatively elsewhere. Command
|
|
17
|
+
semantics live in [the mutation contract](mutation-contract.md), ledger
|
|
18
|
+
semantics in [SPEC.md](../SPEC.md), adapter semantics in [the adapter
|
|
19
|
+
contract](adapter-contract.md), and claim semantics in [the work-claim
|
|
20
|
+
contract](work-claim-contract.md). Nothing here widens any of them.
|
|
21
|
+
|
|
22
|
+
## 1. Resolving the core
|
|
23
|
+
|
|
24
|
+
The core is a Node.js program. Launching it needs four things and never a
|
|
25
|
+
shell: an absolute Node executable, the absolute `wowbagger.js` the package
|
|
26
|
+
installed, an argument array, and `shell: false`. Neither path is discovered by
|
|
27
|
+
searching a global npm directory, and neither is a platform command shim.
|
|
28
|
+
|
|
29
|
+
Wowbagger requires Node.js 20 or later. The package declares that floor in
|
|
30
|
+
`engines.node`, and the launch seam exports it as `MINIMUM_NODE_MAJOR` for a
|
|
31
|
+
host that resolves its own runtime instead of reusing the one it is running on.
|
|
32
|
+
|
|
33
|
+
~~~js
|
|
34
|
+
import { resolveCoreLaunch } from 'wowbagger';
|
|
35
|
+
|
|
36
|
+
const launch = resolveCoreLaunch(['capabilities', '--json']);
|
|
37
|
+
// { executable: <absolute Node executable>, args: [<absolute wowbagger.js>, 'capabilities', '--json'], shell: false }
|
|
38
|
+
~~~
|
|
39
|
+
|
|
40
|
+
`resolveCoreLaunch(argv, { nodeExecutable })` supplies a host-resolved runtime.
|
|
41
|
+
The executable must be an absolute path: a bare name such as `node` is refused
|
|
42
|
+
rather than left for `PATH` to answer, because PATH lookup is the discovery this
|
|
43
|
+
seam exists to remove.
|
|
44
|
+
|
|
45
|
+
A host that wants the script path alone, without importing anything, resolves
|
|
46
|
+
the published subpath:
|
|
47
|
+
|
|
48
|
+
~~~js
|
|
49
|
+
const script = fileURLToPath(import.meta.resolve('wowbagger/wowbagger.js'));
|
|
50
|
+
~~~
|
|
51
|
+
|
|
52
|
+
`CORE_SCRIPT_PATH` from the main entry is the same absolute path. Both are
|
|
53
|
+
resolved from the installed package's own location, so they are correct for a
|
|
54
|
+
global install, a local install, a workspace link, and a plain clone alike, and
|
|
55
|
+
neither depends on the caller's working directory.
|
|
56
|
+
|
|
57
|
+
The `bin` mapping still exists and is still the supported way for a person at a
|
|
58
|
+
terminal to run `wowbagger`. It is not the seam for a host: on Windows it is a
|
|
59
|
+
`.cmd` shim that cannot be spawned without a shell at all.
|
|
60
|
+
|
|
61
|
+
## 2. The process tuple
|
|
62
|
+
|
|
63
|
+
| Element | Value | Owner |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| executable | the absolute Node executable | host |
|
|
66
|
+
| argv | `[<absolute wowbagger.js>, ...coreArguments]` | Wowbagger publishes the array; the host passes it verbatim |
|
|
67
|
+
| `shell` | `false`, always and never a shell | Wowbagger |
|
|
68
|
+
| working directory | the directory that owns the ledger path | host |
|
|
69
|
+
| stdin | bounded request bytes, then EOF | host |
|
|
70
|
+
| stdout | captured, byte-exact, one JSON object and one LF | host captures; Wowbagger writes |
|
|
71
|
+
| stderr | captured; empty on every `--json` response | host captures |
|
|
72
|
+
| timeout | a wall-clock bound the host enforces | host |
|
|
73
|
+
| cancellation | the host's own signal or kill | host |
|
|
74
|
+
| process-tree containment | a process group or job object the host reaps | host |
|
|
75
|
+
| stream caps | a byte cap on captured stdout and stderr | host |
|
|
76
|
+
|
|
77
|
+
The argument array goes to the process verbatim: never a shell, never a
|
|
78
|
+
concatenated command string, and never a string a shell would re-split. Every
|
|
79
|
+
argument value — a ledger path, an item ID, a date — travels as one array
|
|
80
|
+
element, so no quoting rule exists to get wrong.
|
|
81
|
+
|
|
82
|
+
`--ledger` is a host-chosen path. The core performs no ledger discovery and
|
|
83
|
+
binds no implicit path.
|
|
84
|
+
|
|
85
|
+
### A missing executable is a host result
|
|
86
|
+
|
|
87
|
+
A missing or unlaunchable executable is a host-level result, not malformed
|
|
88
|
+
Wowbagger JSON. A process that never started emitted nothing, so there is no
|
|
89
|
+
envelope to parse and no exit code to interpret; the host reports its own
|
|
90
|
+
transport failure. Core failures that do run keep their documented response
|
|
91
|
+
domains and exit codes, in section 5.
|
|
92
|
+
|
|
93
|
+
## 3. Bounded input and output
|
|
94
|
+
|
|
95
|
+
### Input
|
|
96
|
+
|
|
97
|
+
A mutation request is strict UTF-8 JSON with one top-level object. It reaches
|
|
98
|
+
the core in exactly one of two ways:
|
|
99
|
+
|
|
100
|
+
1. **Bounded stdin.** `--input -` reads standard input to EOF. The host writes
|
|
101
|
+
the complete request, closes the stream, and enforces its own byte bound
|
|
102
|
+
before it writes.
|
|
103
|
+
2. **A host-created request file.** `--input <file>` reads a file the host
|
|
104
|
+
created with the permissions it wants. A secure host-created temporary file
|
|
105
|
+
is the alternative when a runtime cannot deliver stdin.
|
|
106
|
+
|
|
107
|
+
Never shell source, and never inline unbounded argv JSON. An invocation
|
|
108
|
+
primitive that carries argv only cannot call `transition` at all; that is the
|
|
109
|
+
gap the two transports above close, and widening argv is not the answer.
|
|
110
|
+
|
|
111
|
+
### Output
|
|
112
|
+
|
|
113
|
+
Every `--json` invocation writes exactly one JSON object and one trailing LF to
|
|
114
|
+
stdout, and nothing to stderr. A host caps both streams and treats an incomplete
|
|
115
|
+
stdout as an unresolved outcome, not as a refusal.
|
|
116
|
+
|
|
117
|
+
`list` and `inspect --workbench` are the two bounded reads: each carries an
|
|
118
|
+
advertised response bound, refuses rather than exceeding it, and says which
|
|
119
|
+
bound it hit. A full `inspect` has no response bound, and this is deliberate
|
|
120
|
+
rather than an omission. `inspect` is lossless: it returns the complete
|
|
121
|
+
base64 item source beside the parsed core view, and an item committed before
|
|
122
|
+
`max_item_source_bytes` existed is still inspectable. Bounding it would make the
|
|
123
|
+
one read an operator uses to repair an oversized item the one read that refuses.
|
|
124
|
+
A host that needs a bound uses `list` to choose a row and reads
|
|
125
|
+
`max_item_source_bytes` to size its buffer for the read that follows.
|
|
126
|
+
|
|
127
|
+
## 4. Path semantics on the owning host
|
|
128
|
+
|
|
129
|
+
The host that owns the workspace is the host that runs the core, with that
|
|
130
|
+
runtime's own Node executable and that runtime's own path spelling. There is
|
|
131
|
+
no cross-runtime path guessing.
|
|
132
|
+
|
|
133
|
+
| Host shape | Ledger path | Node executable |
|
|
134
|
+
|---|---|---|
|
|
135
|
+
| native worktree or plain folder | the local absolute path | the local runtime's Node |
|
|
136
|
+
| Git worktree | the worktree's own path, not the main checkout's | the local runtime's Node |
|
|
137
|
+
| direct SSH | the remote absolute path, resolved on the remote | the remote runtime's Node |
|
|
138
|
+
| WSL or another paired runtime | the path as that runtime spells it | that runtime's Node |
|
|
139
|
+
|
|
140
|
+
A Windows host must not translate a path into a WSL path, or the reverse, and
|
|
141
|
+
then launch the other runtime's core against it. Route the invocation to the
|
|
142
|
+
runtime that owns the workspace and let it resolve its own package.
|
|
143
|
+
|
|
144
|
+
Routing, relay negotiation, credential forwarding, and consent are the host's
|
|
145
|
+
concerns. Wowbagger neither performs nor validates them.
|
|
146
|
+
|
|
147
|
+
## 5. Reading the response
|
|
148
|
+
|
|
149
|
+
### Dispatch on the namespace first
|
|
150
|
+
|
|
151
|
+
A consumer must dispatch on the root `namespace` member before it reads any
|
|
152
|
+
version field. Two domains answer to `capabilities`, and one core command can
|
|
153
|
+
answer in two domains, so the command member alone is ambiguous.
|
|
154
|
+
|
|
155
|
+
1. A response with a root `namespace` member belongs to the domain that member
|
|
156
|
+
names.
|
|
157
|
+
2. A response with no namespace member but a root `ok` member belongs to the core
|
|
158
|
+
domain; its `contract_version` is the core contract version.
|
|
159
|
+
3. A response with neither is a bare result. Only `validate` and `ready` emit
|
|
160
|
+
one, and they are deliberately outside the envelope rule for compatibility.
|
|
161
|
+
|
|
162
|
+
| Domain | Root `namespace` | Version to negotiate |
|
|
163
|
+
|---|---|---|
|
|
164
|
+
| core | absent | top-level `contract_version` of `capabilities --json`, currently `5` |
|
|
165
|
+
| bare result | absent, and no `ok` member either | none |
|
|
166
|
+
| work-claim | `work-claim` | `result.operations.work_claim.api_version` |
|
|
167
|
+
| ledger-publication | `ledger-publication` | the same work-claim `api_version` |
|
|
168
|
+
| ledger-mutation | `ledger-mutation` | the same work-claim `api_version` |
|
|
169
|
+
|
|
170
|
+
A claim-domain `contract_version: 1` is the legacy envelope marker. Never
|
|
171
|
+
compare it with the core `contract_version`.
|
|
172
|
+
|
|
173
|
+
### Exit status
|
|
174
|
+
|
|
175
|
+
| Exit | Condition |
|
|
176
|
+
|---:|---|
|
|
177
|
+
| 0 | successful command; a mutation is state `committed` |
|
|
178
|
+
| 1 | a bare-result command found the ledger invalid, or `report` refused: an invalid ledger, an unreadable input, or a failed publication |
|
|
179
|
+
| 2 | argument, request, lookup, or candidate/lifecycle/layout-precondition failure |
|
|
180
|
+
| 3 | the complete configured ledger is invalid, for every command except `report` |
|
|
181
|
+
| 4 | cooperative comparison, lock, identity, or default-path conflict |
|
|
182
|
+
| 5 | the backend lacks the required capability or write scope |
|
|
183
|
+
| 6 | an unexpected operating or post-publication recovery condition |
|
|
184
|
+
|
|
185
|
+
Only exit 0 is normal completion. A host must read the mutation `state` member
|
|
186
|
+
on every nonzero `create`, `transition`, or `patch` result.
|
|
187
|
+
|
|
188
|
+
### When the response is lost
|
|
189
|
+
|
|
190
|
+
Only complete observed process output establishes a result. When a transition's
|
|
191
|
+
response never arrives — a signal, a timeout, an incomplete stream, or a lost
|
|
192
|
+
transport — the outcome is unresolved, and the host follows one sequence:
|
|
193
|
+
**Dispatch once, never replay, invalidate the inspected revision, reconnect,
|
|
194
|
+
then re-read the ledger.** A later ledger state is not causal proof that the
|
|
195
|
+
lost dispatch produced it.
|
|
196
|
+
|
|
197
|
+
Exit 4 `revision-conflict` is the exception in the other direction: it is a
|
|
198
|
+
proven non-write. Re-inspect for the current revision and dispatch again with
|
|
199
|
+
it.
|
|
200
|
+
|
|
201
|
+
There is no operation identity, operation journal, replay endpoint, or automatic
|
|
202
|
+
retry, and adding correlation requires a new contract decision. [The mutation
|
|
203
|
+
contract](mutation-contract.md), section 10, is normative for this behaviour.
|
|
204
|
+
|
|
205
|
+
## 6. Advertised limits and capabilities
|
|
206
|
+
|
|
207
|
+
`capabilities --json` advertises every semantic limit under the negotiated core
|
|
208
|
+
contract version. Read them there: no consumer must infer a limit from an
|
|
209
|
+
adapter implementation, and none of these numbers is discoverable any other way.
|
|
210
|
+
|
|
211
|
+
| `result.limits` member | Value | Meaning |
|
|
212
|
+
|---|---:|---|
|
|
213
|
+
| `max_item_source_bytes` | 8388608 | the complete serialized item source at every candidate door |
|
|
214
|
+
| `default_list_page_size` | 50 | the page size `list` uses when the query names none |
|
|
215
|
+
| `max_list_page_size` | 200 | the largest page size a query may request |
|
|
216
|
+
| `max_list_title_characters` | 120 | the code-point bound on a projected list title |
|
|
217
|
+
| `max_list_response_bytes` | 131072 | the whole `list` response, envelope and trailing LF included |
|
|
218
|
+
| `max_workbench_title_characters` | 120 | the code-point bound on a projected workbench title |
|
|
219
|
+
| `max_workbench_collection_entries` | 50 | the largest bounded workbench collection |
|
|
220
|
+
| `max_workbench_response_bytes` | 65536 | the whole `inspect --workbench` response |
|
|
221
|
+
|
|
222
|
+
The same envelope advertises which operations exist and how they are negotiated:
|
|
223
|
+
`result.operations.list.query_version`,
|
|
224
|
+
`result.operations.inspect.workbench.projection_version`,
|
|
225
|
+
`result.operations.report.config_versions` with `named_views`, and
|
|
226
|
+
`result.operations.work_claim.api_version`. The list query and the workbench
|
|
227
|
+
projection have their own version domains; a shape this core does not recognize
|
|
228
|
+
is refused by that number, not by the core contract version.
|
|
229
|
+
|
|
230
|
+
`result.limits` also states plainly what the local backend does not do:
|
|
231
|
+
`multi_item_atomicity`, `cross_clone_coordination`,
|
|
232
|
+
`cross_worktree_coordination`, `cross_machine_coordination`,
|
|
233
|
+
`noncooperating_writer_protection`, and `automatic_stale_lock_breaking` are all
|
|
234
|
+
`false`.
|
|
235
|
+
|
|
236
|
+
## 7. Packaged JSON Schemas
|
|
237
|
+
|
|
238
|
+
The schemas are published with the package and resolvable from an installed
|
|
239
|
+
consumer as `wowbagger/schemas/<file>`. `schemas/index.json` names each one's
|
|
240
|
+
response domain and that domain's version. Each `$id` is a stable identifier,
|
|
241
|
+
not a fetch URL.
|
|
242
|
+
|
|
243
|
+
| Schema | Domain | Validates |
|
|
244
|
+
|---|---|---|
|
|
245
|
+
| `common.json` | shared | definitions reused below; not a validation target on its own |
|
|
246
|
+
| `core-envelope.json` | core 5 | every core-domain response, by its four exact root shapes |
|
|
247
|
+
| `core-capabilities-response.json` | core 5 | `capabilities --json`, including every advertised limit |
|
|
248
|
+
| `core-inspect-response.json` | core 5 | the default lossless `inspect` read |
|
|
249
|
+
| `core-inspect-workbench-response.json` | core 5 | `inspect --workbench`, projection version 1 |
|
|
250
|
+
| `core-list-query.json` | list query 1 | the strict `list` request |
|
|
251
|
+
| `core-list-response.json` | core 5 | a bounded, paginated `list` page |
|
|
252
|
+
| `core-list-error-response.json` | core 5 | every documented `list` refusal |
|
|
253
|
+
| `core-transition-request.json` | core 5 | the strict `transition` request |
|
|
254
|
+
| `core-transition-response.json` | core 5 | a committed `transition` |
|
|
255
|
+
| `core-transition-error-response.json` | core 5 | every documented `transition` refusal, with its state |
|
|
256
|
+
| `core-report-response.json` | core 5 | `report` publications and refusals, including a named view |
|
|
257
|
+
| `bare-validation-result.json` | bare result | `validate`, and `ready` on an invalid ledger |
|
|
258
|
+
| `bare-ready-result.json` | bare result | a `ready` success |
|
|
259
|
+
| `ledger-mutation-refusal.json` | ledger-mutation 1 | the legacy-write fence refusals |
|
|
260
|
+
| `report-config-v1.json` | report config 1 | `<ledger>/.wowbagger/report.json` at version 1 |
|
|
261
|
+
| `report-config-v2.json` | report config 2 | the same file at version 2, which names views |
|
|
262
|
+
|
|
263
|
+
Every schema fixes its root members exactly and pins the version of its own
|
|
264
|
+
domain. A core schema therefore refuses a namespaced refusal, a neighbouring
|
|
265
|
+
contract version, and an extra root member, and a version 1 report configuration
|
|
266
|
+
refuses a version 2 one. Validate against the schema for the domain you
|
|
267
|
+
dispatched to, never against a union of all of them.
|
|
268
|
+
|
|
269
|
+
## 8. What Wowbagger does not provide
|
|
270
|
+
|
|
271
|
+
These are host concerns or rejected product behaviour. They are not coming to
|
|
272
|
+
the core, and a host must not read this contract as a promise of any of them:
|
|
273
|
+
|
|
274
|
+
- consent UI, declared-tool policy, and audit records;
|
|
275
|
+
- opaque workspace tokens, focus generation, and focus invalidation;
|
|
276
|
+
- remote routing, relay negotiation, and credential forwarding;
|
|
277
|
+
- process spawning, host caps, and cancellation enforcement;
|
|
278
|
+
- workspace event listeners and change notifications;
|
|
279
|
+
- an automatic transition, a scheduled mutation, or any write the caller did
|
|
280
|
+
not dispatch explicitly;
|
|
281
|
+
- mirrored ledger state or a second store; a response is a live projection and
|
|
282
|
+
may be cached as transient interface state only;
|
|
283
|
+
- operation identity, an operation journal, or a replay endpoint; and
|
|
284
|
+
- a daemon, an RPC service, or a long-lived core process.
|
|
285
|
+
|
|
286
|
+
Each invocation is one process, started by the host, that reads a request,
|
|
287
|
+
writes one response, and exits.
|