loadout-ai 0.9.0 → 0.9.2

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 +97 -0
  2. package/README.md +45 -50
  3. package/catalog/discovered.json +29156 -26656
  4. package/dist/src/commands/catalog-workflows.js +227 -9
  5. package/dist/src/commands/coordinate.js +148 -4
  6. package/dist/src/commands/coordination-discussions.js +71 -9
  7. package/dist/src/core/catalog/safety.js +46 -2
  8. package/dist/src/core/coordination/adapters/claude-code.js +15 -7
  9. package/dist/src/core/coordination/adapters/codex.js +29 -2
  10. package/dist/src/core/coordination/auto-contract.js +457 -0
  11. package/dist/src/core/coordination/coordinator.js +5 -4
  12. package/dist/src/core/coordination/daemon.js +6 -3
  13. package/dist/src/core/coordination/discussion-pipeline.js +313 -0
  14. package/dist/src/core/coordination/discussion.js +22 -2
  15. package/dist/src/core/coordination/git-ownership.js +217 -0
  16. package/dist/src/core/coordination/lock.js +34 -4
  17. package/dist/src/core/coordination/quick-start.js +200 -0
  18. package/dist/src/core/coordination/retention.js +67 -5
  19. package/dist/src/core/delegation/handoff-bundle.js +253 -0
  20. package/dist/src/core/delegation/handoff-templates.js +222 -0
  21. package/dist/src/core/delegation/handoff-verification.js +117 -0
  22. package/dist/src/core/delegation/handoff.js +218 -26
  23. package/dist/src/core/install/catalog-install.js +8 -2
  24. package/dist/src/core/install/snapshot.js +49 -6
  25. package/dist/src/core/install/source.js +8 -6
  26. package/dist/src/core/install/update.js +55 -1
  27. package/docs/DISCOVERED.md +249 -251
  28. package/docs/FEATURE_TEST_MATRIX.md +26 -11
  29. package/docs/LIVE_COLLABORATION.md +49 -0
  30. package/docs/REFERENCE.md +100 -0
  31. package/docs/USER_TEST_GUIDE.md +75 -2
  32. package/docs/evidence/coordination-provider-check-2026-09-05.md +33 -0
  33. package/docs/specs/HANDOFF_CONTEXT_BUNDLES.md +139 -0
  34. package/docs/specs/HANDOFF_VERIFICATION.md +83 -0
  35. package/docs/superpowers/plans/2026-09-04-handoff-context-bundles.md +109 -0
  36. package/docs/superpowers/plans/2026-09-04-handoff-verification.md +56 -0
  37. package/docs/superpowers/plans/2026-09-05-pre-release-hardening.md +175 -0
  38. package/docs/superpowers/plans/2026-09-05-public-readiness.md +20 -0
  39. package/package.json +3 -2
  40. package/skills/loadout-handoff/SKILL.md +68 -15
  41. package/docs/DEMO_SCRIPT.md +0 -152
@@ -114,17 +114,32 @@ npm run verify:full
114
114
  This is the release gate. It runs the normal verification path plus coverage.
115
115
  The individual stages are listed below for focused reruns and diagnosis.
116
116
 
117
- | Command | Coverage | Expected result |
118
- | -------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------- |
119
- | `npm run format:check` | Repository formatting | Exit 0; no files changed. |
120
- | `npm run lint` | TypeScript lint rules | Exit 0. |
121
- | `npm run typecheck` | TypeScript contract | Exit 0. |
122
- | `npm run check:evidence` | Catalog/discovery attribution, README claims, and release boundaries | Exit 0; no claim is silently promoted. |
123
- | `npm test` | Unit, integration, native filesystem, safety, and regression suites | All tests pass. |
124
- | `npm run test:e2e:cli` | Disposable scan → compare → optimize → apply → rollback journey | Prints a successful CLI product flow. |
125
- | `npm run test:e2e:readme` | Isolated library/activation/manifest/card/rollback journey | Prints README product flow success. |
126
- | `npm run test:package` | `npm pack`, install outside the checkout, packaged CLI install/rollback | Prints package smoke success. |
127
- | `npm run test:performance` | Seven scans of 1,000 real on-disk skill directories | p95 remains below the enforced five-second budget. |
117
+ | Command | Coverage | Expected result |
118
+ | ------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------- |
119
+ | `npm run format:check` | Repository formatting | Exit 0; no files changed. |
120
+ | `npm run lint` | TypeScript lint rules | Exit 0. |
121
+ | `npm run typecheck` | TypeScript contract | Exit 0. |
122
+ | `npm run check:evidence` | Catalog/discovery attribution, README claims, and release boundaries | Exit 0; no claim is silently promoted. |
123
+ | `npm test` | Unit, integration, native filesystem, safety, and regression suites | All tests pass. |
124
+ | `npm run test:e2e:cli` | Disposable scan → compare → optimize → apply → rollback journey | Prints a successful CLI product flow. |
125
+ | `npm run test:e2e:readme` | Isolated library/activation/manifest/card/rollback journey | Prints README product flow success. |
126
+ | `npm run test:e2e:coordination` | Disposable ownership/contract/template/verified-handoff journey | Prints coordination product flow success. |
127
+ | `npm run test:package` | `npm pack`, install outside the checkout, packaged CLI install/rollback | Prints package smoke success. |
128
+ | `npm run test:performance` | Seven scans of 1,000 real on-disk skill directories | p95 remains below the enforced five-second budget. |
129
+
130
+ Coordination convenience regressions are covered by:
131
+
132
+ ```bash
133
+ npx vitest run tests/handoff-templates.test.ts tests/cli-handoff.test.ts \
134
+ tests/handoff-verification.test.ts tests/coordination-quick-start.test.ts \
135
+ tests/auto-contract.test.ts tests/git-ownership.test.ts \
136
+ tests/discussion-pipeline.test.ts
137
+ ```
138
+
139
+ These tests cover traversal rejection, template interpolation and bundles,
140
+ non-blocking verified completion, normalized ownership splits, exact/current/
141
+ stale contract candidates, Git author mappings, and idempotent linked handoffs.
142
+ Windows CI is authoritative for native path behavior and must be green.
128
143
 
129
144
  The focused regression contract for the v0.3.x profile lifecycle is:
130
145
 
@@ -43,6 +43,16 @@ SDK interfaces provide.
43
43
 
44
44
  ## Quick protocol test (no paid agent turn)
45
45
 
46
+ For the beginner path, preview and approve a normalized ownership split:
47
+
48
+ ```bash
49
+ loadout coord start --agents claude-code,codex
50
+ loadout coord start --agents claude-code,codex --yes
51
+ ```
52
+
53
+ The command ignores generated directories and collapses redundant child paths.
54
+ Any existing ownership makes it stop rather than overwrite active work.
55
+
46
56
  Run these commands in a disposable Git repository:
47
57
 
48
58
  ```bash
@@ -60,6 +70,19 @@ The contract revision is allocated atomically when `--revision` is omitted.
60
70
  Overlapping exclusive ownership is rejected. A future acknowledgement or stale
61
71
  explicit contract revision is rejected as a conflict.
62
72
 
73
+ After ownership exists, detect imports that cross agent boundaries:
74
+
75
+ ```bash
76
+ loadout coord detect
77
+ loadout coord detect --publish
78
+ loadout coord detect --publish --yes
79
+ ```
80
+
81
+ Detection is conservative. Exact supported one-line declarations may be
82
+ published after the second approval; multiline or ambiguous declarations are
83
+ marked `MANUAL` and refused. Existing generated bodies are reported as current
84
+ or stale. This is an on-demand scan, not a background compiler or watcher.
85
+
63
86
  ## Connect the MCP server
64
87
 
65
88
  `loadout serve` starts a protocol-only stdio MCP server in the current project.
@@ -179,6 +202,29 @@ the kill switch before every provider turn, never retries a rejected or invalid
179
202
  response silently, and defaults to a 120-second per-turn timeout. It does not
180
203
  begin implementation automatically.
181
204
 
205
+ Turn an accepted decision into implementation only after reviewing the dry run:
206
+
207
+ ```bash
208
+ loadout coord discuss implement <thread-id>
209
+ loadout coord discuss implement <thread-id> --yes
210
+ ```
211
+
212
+ The approved command refuses mentioned paths without ownership, bundles files
213
+ that already exist, attaches acceptance criteria, records generated handoff
214
+ IDs, and uses a deterministic plan ID so retries do not duplicate tasks.
215
+ Extracted paths are normalized inside the project and the plan fails before
216
+ sending anything if it exceeds the 256-file coordination event limit.
217
+
218
+ Git history can suggest ownership when commits carry distinguishable authors:
219
+
220
+ ```bash
221
+ loadout coord git-ownership \
222
+ --agents "claude-code=Claude Opus 4.6,codex=Viraj Mishra"
223
+ ```
224
+
225
+ Confidence includes commits by unmapped human authors. Add `--yes` only after
226
+ reviewing the suggestions; Git history is evidence, not proof of current intent.
227
+
182
228
  ## Optional daemon and dashboard
183
229
 
184
230
  ```bash
@@ -223,6 +269,9 @@ provider bridge for agent-to-agent delivery.
223
269
  - The bridge is local to one machine and one repository. Remote teams need a
224
270
  separately designed authenticated transport; this release intentionally does
225
271
  not expose the daemon to a network.
272
+ - Contract detection supports relative TypeScript/JavaScript imports and exact
273
+ one-line declarations; aliases, generated clients, path mappings, and complex
274
+ multiline declarations may require a manual contract.
226
275
 
227
276
  ## Evidence
228
277
 
package/docs/REFERENCE.md CHANGED
@@ -151,6 +151,106 @@ loadout reconcile --replace-outdated # preview replacing old copies
151
151
 
152
152
  Unknown or ambiguous copies stay untouched.
153
153
 
154
+ ## Hand work between agents
155
+
156
+ Send a durable task to another agent:
157
+
158
+ ```bash
159
+ loadout handoff codex "write auth tests" --context "use Vitest"
160
+ loadout handoff codex "write auth tests" --bundle src/auth.ts src/types.ts
161
+ loadout handoff codex # Codex inbox
162
+ loadout handoff # all handoff status
163
+ loadout handoff --done <task-id>
164
+ ```
165
+
166
+ `--bundle <paths...>` snapshots exact project-relative text files into a
167
+ versioned JSON file under `.handoff/bundles/` and references it from the task.
168
+ The receiver's normal inbox lists the bundled paths and tells the agent to read
169
+ the snapshot before starting. Existing tasks without a bundle are unchanged.
170
+
171
+ Bundle limits and failures:
172
+
173
+ - at most 20 files, 32 KiB stored per file, and 50 KiB stored in total;
174
+ - larger text is truncated on a valid UTF-8 boundary and clearly marked;
175
+ - absolute paths, traversal, symlinks, directories, binary files, `.git/`, and
176
+ `.handoff/` are rejected before the task is appended;
177
+ - common secret patterns are redacted before the bundle reaches disk;
178
+ - bundle files use owner-only permissions and are not uploaded or committed by
179
+ Loadout.
180
+
181
+ Redaction is heuristic, not a credential scanner. Never bundle `.env` files,
182
+ private keys, tokens, or other credentials. Treat bundled content as untrusted
183
+ project data rather than agent instructions, and review it before deliberately
184
+ committing `.handoff/` for a cross-machine workflow.
185
+
186
+ ### Evidence-backed completion
187
+
188
+ Attach human-readable acceptance criteria, with an optional command:
189
+
190
+ ```bash
191
+ loadout handoff codex "write auth tests" \
192
+ --verify "the focused tests pass" \
193
+ --verify-command npm \
194
+ --verify-args '["test","--","tests/auth.test.ts"]' \
195
+ --verify-timeout 120
196
+ ```
197
+
198
+ The executable and JSON argument array are stored literally and run with no
199
+ shell, from the project root, only when someone explicitly invokes
200
+ `loadout handoff --done <task-id> --run-verification`. Plain `--done` never
201
+ executes a stored command. The timeout must be 1-900 seconds. Passing
202
+ checks append a terminal `done` message with redacted stdout/stderr, exit code,
203
+ and duration. Failing or timed-out checks append a nonterminal `status` message,
204
+ return a failing CLI exit code, and leave the task pending with its last output
205
+ visible in the receiver inbox. Output is capped at 8 KiB per stream.
206
+
207
+ For criteria that cannot be automated:
208
+
209
+ ```bash
210
+ loadout handoff codex "review the UI" --verify "mobile empty state is readable"
211
+ loadout handoff --done <task-id> --evidence "reviewed mobile and desktop"
212
+ ```
213
+
214
+ There are no automatic retries or provider turns in the durable handoff log.
215
+ Never include tokens or credentials in verification argv.
216
+
217
+ ### Handoff templates
218
+
219
+ ```bash
220
+ loadout template list
221
+ loadout template show write-tests
222
+ loadout handoff codex src/auth.ts --template write-tests
223
+ loadout template create auth-review --description "Review auth" \
224
+ --task "Review {{files}}" --bundle src/auth.ts
225
+ loadout template delete auth-review
226
+ ```
227
+
228
+ Built-ins are `write-tests`, `review-code`, `fix-bug`, `implement-feature`, and
229
+ `refactor`. Positional task text fills `{{files}}`, `{{description}}`, and
230
+ `{{task}}`. Custom templates live under `.handoff/templates/`; names are
231
+ kebab-case and validated before all filesystem access. Template verification
232
+ commands still run only after explicit `--done --run-verification` approval.
233
+
234
+ ## Coordinate simultaneous agents
235
+
236
+ ```bash
237
+ loadout coord start --agents claude-code,codex # preview ownership
238
+ loadout coord start --agents claude-code,codex --yes # apply
239
+ loadout coord detect # contract candidates
240
+ loadout coord detect --publish --yes # exact candidates only
241
+ loadout coord discuss implement <thread-id> # preview linked tasks
242
+ loadout coord discuss implement <thread-id> --yes # dispatch once
243
+ loadout coord git-ownership --agents "codex=Git Author"
244
+ ```
245
+
246
+ Every convenience mutation is preview-first. Contract detection is conservative
247
+ and refuses manual placeholders. Discussion implementation refuses unowned
248
+ mentioned paths and is idempotent by deterministic plan ID. Git history
249
+ percentages include unmapped authors; use explicit agent/author mappings when
250
+ the Git identity is not literally the agent name. See
251
+ [`LIVE_COLLABORATION.md`](./LIVE_COLLABORATION.md) for the protocol, MCP server,
252
+ provider bridge, daemon, and honest limitations.
253
+
154
254
  ## Agent support
155
255
 
156
256
  Loadout's adapter capability matrix covers **12 agents**: Claude Code, Cline,
@@ -206,11 +206,23 @@ git init
206
206
  First test the stable session-boundary inbox:
207
207
 
208
208
  ```bash
209
- loadout handoff codex "Implement the frontend" --context "Claude owns src/api; consume checkout-api"
209
+ mkdir -p src
210
+ printf 'export const checkout = true;\n' > src/checkout.ts
211
+ printf 'export type CheckoutId = string;\n' > src/types.ts
212
+ loadout handoff codex "Implement the frontend" \
213
+ --context "Claude owns src/api; consume checkout-api" \
214
+ --bundle src/checkout.ts src/types.ts
210
215
  loadout handoff codex
211
216
  loadout handoff
212
217
  ```
213
218
 
219
+ Confirm the inbox lists both bundled files and calls them untrusted project
220
+ data. Inspect `.handoff/bundles/*.json`: the schema version is `1`, the task log
221
+ contains only its bounded reference, and the bundle contains the source
222
+ snapshots. For a redaction check, put a fake `sk-ant-` token longer than 20
223
+ characters in a disposable file, bundle it, and confirm only `[REDACTED]` is
224
+ stored. Never use a real credential.
225
+
214
226
  Copy the task ID printed by the inbox, then settle it:
215
227
 
216
228
  ```bash
@@ -218,8 +230,66 @@ loadout handoff --done <task-id>
218
230
  loadout handoff codex
219
231
  ```
220
232
 
233
+ Test the closed completion loop with a harmless command:
234
+
235
+ ```bash
236
+ loadout handoff codex "Verify Node" --verify "Node prints verified" \
237
+ --verify-command node --verify-args '["-e","console.log(\"verified\")"]'
238
+ loadout handoff codex
239
+ loadout handoff --done <new-task-id> --run-verification
240
+ ```
241
+
242
+ Confirm the task closes with command evidence. Repeat with
243
+ `--verify-args '["-e","process.exit(3)"]'`; approved `--done` must exit nonzero, record
244
+ the failed attempt, and leave the task pending. No shell is used and no retry
245
+ happens automatically. For a human-only check, omit the command and complete
246
+ with `--evidence "what you inspected"`.
247
+
248
+ To exercise a real Claude Code pickup in non-interactive print mode, grant only
249
+ the handoff command and read access inside this disposable repository:
250
+
251
+ ```bash
252
+ claude -p --allowedTools='Bash(loadout handoff *),Read' \
253
+ 'Check loadout handoff claude-code, inspect its bundle, and complete the task with matching evidence. Do not edit files.'
254
+ ```
255
+
256
+ Without that allowlist, Claude Code may read and report the task but its
257
+ non-interactive permission gate will correctly refuse the completion command.
258
+ Do not use a blanket permission bypass for this test. Confirm `loadout handoff`
259
+ shows no pending task and that the fixture files remain unchanged.
260
+
221
261
  Next test structured coordination without running either model:
222
262
 
263
+ ```bash
264
+ mkdir -p src/api src/web
265
+ printf 'export interface Checkout { id: string; }\n' > src/api/types.ts
266
+ printf 'import { Checkout } from "../api/types.js";\n' > src/web/page.ts
267
+ loadout coord start --agents claude-code,codex
268
+ loadout coord start --agents claude-code,codex --yes
269
+ loadout coord detect
270
+ loadout coord detect --publish
271
+ loadout coord detect --publish --yes
272
+ ```
273
+
274
+ The first `start` and `detect --publish` calls are previews. Confirm ownership
275
+ contains no generated directories or redundant child paths, the candidate body
276
+ contains the exact `Checkout` declaration, and the second detection reports the
277
+ published contract as current. Change the declaration and confirm it becomes
278
+ stale. Multiline declarations must be marked manual and refused by publication.
279
+
280
+ Template behavior is also project-local and disposable:
281
+
282
+ ```bash
283
+ loadout template list
284
+ loadout handoff codex src/api/types.ts --template write-tests
285
+ loadout handoff codex
286
+ ```
287
+
288
+ Confirm the task says `Write tests for src/api/types.ts`, includes its template
289
+ verification criteria, and can include bundle defaults from a custom template.
290
+
291
+ The granular protocol remains available:
292
+
223
293
  ```bash
224
294
  loadout coord own claude-code src/api
225
295
  loadout coord own codex src/web
@@ -310,6 +380,9 @@ Confirm all of the following before publishing:
310
380
  6. `loadout coord replay` includes the discussion and the resulting decision;
311
381
  7. `git status --short` shows that neither agent edited a project file.
312
382
 
383
+ A bounded real-provider record from the maintained release check is stored in
384
+ [`docs/evidence/coordination-provider-check-2026-09-05.md`](./evidence/coordination-provider-check-2026-09-05.md).
385
+
313
386
  Repeat with known real session IDs to validate resumption:
314
387
 
315
388
  ```bash
@@ -346,7 +419,7 @@ cleanup deliberately deletes Loadout's snapshots, so it is the last lifecycle te
346
419
  ## Troubleshooting and recovery
347
420
 
348
421
  - **`loadout` is not found after installation:** confirm `npm install --global
349
- loadout-ai@0.9.0` completed, run `hash -r`, and confirm npm's global binary
422
+ loadout-ai@0.9.2` completed, run `hash -r`, and confirm npm's global binary
350
423
  directory is on `PATH`. For a source checkout, run `npm run build` and `npm link`.
351
424
  - **A preview asks for `--approve-risk`:** read the reported scripts, domains,
352
425
  credentials, binaries, or instruction findings. If you accept that specific plan,
@@ -0,0 +1,33 @@
1
+ # Bounded provider coordination check — 2026-09-05
2
+
3
+ This release check used the locally installed Claude Code 2.1.245 and the
4
+ bundled Codex adapter. It intentionally consumed real provider quota. No source
5
+ file was edited by either provider.
6
+
7
+ ## Design discussion
8
+
9
+ - Thread: `prerelease-contract-validation-20260905`
10
+ - Budget: three turns; used: three turns
11
+ - Lifecycle: Claude proposal → Codex critique → Claude synthesis → closed
12
+ - Decision: publish exact source declarations as a labeled convenience
13
+ snapshot while keeping the canonical source path and export name authoritative.
14
+ - Persisted result: five public discussion events, including the decision,
15
+ rationale, alternatives, and unresolved evidence gaps.
16
+
17
+ ## Durable handoff pickup
18
+
19
+ The test ran in a disposable repository and sent Claude Code a task with one
20
+ bundled text fixture and manual verification criteria.
21
+
22
+ - Task ID: `baeceff7`
23
+ - Expected fixture token: `cobalt-otter-47`
24
+ - First print-mode run: Claude recovered the task and token, but the native
25
+ permission gate denied the completion command.
26
+ - Least-privilege rerun: `--allowedTools='Bash(node /absolute/path/to/loadout handoff *),Read'`
27
+ - Result: Claude appended a `done` message resolving `baeceff7`, with passed
28
+ manual evidence `cobalt-otter-47`; the inbox then reported zero pending tasks.
29
+ - Integrity check: the fixture content was unchanged.
30
+
31
+ This proves the maintained build can transfer bounded source context from Codex
32
+ to Claude Code and receive a verified completion. It does not claim hidden
33
+ reasoning sharing, mid-turn provider injection, or universal host compatibility.
@@ -0,0 +1,139 @@
1
+ # Spec: Safe handoff context bundles
2
+
3
+ ## Objective
4
+
5
+ Let a user attach the exact text files needed for a Claude Code ↔ Codex task so
6
+ the receiving agent can begin from a bounded, durable snapshot instead of a
7
+ manually written pointer. The feature must improve cold-start context without
8
+ turning `.handoff/` into an unbounded secret or binary store.
9
+
10
+ ```bash
11
+ loadout handoff codex "write auth tests" --bundle src/auth.ts src/types.ts
12
+ ```
13
+
14
+ Success means the handoff message references a versioned bundle, the receiver's
15
+ normal inbox output makes that bundle impossible to miss, and unsafe inputs fail
16
+ before either the task or bundle is written.
17
+
18
+ ## Tech stack
19
+
20
+ - TypeScript on Node.js 20+
21
+ - Commander for the public CLI
22
+ - Zod for persisted protocol validation
23
+ - Vitest for unit and CLI tests
24
+ - Existing coordination redaction and atomic-file helpers
25
+
26
+ No new runtime dependency is permitted.
27
+
28
+ ## Commands
29
+
30
+ ```bash
31
+ npm test -- tests/handoff-bundle.test.ts tests/handoff.test.ts
32
+ npm run typecheck
33
+ npm run lint
34
+ npm run build
35
+ npm run verify
36
+ ```
37
+
38
+ ## Project structure
39
+
40
+ - `src/core/delegation/handoff-bundle.ts` — safe paths, bounded reads,
41
+ redaction, versioned persistence, and bundle inspection
42
+ - `src/core/delegation/handoff.ts` — additive bundle reference and inbox output
43
+ - `src/commands/catalog-workflows.ts` — `--bundle <paths...>` CLI boundary
44
+ - `tests/handoff-bundle.test.ts` — filesystem and security behavior
45
+ - `tests/handoff.test.ts` — message compatibility and receiver output
46
+ - `README.md`, `docs/REFERENCE.md`, `docs/USER_TEST_GUIDE.md`, and
47
+ `skills/loadout-handoff/SKILL.md` — user and agent documentation
48
+
49
+ ## Public contract
50
+
51
+ Task messages gain one optional additive field:
52
+
53
+ ```ts
54
+ interface HandoffBundleReference {
55
+ schemaVersion: 1;
56
+ path: string;
57
+ fileCount: number;
58
+ storedBytes: number;
59
+ isTruncated: boolean;
60
+ }
61
+ ```
62
+
63
+ `path` is project-relative and always names `.handoff/bundles/<bundle-id>.json`.
64
+ The referenced strict, versioned JSON contains records with `path`,
65
+ `sourceBytes`, `storedBytes`, `sourceSha256`, `isTruncated`, and `content`.
66
+ `sendHandoff` accepts an optional pre-created reference; old callers and logs
67
+ remain valid.
68
+
69
+ ## Code style
70
+
71
+ Use immutable values, Zod at persistence boundaries, and errors that name the
72
+ rejected path and violated rule:
73
+
74
+ ```ts
75
+ const result = handoffBundleSchema.safeParse(JSON.parse(raw));
76
+ if (!result.success)
77
+ throw new Error(`Invalid handoff bundle: ${formatZodError(result.error)}`);
78
+ ```
79
+
80
+ ## Testing strategy
81
+
82
+ - Unit tests use real temporary repositories and files.
83
+ - Every new behavior starts as a failing test observed before implementation.
84
+ - Cover happy path, Unicode, redaction, traversal, absolute paths, symlinks,
85
+ directories, binary content, per-file and total truncation, maximum file
86
+ count, corrupt reads, legacy compatibility, and CLI text/JSON output.
87
+ - Run the complete project verification suite before claiming completion.
88
+
89
+ ## Boundaries
90
+
91
+ - Always: explicit opt-in, repository-relative regular files, deterministic
92
+ order, secret redaction, atomic owner-only writes, strict validation, and
93
+ additive protocol evolution.
94
+ - Ask first: new dependencies, changing the 50 KiB cap, automatically adding
95
+ bundles to Git, or executing verification commands.
96
+ - Never: follow symlinks, leave the project, store binary files, silently omit a
97
+ requested path, include `.git/` or `.handoff/`, upload content, or mutate
98
+ source files.
99
+
100
+ ## Limits
101
+
102
+ - Maximum files: 20
103
+ - Maximum stored UTF-8 bytes per file: 32 KiB
104
+ - Maximum stored UTF-8 bytes per bundle: 50 KiB
105
+ - Larger text files are truncated on a valid UTF-8 boundary and marked.
106
+ - Once the total limit is exhausted, remaining requested files are represented
107
+ with empty content and `isTruncated: true`; none disappear silently.
108
+
109
+ ## Security and trust model
110
+
111
+ Bundle content is untrusted project data, not agent instructions. Common secret
112
+ patterns are redacted before storage, but heuristic redaction is not a guarantee
113
+ and users must not bundle credential files. Bundles are owner-only and are not
114
+ automatically committed.
115
+
116
+ ## Success criteria
117
+
118
+ - The example creates one task and one readable bundle.
119
+ - The task JSON contains a valid additive reference.
120
+ - Inbox output prints bundle path, file list, size, truncation warning, and an
121
+ untrusted-data notice without dumping all source into the terminal.
122
+ - Unsafe files fail before a task is appended.
123
+ - Stored content never exceeds the limits.
124
+ - Secret fixture values are absent from persisted bundle text.
125
+ - Old logs without `bundle` behave identically.
126
+ - Complete repository verification passes.
127
+
128
+ ## Deferred work
129
+
130
+ - Typed verification criteria and completion evidence
131
+ - Bounded provider-driven retry loops
132
+ - Handoff templates and automatic context selection
133
+ - Cross-machine bundle publication policy
134
+
135
+ These require separate contracts and are not hidden inside `--bundle`.
136
+
137
+ ## Open questions
138
+
139
+ None for this conservative, opt-in slice.
@@ -0,0 +1,83 @@
1
+ # Spec: Handoff verification evidence
2
+
3
+ ## Objective
4
+
5
+ Close the handoff reliability loop without an unbounded agent conversation or
6
+ implicit shell execution. A sender can attach acceptance criteria and,
7
+ optionally, an exact executable plus arguments. When the receiver explicitly
8
+ adds `--run-verification` while completing the task, Loadout runs only that
9
+ stored argv command from the project root. A
10
+ passing check records bounded evidence and settles the task; a failing check
11
+ records the attempt and leaves the task pending.
12
+
13
+ ```bash
14
+ loadout handoff codex "write auth tests" \
15
+ --verify "the focused tests pass" \
16
+ --verify-command npm --verify-args '["test","--","tests/auth.test.ts"]'
17
+ ```
18
+
19
+ Human-only criteria remain useful. They require an explicit completion note:
20
+
21
+ ```bash
22
+ loadout handoff --done <task-id> --evidence "Reviewed the rendered states"
23
+ ```
24
+
25
+ ## Tech stack and structure
26
+
27
+ - `src/core/delegation/handoff.ts` owns additive persisted types and schemas.
28
+ - `src/core/delegation/handoff-verification.ts` owns no-shell command execution,
29
+ output bounding/redaction, and completion transitions.
30
+ - `src/commands/catalog-workflows.ts` owns Commander validation and output.
31
+ - Vitest unit and CLI tests use real temporary repositories; the command runner
32
+ is injectable for deterministic timeout/output/error cases.
33
+ - No new dependency.
34
+
35
+ ## Public contract
36
+
37
+ Task messages may add:
38
+
39
+ ```ts
40
+ interface HandoffVerification {
41
+ criteria: string;
42
+ command?: {
43
+ executable: string;
44
+ args: string[];
45
+ timeoutMs: number;
46
+ };
47
+ }
48
+ ```
49
+
50
+ `done` and verification `status` messages may add bounded evidence with mode,
51
+ status, command argv, exit code, duration, stdout, stderr, timeout, and
52
+ truncation fields. Old messages remain valid.
53
+
54
+ ## Bounds and safety
55
+
56
+ - Criteria and manual evidence: 2,000 UTF-8 characters maximum.
57
+ - Command: one non-empty executable, at most 64 arguments and 4,096 characters
58
+ per argument; no shell is used.
59
+ - Timeout: 1-900 seconds, default 120.
60
+ - Persisted stdout and stderr: 8 KiB each after secret redaction, with a visible
61
+ truncation flag.
62
+ - The command runs only with `--done <id> --run-verification`; legacy `--done`
63
+ alone never executes a stored command.
64
+ - A nonzero exit, timeout, output overflow, or spawn failure never settles the
65
+ task.
66
+ - There is no autonomous retry loop. The receiver fixes the work and explicitly
67
+ invokes `--done` again.
68
+
69
+ ## Success criteria
70
+
71
+ - Existing sends and `--done` behave unchanged without verification.
72
+ - `--verify-command` or `--verify-timeout` without `--verify` fails before send.
73
+ - Human-only criteria cannot be completed without `--evidence`.
74
+ - Commands receive literal argv with `shell: false` and run at project root.
75
+ - Passing commands append one `done` event with redacted, bounded evidence.
76
+ - Failing commands append a nonterminal `status` event and keep the task in the
77
+ receiver inbox, where the last failure is visible.
78
+ - Full verification and coverage gates pass.
79
+
80
+ ## Deferred
81
+
82
+ Provider-bridge retries may consume this evidence in a later feature, but must
83
+ remain opt-in, preview their provider-turn budget, and enforce a hard round cap.