owlrunkit 0.18.2 → 0.18.4

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 (40) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +159 -52
  3. package/docs/architecture/OWLCODA_RUNKIT_0184_EXTERNAL_DELIVERY_INTAKE_PRODUCT_DECISION_20260812.md +209 -0
  4. package/docs/architecture/OWLCODA_RUNKIT_018_PROJECT_DRIVER_PRODUCT_DEFINITION.md +16 -5
  5. package/docs/architecture/OWLCODA_RUNKIT_USAGE_MODE_SELECTION_PRODUCT_DECISION_20260811.md +54 -3
  6. package/docs/architecture/OWLCODA_RUN_KIT_CONTRACT_V0_2.md +7 -0
  7. package/integrations/codex/skills/owlcoda-runkit/SKILL.md +125 -74
  8. package/integrations/codex/skills/owlcoda-runkit/assets/templates/config.json +3 -3
  9. package/integrations/codex/skills/owlcoda-runkit/references/contract-v0.1.md +160 -0
  10. package/integrations/codex/skills/owlcoda-runkit/references/contract-v0.2.md +545 -0
  11. package/package.json +1 -1
  12. package/packages/attest/README.md +4 -3
  13. package/packages/attest/consumer-surface-v1.json +1 -0
  14. package/packages/attest/distribution-manifest-v1.json +12 -1
  15. package/packages/attest/schemas/quick-verification-receipt-v2.schema.json +232 -0
  16. package/packages/attest/src/index.mjs +4 -1
  17. package/packages/attest/src/quick-receipt-contract.mjs +16 -6
  18. package/packages/attest/src/quick.mjs +21 -2
  19. package/packages/attest/src/workspace-snapshot.mjs +10 -1
  20. package/registry-release-policy-v1.json +5 -5
  21. package/sbom.spdx.json +5 -5
  22. package/scripts/runkit-contract/assurance-router.mjs +25 -6
  23. package/scripts/runkit-contract/core-contract.mjs +10 -1
  24. package/scripts/runkit-contract/onboarding-doctor.mjs +1 -1
  25. package/scripts/runkit-contract/profile-onboarding.mjs +263 -15
  26. package/scripts/runkit-contract/project-cli-resolver.mjs +6 -0
  27. package/scripts/runkit-contract/project-external-delivery.mjs +707 -0
  28. package/scripts/runkit-contract/quick-metrics.mjs +3 -3
  29. package/scripts/runkit-contract/quick-receipt.mjs +79 -12
  30. package/scripts/runkit-contract/quick-verify.mjs +89 -12
  31. package/scripts/runkit-contract/runkit-bootstrap.mjs +6 -1
  32. package/scripts/runkit-contract/runkit-cli.mjs +363 -143
  33. package/scripts/runkit-contract/schemas/assurance-route-v2.schema.json +26 -0
  34. package/scripts/runkit-contract/schemas/profile-detection-v3.schema.json +170 -0
  35. package/scripts/runkit-contract/schemas/team-project-event-v2.schema.json +128 -0
  36. package/scripts/runkit-contract/schemas/team-project-event-v3.schema.json +146 -0
  37. package/scripts/runkit-contract/schemas/team-project-status-v2.schema.json +85 -0
  38. package/scripts/runkit-contract/schemas/usage-mode-recommendation-v2.schema.json +136 -0
  39. package/scripts/runkit-contract/team-project.mjs +782 -55
  40. package/scripts/runkit-contract/usage-mode.mjs +28 -7
@@ -86,9 +86,8 @@ import {
86
86
  importOfflineReceipt,
87
87
  } from "./offline-store.mjs";
88
88
  import {
89
- applyDetectedProfilesV2,
90
- detectProfiles,
91
- detectProfilesV2,
89
+ applyDetectedProfilesV3,
90
+ detectProfilesV3,
92
91
  reconcileProfilesV2,
93
92
  resolveProfilesImpact,
94
93
  validateProfiles,
@@ -102,11 +101,11 @@ import {
102
101
  } from "./fleet-discovery.mjs";
103
102
  import {
104
103
  RUNKIT_RISK_CATEGORIES,
105
- routeRunKitAssuranceV1,
104
+ routeRunKitAssuranceV2,
106
105
  } from "./assurance-router.mjs";
107
106
  import {
108
- formatUsageModeHumanV1,
109
- recommendUsageModeV1,
107
+ formatUsageModeHumanV2,
108
+ recommendUsageModeV2,
110
109
  } from "./usage-mode.mjs";
111
110
  import { deriveHumanStatusFromInspectV1 } from "./human-status.mjs";
112
111
  import {
@@ -147,99 +146,104 @@ import { OFFICIAL_NPM_REGISTRY } from "./registry-adoption-gate.mjs";
147
146
  import {
148
147
  appendTeamProjectEventV1,
149
148
  assignTeamProjectV1,
150
- buildTeamProjectTakeoverV1,
149
+ buildTeamProjectTakeoverV2,
151
150
  checkpointTeamProjectV1,
152
151
  closeTeamProjectVerificationV1,
153
152
  deferTeamProjectVerificationV1,
154
- formatTeamProjectStatusHumanV1,
155
- formatTeamProjectTakeoverHumanV1,
153
+ formatTeamProjectStatusHumanV2,
154
+ formatTeamProjectTakeoverHumanV2,
156
155
  handoffTeamProjectV1,
157
156
  initializeTeamProjectV1,
158
157
  integrateTeamProjectV1,
159
158
  openTeamProjectDecisionV1,
160
- readTeamProjectStatusV1,
159
+ readTeamProjectStatusV2,
160
+ rejectAndReturnTeamProjectV1,
161
161
  resolveTeamProjectDecisionV1,
162
162
  } from "./team-project.mjs";
163
163
  import {
164
164
  formatTeamProjectSuccessorHumanV1,
165
165
  successorTeamProjectV1,
166
166
  } from "./team-project-successor.mjs";
167
+ import {
168
+ captureTargetWorkspaceSnapshotV1,
169
+ importExternalDeliveryV1,
170
+ } from "./project-external-delivery.mjs";
167
171
 
168
172
  const TOP_LEVEL_HELP = `OwlRunKit ${CORE_VERSION}
169
173
 
170
174
  Usage:
171
- owlrunkit <command> [options]
175
+ npx --no-install owlrunkit <command> [options]
172
176
 
173
177
  Start here:
174
- owlrunkit mode recommend --workspace .
175
- owlrunkit doctor --workspace .
176
- owlrunkit profiles detect --workspace . --dry-run
177
- owlrunkit profiles detect --workspace . --apply
178
- owlrunkit assurance route --workspace . --request <risk-facts.json>
179
- owlrunkit adopt --workspace . --exact owlrunkit@${CORE_VERSION}
178
+ npx --no-install owlrunkit mode recommend --workspace .
179
+ npx --no-install owlrunkit doctor --workspace .
180
+ npx --no-install owlrunkit profiles detect --workspace . --dry-run
181
+ npx --no-install owlrunkit profiles detect --workspace . --apply
182
+ npx --no-install owlrunkit assurance route --workspace . --request <risk-facts.json>
183
+ npx --no-install owlrunkit adopt --workspace . --exact owlrunkit@${CORE_VERSION}
180
184
  Quick Verification
181
- owlrunkit quick-verify --workspace . -- <command> [args...]
185
+ npx --no-install owlrunkit quick-verify --workspace . -- <command> [args...]
182
186
  Low-risk, source-bound reusable evidence without writer leases or acceptance.
183
187
 
184
188
  Formal Delivery
185
- owlrunkit formal <start|check|finish> --workspace . --run-id <id> [...]
189
+ npx --no-install owlrunkit formal <start|check|finish> --workspace . --run-id <id> [...]
186
190
  Use for multi-writer, permissions, security, funds, irreversible change,
187
191
  uncertain rollback, schema/data migration, or explicit Formal acceptance.
188
192
 
189
193
  Frozen dirty source
190
- owlrunkit candidate <freeze|verify|materialize> --workspace . [...]
194
+ npx --no-install owlrunkit candidate <freeze|verify|materialize> --workspace . [...]
191
195
 
192
196
  Two-stage deployment
193
- owlrunkit deployment prepare --workspace . --run-id <accepted-run> --artifact <file> --media-type <type> --owner-decision <decision-v1.json> --output <receipt>
194
- owlrunkit deployment execute --workspace . [--resume] --prepare <receipt> --owner-decision <decision-v1.json> --owner-authority <signed-v2.json> --manifest <remote.json>
197
+ npx --no-install owlrunkit deployment prepare --workspace . --run-id <accepted-run> --artifact <file> --media-type <type> --owner-decision <decision-v1.json> --output <receipt>
198
+ npx --no-install owlrunkit deployment execute --workspace . [--resume] --prepare <receipt> --owner-decision <decision-v1.json> --owner-authority <signed-v2.json> --manifest <remote.json>
195
199
 
196
200
  Fleet and status
197
- owlrunkit fleet <register-root|inspect-registry> [options]
198
- owlrunkit fleet replace-registry --request <file> --receipt <file> [--dry-run]
199
- owlrunkit fleet rollback-registry --receipt <file> --rollback-receipt <file>
200
- owlrunkit fleet discover; owlrunkit status --workspace .
201
+ npx --no-install owlrunkit fleet <register-root|inspect-registry> [options]
202
+ npx --no-install owlrunkit fleet replace-registry --request <file> --receipt <file> [--dry-run]
203
+ npx --no-install owlrunkit fleet rollback-registry --receipt <file> --rollback-receipt <file>
204
+ npx --no-install owlrunkit fleet discover; npx --no-install owlrunkit status --workspace .
201
205
 
202
206
  Agent team projects
203
- owlrunkit project <init|assign|checkpoint|handoff|decision|verification|capture|status|takeover|successor> [options]
207
+ npx --no-install owlrunkit project <init|assign|checkpoint|handoff|reject-and-return|decision|verification|capture|target-snapshot|import-delivery|status|takeover|successor> [options]
204
208
  Durable Agent work, dependencies, decisions, gates, progress, and handoffs.
205
209
  Core successor
206
- owlrunkit core-successor <plan|apply|resume> --workspace . [...]
210
+ npx --no-install owlrunkit core-successor <plan|apply|resume> --workspace . [...]
207
211
 
208
212
  Other onboarding commands:
209
- owlrunkit profiles validate --workspace .; owlrunkit profiles impact --workspace . --changed <path>
210
- owlrunkit inspect --workspace . --json
213
+ npx --no-install owlrunkit profiles validate --workspace .; npx --no-install owlrunkit profiles impact --workspace . --changed <path>
214
+ npx --no-install owlrunkit inspect --workspace . --json
211
215
  Formal accepted does not grant Git or release authority; Quick cannot become Formal.
212
216
  `;
213
217
 
214
218
  const COMMAND_HELP = Object.freeze({
215
219
  adopt: `Usage:
216
- owlrunkit adopt --workspace <directory> --exact owlrunkit@${CORE_VERSION}
220
+ npx --no-install owlrunkit adopt --workspace <directory> --exact owlrunkit@${CORE_VERSION}
217
221
  [--registry <url>] [--timeout-ms <milliseconds>] [--json]
218
222
 
219
223
  Verifies the exact registry release against the project-local install and writes
220
224
  project-owned adoption evidence. It grants no Git or release authority.
221
225
  `,
222
226
  assurance: `Usage:
223
- owlrunkit assurance route --workspace <directory> --request <risk-facts.json>
227
+ npx --no-install owlrunkit assurance route --workspace <directory> --request <risk-facts.json>
224
228
 
225
229
  Selects none, Quick, or Formal from structured risk facts. It does not grant
226
230
  repository, release, deployment, or destructive authority.
227
231
  `,
228
232
  "assurance route": `Usage:
229
- owlrunkit assurance route --workspace <directory> --request <risk-facts.json>
233
+ npx --no-install owlrunkit assurance route --workspace <directory> --request <risk-facts.json>
230
234
 
231
235
  Required:
232
236
  --request <file> Structured assurance risk facts.
233
237
  `,
234
238
  mode: `Usage:
235
- owlrunkit mode recommend --workspace <directory> [risk facts]
236
- owlrunkit mode status --workspace <directory> [--json]
239
+ npx --no-install owlrunkit mode recommend --workspace <directory> [risk facts]
240
+ npx --no-install owlrunkit mode status --workspace <directory> [--json]
237
241
 
238
242
  Selects continuity and assurance independently. Recommendation and status are
239
243
  read-only and grant no Git, release, deployment, production, or business authority.
240
244
  `,
241
245
  "mode recommend": `Usage:
242
- owlrunkit mode recommend --workspace <directory>
246
+ npx --no-install owlrunkit mode recommend --workspace <directory>
243
247
  [--requested-mode auto|off|light|managed|formal]
244
248
  [--needs-evidence] [--exact-command-count <count>] [--writer-count <count>]
245
249
  [--cross-session] [--long-running] [--interruption-recovery]
@@ -253,195 +257,209 @@ Returns one user mode plus the independent continuity and assurance selections.
253
257
  Persisted mode preferences are not part of this release.
254
258
  `,
255
259
  "mode status": `Usage:
256
- owlrunkit mode status --workspace <directory> [--json]
260
+ npx --no-install owlrunkit mode status --workspace <directory> [--json]
257
261
 
258
262
  Reads the current mode preference source without creating project state.
259
263
  `,
260
264
  "quick-attest": `Usage:
261
- owlrunkit quick-attest --workspace <directory> --receipt <receipt.json> [--json]
265
+ npx --no-install owlrunkit quick-attest --workspace <directory> --receipt <receipt.json> [--json]
262
266
 
263
267
  Attests one Quick Receipt against its bound materials and current workspace.
264
268
  It never grants repository or business authority.
265
269
  `,
266
270
  "quick-verify": `Usage:
267
- owlrunkit quick-verify --workspace <directory> [--json] -- <executable> [args...]
271
+ npx --no-install owlrunkit quick-verify --workspace <directory> [--stdin-file <file>] [--attest] [--json]
272
+ -- <executable> [args...]
268
273
 
269
274
  Runs one exact command, saves source-bound stdout/stderr and a Quick receipt,
270
- and returns a bounded output summary. Supply the exact command after --.
275
+ and returns a bounded head/tail output summary. --stdin-file copies and hash-binds
276
+ up to 1 MiB of exact stdin bytes in the receipt store. --attest immediately
277
+ attests the saved receipt without merging Quick and attestation semantics.
271
278
  Quick evidence is not Formal acceptance and grants no repository or business authority.
279
+ `,
280
+ "quick-metrics": `Usage:
281
+ npx --no-install owlrunkit quick-metrics --workspace <directory> [--local] [--verbose] [--json]
282
+
283
+ Returns aggregate local-only Quick counts with no telemetry or network access.
284
+ --verbose additionally lists the receipt paths used for the aggregation.
272
285
  `,
273
286
  fleet: `Usage:
274
- owlrunkit fleet register-root --fleet-root <directory>
275
- owlrunkit fleet inspect-registry [--registry <file>]
276
- owlrunkit fleet replace-registry --request <file> --receipt <file> [--registry <file>] [--dry-run]
277
- owlrunkit fleet rollback-registry --receipt <file> --rollback-receipt <file> [--registry <file>]
278
- owlrunkit fleet discover [--fleet-root <directory>] [--fleet-manifest <file>]
287
+ npx --no-install owlrunkit fleet register-root --fleet-root <directory>
288
+ npx --no-install owlrunkit fleet inspect-registry [--registry <file>]
289
+ npx --no-install owlrunkit fleet replace-registry --request <file> --receipt <file> [--registry <file>] [--dry-run]
290
+ npx --no-install owlrunkit fleet rollback-registry --receipt <file> --rollback-receipt <file> [--registry <file>]
291
+ npx --no-install owlrunkit fleet discover [--fleet-root <directory>] [--fleet-manifest <file>]
279
292
  `,
280
293
  "fleet register-root": `Usage:
281
- owlrunkit fleet register-root --fleet-root <directory>
294
+ npx --no-install owlrunkit fleet register-root --fleet-root <directory>
282
295
 
283
296
  Registers one durable fleet coverage root for later no-argument discovery.
284
297
  `,
285
298
  "fleet inspect-registry": `Usage:
286
- owlrunkit fleet inspect-registry [--registry <file>]
299
+ npx --no-install owlrunkit fleet inspect-registry [--registry <file>]
287
300
 
288
301
  Reads the exact registry bytes, hashes, roots, and membership without mutation.
289
302
  `,
290
303
  "fleet replace-registry": `Usage:
291
- owlrunkit fleet replace-registry --request <file> --receipt <file>
304
+ npx --no-install owlrunkit fleet replace-registry --request <file> --receipt <file>
292
305
  [--registry <file>] [--dry-run]
293
306
 
294
307
  Atomically replaces a registry from an exact preimage and evidence-bound fleet
295
308
  membership. Coverage reduction requires explicit exclusion evidence.
296
309
  `,
297
310
  "fleet rollback-registry": `Usage:
298
- owlrunkit fleet rollback-registry --receipt <replacement-receipt.json>
311
+ npx --no-install owlrunkit fleet rollback-registry --receipt <replacement-receipt.json>
299
312
  --rollback-receipt <file> [--registry <file>]
300
313
 
301
314
  Restores the exact preimage recorded by a replacement receipt.
302
315
  `,
303
316
  "fleet discover": `Usage:
304
- owlrunkit fleet discover [--fleet-root <directory>] [--fleet-manifest <file>]
317
+ npx --no-install owlrunkit fleet discover [--fleet-root <directory>] [--fleet-manifest <file>]
305
318
  [--workspace-root <directory>]
306
319
 
307
320
  With no source option, discovers the complete fleet inside registered roots.
308
321
  `,
309
322
  profiles: `Usage:
310
- owlrunkit profiles detect --workspace <directory> [--dry-run | --apply]
311
- owlrunkit profiles reconcile --workspace <directory> (--dry-run | --apply)
312
- owlrunkit profiles validate --workspace <directory>
313
- owlrunkit profiles impact --workspace <directory> --changed <path>
323
+ npx --no-install owlrunkit profiles detect --workspace <directory> [--dry-run | --apply]
324
+ npx --no-install owlrunkit profiles reconcile --workspace <directory> (--dry-run | --apply)
325
+ npx --no-install owlrunkit profiles validate --workspace <directory>
326
+ npx --no-install owlrunkit profiles impact --workspace <directory> --changed <path>
314
327
  `,
315
328
  "profiles detect": `Usage:
316
- owlrunkit profiles detect --workspace <directory> [--dry-run | --apply]
329
+ npx --no-install owlrunkit profiles detect --workspace <directory> [--dry-run | --apply]
317
330
 
318
331
  --dry-run reports deterministic candidates. --apply atomically adopts only a
319
332
  high-confidence unambiguous profile.
320
333
  `,
321
334
  "profiles reconcile": `Usage:
322
- owlrunkit profiles reconcile --workspace <directory> (--dry-run | --apply)
335
+ npx --no-install owlrunkit profiles reconcile --workspace <directory> (--dry-run | --apply)
323
336
 
324
337
  --dry-run previews deterministic additions and command updates without writing.
325
338
  --apply atomically updates profiles.json and writes a hash-bound migration receipt.
326
339
  `,
327
340
  formal: `Usage:
328
- owlrunkit formal start --workspace <directory> --run-id <id> [...]
329
- owlrunkit formal check --workspace <directory> --run-id <id> -- <command>
330
- owlrunkit formal finish --workspace <directory> --run-id <id>
341
+ npx --no-install owlrunkit formal start --workspace <directory> --run-id <id> [...]
342
+ npx --no-install owlrunkit formal check --workspace <directory> --run-id <id> -- <command>
343
+ npx --no-install owlrunkit formal finish --workspace <directory> --run-id <id>
331
344
  `,
332
345
  "formal start": `Usage:
333
- owlrunkit formal start --workspace <directory> --run-id <id>
346
+ npx --no-install owlrunkit formal start --workspace <directory> --run-id <id>
334
347
  --goal <goal.json> --work-item <id> --owned-path <path>
335
348
 
336
349
  Creates the execution and exact writer lease.
337
350
  `,
338
351
  "formal check": `Usage:
339
- owlrunkit formal check --workspace <directory> --run-id <id>
352
+ npx --no-install owlrunkit formal check --workspace <directory> --run-id <id>
340
353
  --work-item <id> --check-id <id> --envelope <verification-envelope.json>
341
- owlrunkit formal check --workspace <directory> --run-id <id>
354
+ npx --no-install owlrunkit formal check --workspace <directory> --run-id <id>
342
355
  --work-item <id> --check-id <id> --cwd <directory> -- <built-in-command> [args...]
343
356
 
344
357
  Verification Envelopes admit real project commands only when file, network,
345
358
  process, environment, output, timeout, and cleanup constraints are enforced.
346
359
  `,
347
360
  "formal finish": `Usage:
348
- owlrunkit formal finish --workspace <directory> --run-id <id>
361
+ npx --no-install owlrunkit formal finish --workspace <directory> --run-id <id>
349
362
 
350
363
  Runs the final source, evidence, permission, closeout, and lease-release path.
351
364
  `,
352
365
  candidate: `Usage:
353
- owlrunkit candidate freeze --workspace <directory> --run-id <id>
366
+ npx --no-install owlrunkit candidate freeze --workspace <directory> --run-id <id>
354
367
  --from-lease <id> --candidate-id <id>
355
- owlrunkit candidate verify --workspace <directory> --candidate <file>
356
- owlrunkit candidate materialize --workspace <directory> --candidate <file>
368
+ npx --no-install owlrunkit candidate verify --workspace <directory> --candidate <file>
369
+ npx --no-install owlrunkit candidate materialize --workspace <directory> --candidate <file>
357
370
  --target-workspace <directory>
358
371
  `,
359
372
  "candidate freeze": `Usage:
360
- owlrunkit candidate freeze --workspace <directory> --run-id <id>
373
+ npx --no-install owlrunkit candidate freeze --workspace <directory> --run-id <id>
361
374
  --from-lease <id> --candidate-id <id>
362
375
 
363
376
  Freezes the exact dirty source manifest, including deletions and renames.
364
377
  `,
365
378
  "candidate verify": `Usage:
366
- owlrunkit candidate verify --workspace <directory> --candidate <file>
379
+ npx --no-install owlrunkit candidate verify --workspace <directory> --candidate <file>
367
380
  `,
368
381
  "candidate materialize": `Usage:
369
- owlrunkit candidate materialize --workspace <directory> --candidate <file>
382
+ npx --no-install owlrunkit candidate materialize --workspace <directory> --candidate <file>
370
383
  --target-workspace <directory>
371
384
  `,
372
385
  deployment: `Usage:
373
- owlrunkit deployment prepare --workspace <directory> --run-id <accepted-run>
386
+ npx --no-install owlrunkit deployment prepare --workspace <directory> --run-id <accepted-run>
374
387
  --artifact <file> --media-type <type> --owner-decision <decision-v1.json> --output <receipt>
375
- owlrunkit deployment execute --workspace <directory> --prepare <receipt>
388
+ npx --no-install owlrunkit deployment execute --workspace <directory> --prepare <receipt>
376
389
  --owner-decision <decision-v1.json> --owner-authority <signed-v2.json> --manifest <remote.json> [--resume]
377
390
  `,
378
391
  "deployment prepare": `Usage:
379
- owlrunkit deployment prepare --workspace <directory> --run-id <accepted-run>
392
+ npx --no-install owlrunkit deployment prepare --workspace <directory> --run-id <accepted-run>
380
393
  --artifact <file> --media-type <type> --owner-decision <decision-v1.json> --output <receipt>
381
394
  `,
382
395
  "deployment execute": `Usage:
383
- owlrunkit deployment execute --workspace <directory> --prepare <receipt>
396
+ npx --no-install owlrunkit deployment execute --workspace <directory> --prepare <receipt>
384
397
  --owner-decision <decision-v1.json> --owner-authority <signed-v2.json> --manifest <remote.json> [--resume]
385
398
 
386
399
  The default happy path creates and closes the deployment child, goal, lease,
387
400
  profile, preflight, lineage, and result. --request is an advanced legacy path.
388
401
  `,
389
402
  "core-successor": `Usage:
390
- owlrunkit core-successor plan --workspace <directory> --plan-id <id> [...]
391
- owlrunkit core-successor apply --workspace <directory> --plan <file>
403
+ npx --no-install owlrunkit core-successor plan --workspace <directory> --plan-id <id> [...]
404
+ npx --no-install owlrunkit core-successor apply --workspace <directory> --plan <file>
392
405
  --owner-authority <signed-v2.json> --receipt-id <id>
393
- owlrunkit core-successor resume --workspace <directory> --plan <file>
406
+ npx --no-install owlrunkit core-successor resume --workspace <directory> --plan <file>
394
407
  --owner-authority <signed-v2.json> [...]
395
408
  `,
396
409
  "core-successor plan": `Usage:
397
- owlrunkit core-successor plan --workspace <directory> --plan-id <id>
410
+ npx --no-install owlrunkit core-successor plan --workspace <directory> --plan-id <id>
398
411
  --run-id <id> --from-lease <id> --candidate-id <id>
399
412
  [--fleet-root <directory> | --fleet-manifest <file>]
400
413
  `,
401
414
  "core-successor apply": `Usage:
402
- owlrunkit core-successor apply --workspace <directory> --plan <file>
415
+ npx --no-install owlrunkit core-successor apply --workspace <directory> --plan <file>
403
416
  --owner-authority <signed-v2.json> --receipt-id <id>
404
417
  `,
405
418
  "core-successor resume": `Usage:
406
- owlrunkit core-successor resume --workspace <directory> --plan <file>
419
+ npx --no-install owlrunkit core-successor resume --workspace <directory> --plan <file>
407
420
  --owner-authority <signed-v2.json> [--from-receipt <file>]
408
421
  `,
409
422
  status: `Usage:
410
- owlrunkit status --workspace <directory> [--json]
423
+ npx --no-install owlrunkit status --workspace <directory> [--json]
411
424
 
412
425
  Shows completed milestones, current state, remaining gates, and the next allowed
413
426
  action without granting any authority.
414
427
  `,
415
428
  project: `Usage:
416
- owlrunkit project init --workspace <directory> --definition <project.json>
417
- owlrunkit project assign --workspace <directory> --assignment-id <id> --at <ISO-UTC> --work-item <id> --agent <id>
429
+ npx --no-install owlrunkit project init --workspace <directory> --definition <project.json>
430
+ npx --no-install owlrunkit project assign --workspace <directory> --assignment-id <id> --at <ISO-UTC> --work-item <id> --agent <id>
418
431
  [--supersedes <current-assignment-id>] [--execution-run-id <id> --execution-work-item <id>] [--json]
419
- owlrunkit project handoff --workspace <directory> --handoff-id <id> --at <ISO-UTC>
432
+ npx --no-install owlrunkit project handoff --workspace <directory> --handoff-id <id> --at <ISO-UTC>
420
433
  --assignment-id <current> --work-item <id> --from-agent <id> --to-agent <id>
421
434
  --summary <text> --next <text> --evidence <ref> [--evidence <ref> ...] [--json]
422
- owlrunkit project decision --workspace <directory> --open --decision-id <id> --at <ISO-UTC>
435
+ npx --no-install owlrunkit project reject-and-return --workspace <directory> --rework-id <id> --at <ISO-UTC>
436
+ --work-item <failed-id> --reviewer-agent <id> --to-agent <id>
437
+ --reason <text> --next <text> --evidence <ref> [--evidence <ref> ...] [--json]
438
+ npx --no-install owlrunkit project decision --workspace <directory> --open --decision-id <id> --at <ISO-UTC>
423
439
  --title <text> --question <text> --owner-agent <id>
424
440
  [--blocking-work-item <id> ...] --option <text> [--option <text> ...] [--json]
425
- owlrunkit project decision --workspace <directory> --resolve --decision-id <id> --at <ISO-UTC>
441
+ npx --no-install owlrunkit project decision --workspace <directory> --resolve --decision-id <id> --at <ISO-UTC>
426
442
  --resolution <text> --rationale <text> --evidence <ref> [--evidence <ref> ...] [--json]
427
- owlrunkit project checkpoint --workspace <directory> --checkpoint-id <id> --at <ISO-UTC>
443
+ npx --no-install owlrunkit project checkpoint --workspace <directory> --checkpoint-id <id> --at <ISO-UTC>
428
444
  --assignment-id <current> --work-item <id>
429
445
  --state <active|waiting_dependency|waiting_decision|verifying|ready_to_integrate|completed|failed>
430
446
  --summary <text> [--completed-units <nonnegative-int>]
431
447
  [--evidence <ref> ...] [--blocker <ref> ...] [--decision <id> ...]
432
448
  [--next <text>] [--source-fingerprint <sha256>] [--json]
433
- owlrunkit project verification --workspace <directory> --defer --verification-id <id> --at <ISO-UTC>
449
+ npx --no-install owlrunkit project verification --workspace <directory> --defer --verification-id <id> --at <ISO-UTC>
434
450
  --work-item <id> --owner-agent <id> --check <check-id> [--check <check-id> ...]
435
451
  --reason <text> --due-gate <gate-id> [--json]
436
- owlrunkit project verification --workspace <directory> --close --verification-id <id> --at <ISO-UTC>
452
+ npx --no-install owlrunkit project verification --workspace <directory> --close --verification-id <id> --at <ISO-UTC>
437
453
  --disposition <verified|no_longer_required> --summary <text>
438
454
  [--evidence <ref> ...] [--decision <resolved-decision-id> ...] [--json]
439
- owlrunkit project integrate --workspace <directory> --gate <gate-id> --at <ISO-UTC>
455
+ npx --no-install owlrunkit project integrate --workspace <directory> --gate <gate-id> --at <ISO-UTC>
440
456
  --summary <text> --evidence <ref> [--evidence <ref> ...] [--json]
441
- owlrunkit project <checkpoint|handoff|decision|verification|integrate|capture> --workspace <directory> --request <event.json>
442
- owlrunkit project status --workspace <directory> [--json]
443
- owlrunkit project takeover --workspace <directory> --agent <id> [--json]
444
- owlrunkit project successor --workspace <directory> --transition-id <id> --at <ISO-UTC>
457
+ npx --no-install owlrunkit project <checkpoint|handoff|decision|verification|integrate|capture> --workspace <directory> --request <event.json>
458
+ npx --no-install owlrunkit project target-snapshot --workspace <controller> --snapshot-id <id> --at <ISO-UTC> --work-item <id> --target-workspace <frozen-worktree> --dry-run|--apply
459
+ npx --no-install owlrunkit project import-delivery --workspace <controller> --delivery-id <id> --at <ISO-UTC> --assignment-id <current> --work-item <id> --producer <id> --target-workspace <frozen-worktree> --packet <delivery-packet.json> --dry-run|--apply
460
+ npx --no-install owlrunkit project status --workspace <directory> [--json]
461
+ npx --no-install owlrunkit project takeover --workspace <directory> --agent <id> [--json]
462
+ npx --no-install owlrunkit project successor --workspace <directory> --transition-id <id> --at <ISO-UTC>
445
463
  --definition <project.json> --reason <text> [--json]
446
464
 
447
465
  Project status is derived from durable work items, Agent assignments,
@@ -449,7 +467,7 @@ dependencies, decisions, checkpoints, integration gates, and evidence refs.
449
467
  No self-reported percentage is accepted.
450
468
  `,
451
469
  "project checkpoint": `Usage:
452
- owlrunkit project checkpoint --workspace <directory> --checkpoint-id <id> --at <ISO-UTC>
470
+ npx --no-install owlrunkit project checkpoint --workspace <directory> --checkpoint-id <id> --at <ISO-UTC>
453
471
  --assignment-id <current> --work-item <id>
454
472
  --state <active|waiting_dependency|waiting_decision|verifying|ready_to_integrate|completed|failed>
455
473
  --summary <text> [--completed-units <nonnegative-int>]
@@ -458,18 +476,58 @@ No self-reported percentage is accepted.
458
476
 
459
477
  Measured WorkItems require --completed-units on every checkpoint. A completed
460
478
  checkpoint must use the WorkItem's declared total. Example:
461
- owlrunkit project checkpoint --workspace . --checkpoint-id checkpoint-x --at 2026-08-11T00:00:00.000Z --assignment-id assign-x --work-item x --state completed --summary 'Completed x.' --completed-units 5 --evidence receipt:quick
479
+ npx --no-install owlrunkit project checkpoint --workspace . --checkpoint-id checkpoint-x --at 2026-08-11T00:00:00.000Z --assignment-id assign-x --work-item x --state completed --summary 'Completed x.' --completed-units 5 --evidence receipt:quick
480
+ `,
481
+ "project assign": `Usage:
482
+ npx --no-install owlrunkit project assign --workspace <directory>
483
+ --assignment-id <id> --at <ISO-UTC> --work-item <id> --agent <id>
484
+ [--supersedes <current-assignment-id>]
485
+ [--execution-run-id <id> --execution-work-item <id>] [--json]
486
+
487
+ Assigns one current WorkItem owner without granting Git, release, deployment,
488
+ production, business, or other authorization.
489
+ `,
490
+ "project reject-and-return": `Usage:
491
+ npx --no-install owlrunkit project reject-and-return --workspace <directory> --rework-id <id> --at <ISO-UTC>
492
+ --work-item <failed-id> --reviewer-agent <id> --to-agent <id>
493
+ --reason <text> --next <text> --evidence <ref> [--evidence <ref> ...] [--json]
494
+
495
+ Atomically records the rejection and opens a new assigned rework attempt. The
496
+ failed attempt remains immutable and evidence-linked. This action does not
497
+ grant Git, release, deployment, production, or business authority.
498
+ `,
499
+ "project target-snapshot": `Usage:
500
+ npx --no-install owlrunkit project target-snapshot --workspace <controller>
501
+ --snapshot-id <id> --at <ISO-UTC> --work-item <id>
502
+ --target-workspace <frozen-worktree> [--allowed-path <path> ...]
503
+ --dry-run|--apply [--json]
504
+
505
+ Captures target HEAD and the visible dirty overlay into the controller project.
506
+ It does not write the target worktree or grant Git, release, deployment,
507
+ production, business, or other authorization.
508
+ `,
509
+ "project import-delivery": `Usage:
510
+ npx --no-install owlrunkit project import-delivery --workspace <controller>
511
+ --delivery-id <id> --at <ISO-UTC> --assignment-id <current>
512
+ --work-item <id> --producer <id> --target-workspace <frozen-worktree>
513
+ --packet <delivery-packet.json> [--entry-snapshot <id>]
514
+ --dry-run|--apply [--json]
515
+
516
+ Verifies the external DeliveryPacket against the read-only target and records
517
+ candidate identity in Project Driver only with --apply. Without an entry
518
+ snapshot it reports candidate_only and does not claim entry-to-candidate proof.
519
+ No Git, release, deployment, production, business, or other authorization is granted.
462
520
  `,
463
521
  "project status": `Usage:
464
- owlrunkit project status --workspace <directory> [--json]
522
+ npx --no-install owlrunkit project status --workspace <directory> [--json]
465
523
  `,
466
524
  "project takeover": `Usage:
467
- owlrunkit project takeover --workspace <directory> --agent <id> [--json]
525
+ npx --no-install owlrunkit project takeover --workspace <directory> --agent <id> [--json]
468
526
 
469
527
  Builds a read-only blank-session recovery packet for one Agent.
470
528
  `,
471
529
  "project successor": `Usage:
472
- owlrunkit project successor --workspace <directory> --transition-id <id> --at <ISO-UTC>
530
+ npx --no-install owlrunkit project successor --workspace <directory> --transition-id <id> --at <ISO-UTC>
473
531
  --definition <project.json> --reason <text> [--json]
474
532
 
475
533
  Archives one derived-completed active project and installs one fresh active
@@ -503,7 +561,7 @@ function correctedCheckpointCommand(argv, completedUnits) {
503
561
  "--completed-units",
504
562
  String(completedUnits),
505
563
  );
506
- return `owlrunkit ${corrected.map(shellCommandToken).join(" ")}`;
564
+ return `npx --no-install owlrunkit ${corrected.map(shellCommandToken).join(" ")}`;
507
565
  }
508
566
 
509
567
  function formatTeamProjectAssignmentHuman(result) {
@@ -536,6 +594,56 @@ function formatTeamProjectHandoffHuman(result) {
536
594
  ].join("\n");
537
595
  }
538
596
 
597
+ function formatTeamProjectReworkHuman(result) {
598
+ const disposition = result.resumed ? "Resumed" : "Returned";
599
+ const nextAction = result.nextAction === null
600
+ ? "none"
601
+ : String(result.nextAction).replace(/\s+/gu, " ").trim();
602
+ return [
603
+ `${disposition} failed WorkItem ${result.workItemId} to Agent ${result.toAgentId} for rework attempt ${result.reworkAttempt}.`,
604
+ `Failed checkpoint preserved: ${result.failedCheckpointEventId}`,
605
+ `Next: ${nextAction}`,
606
+ `Rework assignment: ${result.assignmentId}`,
607
+ "",
608
+ ].join("\n");
609
+ }
610
+
611
+ function formatTargetSnapshotHuman(result) {
612
+ return [
613
+ result.persisted
614
+ ? `Captured target snapshot ${result.snapshotId}.`
615
+ : `Previewed target snapshot ${result.snapshotId}; nothing persisted.`,
616
+ `Target: ${result.targetWorkspaceRef}`,
617
+ `HEAD: ${result.targetHead}`,
618
+ `Allowed paths: ${result.allowedPaths.join(", ")}`,
619
+ "Target write: no; authorization granted: no.",
620
+ "",
621
+ ].join("\n");
622
+ }
623
+
624
+ function formatExternalDeliveryHuman(result) {
625
+ if (result.status === "external_delivery_rejected") {
626
+ return [
627
+ `Rejected external delivery ${result.deliveryId}.`,
628
+ `Out-of-scope source: ${result.overlay?.outOfScopeSourcePaths?.join(", ") || "none"}`,
629
+ "Nothing was added to Project Driver; authorization granted: no.",
630
+ "",
631
+ ].join("\n");
632
+ }
633
+ return [
634
+ result.persisted
635
+ ? `Imported external delivery ${result.deliveryId}.`
636
+ : `Previewed external delivery ${result.deliveryId}; nothing persisted.`,
637
+ `Candidate: ${result.deliveryCandidateFingerprint}`,
638
+ `Overlay: ${result.overlay.status}`,
639
+ `Tool cache changes: ${result.overlay.toolCachePaths.join(", ") || "none"}`,
640
+ `Dependency environment changes: ${result.overlay.dependencyEnvironmentPaths.join(", ") || "none"}`,
641
+ `Not proven: ${result.notProven.join(" ")}`,
642
+ "Target write: no; authorization granted: no.",
643
+ "",
644
+ ].join("\n");
645
+ }
646
+
539
647
  function formatTeamProjectDecisionHuman(result) {
540
648
  const disposition = result.resumed
541
649
  ? "Resumed"
@@ -633,18 +741,18 @@ function onboardingProjection(root, recovery = null) {
633
741
  const steps = [
634
742
  {
635
743
  id: "doctor",
636
- command: "owlrunkit doctor --workspace .",
744
+ command: "npx --no-install owlrunkit doctor --workspace .",
637
745
  },
638
746
  ...(!profilesReady
639
747
  ? [{
640
748
  id: "profiles_detect",
641
- command: "owlrunkit profiles detect --workspace . --dry-run",
749
+ command: "npx --no-install owlrunkit profiles detect --workspace . --dry-run",
642
750
  }]
643
751
  : []),
644
752
  ...(!adoptionReady
645
753
  ? [{
646
754
  id: "adopt_or_start",
647
- command: `owlrunkit adopt --workspace . --exact owlrunkit@${CORE_VERSION} or owlrunkit start`,
755
+ command: `npx --no-install owlrunkit adopt --workspace . --exact owlrunkit@${CORE_VERSION} or npx --no-install owlrunkit start`,
648
756
  }]
649
757
  : []),
650
758
  ];
@@ -1342,9 +1450,9 @@ async function initialize(options) {
1342
1450
  `Initialized OwlRunKit ${result.core.coreVersion} in ${result.runtimeRoot}`,
1343
1451
  "",
1344
1452
  "Next:",
1345
- "1. owlrunkit doctor --workspace .",
1346
- "2. owlrunkit profiles detect --workspace . --dry-run",
1347
- `3. owlrunkit adopt --workspace . --exact owlrunkit@${CORE_VERSION} or owlrunkit start`,
1453
+ "1. npx --no-install owlrunkit doctor --workspace .",
1454
+ "2. npx --no-install owlrunkit profiles detect --workspace . --dry-run",
1455
+ `3. npx --no-install owlrunkit adopt --workspace . --exact owlrunkit@${CORE_VERSION} or npx --no-install owlrunkit start`,
1348
1456
  "",
1349
1457
  ].join("\n"),
1350
1458
  );
@@ -1644,7 +1752,7 @@ function inspect(options) {
1644
1752
  const onboarding = onboardingProjection(root, recovery);
1645
1753
  const projectDefinitionPath = runtimePath(root, "project", "definition.json");
1646
1754
  const projectDriver = pathEntryExists(projectDefinitionPath)
1647
- ? readTeamProjectStatusV1({ workspaceRoot: root })
1755
+ ? readTeamProjectStatusV2({ workspaceRoot: root })
1648
1756
  : null;
1649
1757
  const summary = buildInspectSummary(result, {
1650
1758
  maintenanceNextAction: onboarding.maintenanceNextAction ?? null,
@@ -1921,8 +2029,12 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
1921
2029
  || command === "start"
1922
2030
  || (command === "formal" && action === "start")
1923
2031
  ? ["owned-path"]
2032
+ : command === "project" && action === "target-snapshot"
2033
+ ? ["allowed-path"]
1924
2034
  : command === "project" && action === "handoff"
1925
2035
  ? ["evidence"]
2036
+ : command === "project" && action === "reject-and-return"
2037
+ ? ["evidence"]
1926
2038
  : command === "project" && action === "integrate"
1927
2039
  ? ["evidence"]
1928
2040
  : command === "project" && action === "verification"
@@ -1960,8 +2072,10 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
1960
2072
  ? ["json", "open", "resolve"]
1961
2073
  : command === "project" && action === "verification"
1962
2074
  ? ["json", "defer", "close"]
1963
- : command === "project" && new Set(["assign", "handoff", "checkpoint", "integrate", "status", "takeover", "successor"]).has(action)
2075
+ : command === "project" && new Set(["assign", "handoff", "reject-and-return", "checkpoint", "integrate", "status", "takeover", "successor"]).has(action)
1964
2076
  ? ["json"]
2077
+ : command === "project" && new Set(["target-snapshot", "import-delivery"]).has(action)
2078
+ ? ["json", "dry-run", "apply"]
1965
2079
  : command === "doctor" || command === "adopt" || command === "status"
1966
2080
  ? ["json"]
1967
2081
  : command === "profiles"
@@ -1974,8 +2088,12 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
1974
2088
  ? ["adopt-orphan-success-receipts"]
1975
2089
  : command === "deployment" && action === "execute"
1976
2090
  ? ["resume"]
1977
- : new Set(["quick-verify", "quick-attest", "quick-metrics"]).has(command)
1978
- ? ["json", "local"]
2091
+ : command === "quick-verify"
2092
+ ? ["json", "attest"]
2093
+ : command === "quick-attest"
2094
+ ? ["json"]
2095
+ : command === "quick-metrics"
2096
+ ? ["json", "local", "verbose"]
1979
2097
  : [],
1980
2098
  });
1981
2099
  if (command === "init") return await initialize(options);
@@ -2008,10 +2126,10 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2008
2126
  }
2009
2127
  if (command === "assurance") {
2010
2128
  if (action !== "route") {
2011
- throw new Error("Usage: owlrunkit assurance route --request <risk-facts.json>");
2129
+ throw new Error("Usage: npx --no-install owlrunkit assurance route --request <risk-facts.json>");
2012
2130
  }
2013
2131
  const requestPath = realpathSync(requireOption(options, "request"));
2014
- return routeRunKitAssuranceV1(readJson(requestPath));
2132
+ return routeRunKitAssuranceV2(readJson(requestPath));
2015
2133
  }
2016
2134
  if (command === "mode") {
2017
2135
  const root = workspace(options);
@@ -2038,7 +2156,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2038
2156
  "risk-category",
2039
2157
  "json",
2040
2158
  ]);
2041
- const recommendation = recommendUsageModeV1({
2159
+ const recommendation = recommendUsageModeV2({
2042
2160
  workspaceRoot: root,
2043
2161
  requestedMode: options["requested-mode"] ?? "auto",
2044
2162
  needsDurableEvidence: options["needs-evidence"] === true,
@@ -2067,11 +2185,11 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2067
2185
  });
2068
2186
  return options.json === true
2069
2187
  ? recommendation
2070
- : withHumanOutput(recommendation, formatUsageModeHumanV1(recommendation));
2188
+ : withHumanOutput(recommendation, formatUsageModeHumanV2(recommendation));
2071
2189
  }
2072
2190
  if (action === "status") {
2073
2191
  assertOnlyOptions(options, ["workspace", "json"]);
2074
- const recommendation = recommendUsageModeV1({
2192
+ const recommendation = recommendUsageModeV2({
2075
2193
  workspaceRoot: root,
2076
2194
  requestedMode: "auto",
2077
2195
  needsDurableEvidence: false,
@@ -2100,9 +2218,9 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2100
2218
  };
2101
2219
  return options.json === true
2102
2220
  ? status
2103
- : withHumanOutput(status, formatUsageModeHumanV1(status));
2221
+ : withHumanOutput(status, formatUsageModeHumanV2(status));
2104
2222
  }
2105
- throw new Error("Usage: owlrunkit mode <recommend|status> --workspace <directory>");
2223
+ throw new Error("Usage: npx --no-install owlrunkit mode <recommend|status> --workspace <directory>");
2106
2224
  }
2107
2225
  if (command === "fleet") {
2108
2226
  if (action === "register-root") {
@@ -2145,7 +2263,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2145
2263
  };
2146
2264
  }
2147
2265
  if (action !== "discover") {
2148
- throw new Error("Usage: owlrunkit fleet <register-root|inspect-registry|replace-registry|rollback-registry|discover>");
2266
+ throw new Error("Usage: npx --no-install owlrunkit fleet <register-root|inspect-registry|replace-registry|rollback-registry|discover>");
2149
2267
  }
2150
2268
  const discovered = await discoverFleet({
2151
2269
  fleetRoots: options["fleet-root"] ?? null,
@@ -2217,7 +2335,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2217
2335
  });
2218
2336
  }
2219
2337
  throw new Error(
2220
- "Usage: owlrunkit core-successor <plan|apply|resume> [options]",
2338
+ "Usage: npx --no-install owlrunkit core-successor <plan|apply|resume> [options]",
2221
2339
  );
2222
2340
  }
2223
2341
  if (command === "deployment") {
@@ -2650,7 +2768,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2650
2768
  };
2651
2769
  }
2652
2770
  }
2653
- throw new Error("Usage: owlrunkit deployment <prepare|execute> [options]");
2771
+ throw new Error("Usage: npx --no-install owlrunkit deployment <prepare|execute> [options]");
2654
2772
  }
2655
2773
  if (command === "formal") {
2656
2774
  if (action === "start") {
@@ -2732,7 +2850,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2732
2850
  authorizationGranted: false,
2733
2851
  };
2734
2852
  }
2735
- throw new Error("Usage: owlrunkit formal <start|check|finish> [options]");
2853
+ throw new Error("Usage: npx --no-install owlrunkit formal <start|check|finish> [options]");
2736
2854
  }
2737
2855
  if (command === "candidate") {
2738
2856
  if (action === "freeze") {
@@ -2772,7 +2890,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2772
2890
  targetWorkspaceRoot: requireOption(options, "target-workspace"),
2773
2891
  });
2774
2892
  }
2775
- throw new Error("Usage: owlrunkit candidate <freeze|verify|materialize> [options]");
2893
+ throw new Error("Usage: npx --no-install owlrunkit candidate <freeze|verify|materialize> [options]");
2776
2894
  }
2777
2895
  if (command === "start") return startExecution(options);
2778
2896
  if (command === "plan") {
@@ -2811,6 +2929,10 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2811
2929
  "workspace", "request", "handoff-id", "at", "assignment-id", "work-item",
2812
2930
  "from-agent", "to-agent", "summary", "next", "evidence", "json",
2813
2931
  ],
2932
+ "reject-and-return": [
2933
+ "workspace", "rework-id", "at", "work-item", "reviewer-agent",
2934
+ "to-agent", "reason", "next", "evidence", "json",
2935
+ ],
2814
2936
  decision: [
2815
2937
  "workspace", "request", "open", "resolve", "decision-id", "at", "title",
2816
2938
  "question", "owner-agent", "blocking-work-item", "option", "resolution",
@@ -2828,6 +2950,15 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2828
2950
  ],
2829
2951
  integrate: ["workspace", "request", "gate", "at", "summary", "evidence", "json"],
2830
2952
  capture: ["workspace", "request"],
2953
+ "target-snapshot": [
2954
+ "workspace", "snapshot-id", "at", "work-item", "target-workspace",
2955
+ "allowed-path", "dry-run", "apply", "json",
2956
+ ],
2957
+ "import-delivery": [
2958
+ "workspace", "delivery-id", "at", "assignment-id", "work-item",
2959
+ "producer", "target-workspace", "packet", "entry-snapshot",
2960
+ "dry-run", "apply", "json",
2961
+ ],
2831
2962
  status: ["workspace", "json"],
2832
2963
  takeover: ["workspace", "agent", "json"],
2833
2964
  successor: ["workspace", "transition-id", "at", "definition", "reason", "json"],
@@ -2842,6 +2973,43 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2842
2973
  definition: readJson(realpathSync(requireOption(options, "definition"))),
2843
2974
  });
2844
2975
  }
2976
+ if (action === "target-snapshot") {
2977
+ if ((options.apply === true) === (options["dry-run"] === true)) {
2978
+ throw new Error("project target-snapshot requires exactly one of --dry-run or --apply.");
2979
+ }
2980
+ const captured = captureTargetWorkspaceSnapshotV1({
2981
+ controllerWorkspaceRoot: root,
2982
+ snapshotId: requireOption(options, "snapshot-id"),
2983
+ occurredAt: requireOption(options, "at"),
2984
+ workItemId: requireOption(options, "work-item"),
2985
+ targetWorkspaceRoot: requireOption(options, "target-workspace"),
2986
+ allowedPaths: options["allowed-path"],
2987
+ apply: options.apply === true,
2988
+ });
2989
+ return options.json === true
2990
+ ? captured
2991
+ : withHumanOutput(captured, formatTargetSnapshotHuman(captured));
2992
+ }
2993
+ if (action === "import-delivery") {
2994
+ if ((options.apply === true) === (options["dry-run"] === true)) {
2995
+ throw new Error("project import-delivery requires exactly one of --dry-run or --apply.");
2996
+ }
2997
+ const imported = importExternalDeliveryV1({
2998
+ controllerWorkspaceRoot: root,
2999
+ deliveryId: requireOption(options, "delivery-id"),
3000
+ occurredAt: requireOption(options, "at"),
3001
+ assignmentId: requireOption(options, "assignment-id"),
3002
+ workItemId: requireOption(options, "work-item"),
3003
+ producerId: requireOption(options, "producer"),
3004
+ targetWorkspaceRoot: requireOption(options, "target-workspace"),
3005
+ packetPath: requireOption(options, "packet"),
3006
+ entrySnapshotId: options["entry-snapshot"] ?? null,
3007
+ apply: options.apply === true,
3008
+ });
3009
+ return options.json === true
3010
+ ? imported
3011
+ : withHumanOutput(imported, formatExternalDeliveryHuman(imported));
3012
+ }
2845
3013
  if (action === "assign") {
2846
3014
  const directAssignmentFields = [
2847
3015
  "assignment-id",
@@ -2859,9 +3027,13 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2859
3027
  throw new Error("--request cannot be combined with direct assignment fields.");
2860
3028
  }
2861
3029
  if (options.request !== undefined) {
3030
+ const requestedEvent = readJson(realpathSync(requireOption(options, "request")));
3031
+ if (requestedEvent?.type !== "agent_assigned") {
3032
+ throw new Error("Project assign request only accepts type=agent_assigned.");
3033
+ }
2862
3034
  return appendTeamProjectEventV1({
2863
3035
  workspaceRoot: root,
2864
- event: readJson(realpathSync(requireOption(options, "request"))),
3036
+ event: requestedEvent,
2865
3037
  });
2866
3038
  }
2867
3039
  const assigned = assignTeamProjectV1({
@@ -2897,9 +3069,13 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2897
3069
  throw new Error("--request cannot be combined with direct handoff fields.");
2898
3070
  }
2899
3071
  if (options.request !== undefined) {
3072
+ const requestedEvent = readJson(realpathSync(requireOption(options, "request")));
3073
+ if (requestedEvent?.type !== "handoff_recorded") {
3074
+ throw new Error("Project handoff request only accepts type=handoff_recorded.");
3075
+ }
2900
3076
  return appendTeamProjectEventV1({
2901
3077
  workspaceRoot: root,
2902
- event: readJson(realpathSync(requireOption(options, "request"))),
3078
+ event: requestedEvent,
2903
3079
  });
2904
3080
  }
2905
3081
  const handedOff = handoffTeamProjectV1({
@@ -2918,6 +3094,22 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2918
3094
  ? handedOff
2919
3095
  : withHumanOutput(handedOff, formatTeamProjectHandoffHuman(handedOff));
2920
3096
  }
3097
+ if (action === "reject-and-return") {
3098
+ const returned = rejectAndReturnTeamProjectV1({
3099
+ workspaceRoot: root,
3100
+ reworkId: requireOption(options, "rework-id"),
3101
+ occurredAt: requireOption(options, "at"),
3102
+ workItemId: requireOption(options, "work-item"),
3103
+ reviewerAgentId: requireOption(options, "reviewer-agent"),
3104
+ toAgentId: requireOption(options, "to-agent"),
3105
+ reason: requireOption(options, "reason"),
3106
+ nextAction: requireOption(options, "next"),
3107
+ evidenceRefs: options.evidence ?? [],
3108
+ });
3109
+ return options.json === true
3110
+ ? returned
3111
+ : withHumanOutput(returned, formatTeamProjectReworkHuman(returned));
3112
+ }
2921
3113
  if (action === "decision") {
2922
3114
  const directDecisionFields = [
2923
3115
  "open",
@@ -2940,9 +3132,16 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
2940
3132
  throw new Error("--request cannot be combined with direct decision fields.");
2941
3133
  }
2942
3134
  if (options.request !== undefined) {
3135
+ const requestedEvent = readJson(realpathSync(requireOption(options, "request")));
3136
+ if (!new Set(["decision_opened", "decision_resolved"])
3137
+ .has(requestedEvent?.type)) {
3138
+ throw new Error(
3139
+ "Project decision request only accepts type=decision_opened or decision_resolved.",
3140
+ );
3141
+ }
2943
3142
  return appendTeamProjectEventV1({
2944
3143
  workspaceRoot: root,
2945
- event: readJson(realpathSync(requireOption(options, "request"))),
3144
+ event: requestedEvent,
2946
3145
  });
2947
3146
  }
2948
3147
  if (options.open === options.resolve) {
@@ -3143,7 +3342,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3143
3342
  } catch (error) {
3144
3343
  if (error instanceof Error
3145
3344
  && error.message === "Measured work item checkpoint requires completedUnits.") {
3146
- const projectStatus = readTeamProjectStatusV1({ workspaceRoot: root });
3345
+ const projectStatus = readTeamProjectStatusV2({ workspaceRoot: root });
3147
3346
  const workItem = projectStatus.workItems.find((row) => row.workItemId === workItemId);
3148
3347
  const suggestedUnits = state === "completed"
3149
3348
  ? workItem?.progress.total
@@ -3195,25 +3394,31 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3195
3394
  : withHumanOutput(integrated, formatTeamProjectIntegrationHuman(integrated));
3196
3395
  }
3197
3396
  if (new Set(["checkpoint", "capture"]).has(action)) {
3397
+ const requestedEvent = readJson(realpathSync(requireOption(options, "request")));
3398
+ if (requestedEvent?.type === "source_delivery_imported") {
3399
+ throw new Error(
3400
+ "External source delivery events require verified intake; use project import-delivery.",
3401
+ );
3402
+ }
3198
3403
  return appendTeamProjectEventV1({
3199
3404
  workspaceRoot: root,
3200
- event: readJson(realpathSync(requireOption(options, "request"))),
3405
+ event: requestedEvent,
3201
3406
  });
3202
3407
  }
3203
3408
  if (action === "status") {
3204
- const status = readTeamProjectStatusV1({ workspaceRoot: root });
3409
+ const status = readTeamProjectStatusV2({ workspaceRoot: root });
3205
3410
  return options.json === true
3206
3411
  ? status
3207
- : withHumanOutput(status, formatTeamProjectStatusHumanV1(status));
3412
+ : withHumanOutput(status, formatTeamProjectStatusHumanV2(status));
3208
3413
  }
3209
3414
  if (action === "takeover") {
3210
- const takeover = buildTeamProjectTakeoverV1({
3415
+ const takeover = buildTeamProjectTakeoverV2({
3211
3416
  workspaceRoot: root,
3212
3417
  agentId: requireOption(options, "agent"),
3213
3418
  });
3214
3419
  return options.json === true
3215
3420
  ? takeover
3216
- : withHumanOutput(takeover, formatTeamProjectTakeoverHumanV1(takeover));
3421
+ : withHumanOutput(takeover, formatTeamProjectTakeoverHumanV2(takeover));
3217
3422
  }
3218
3423
  if (action === "successor") {
3219
3424
  const successor = successorTeamProjectV1({
@@ -3228,7 +3433,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3228
3433
  ? successor
3229
3434
  : withHumanOutput(successor, formatTeamProjectSuccessorHumanV1(successor));
3230
3435
  }
3231
- throw new Error("Usage: owlrunkit project <init|assign|checkpoint|handoff|decision|verification|integrate|capture|status|takeover|successor> [options]");
3436
+ throw new Error("Usage: npx --no-install owlrunkit project <init|assign|checkpoint|handoff|reject-and-return|decision|verification|integrate|capture|target-snapshot|import-delivery|status|takeover|successor> [options]");
3232
3437
  }
3233
3438
  if (command === "profiles") {
3234
3439
  const root = requireOption(options, "workspace");
@@ -3236,12 +3441,10 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3236
3441
  if (options.apply === true && options["dry-run"] === true) {
3237
3442
  throw new Error("profiles detect accepts either --apply or --dry-run, not both.");
3238
3443
  }
3239
- if (options["dry-run"] === true) {
3240
- return detectProfiles({ workspaceRoot: root });
3241
- }
3242
- const detection = detectProfilesV2({ workspaceRoot: root });
3444
+ if (options["dry-run"] === true) return detectProfilesV3({ workspaceRoot: root });
3445
+ const detection = detectProfilesV3({ workspaceRoot: root });
3243
3446
  return options.apply === true
3244
- ? applyDetectedProfilesV2({ workspaceRoot: root, detection })
3447
+ ? applyDetectedProfilesV3({ workspaceRoot: root, detection })
3245
3448
  : detection;
3246
3449
  }
3247
3450
  if (action === "reconcile") {
@@ -3262,7 +3465,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3262
3465
  if (changedPaths.length === 0) throw new Error("profiles impact requires --changed.");
3263
3466
  return resolveProfilesImpact({ workspaceRoot: root, changedPaths });
3264
3467
  }
3265
- throw new Error("Usage: owlrunkit profiles <detect|reconcile|validate|impact> [options]");
3468
+ throw new Error("Usage: npx --no-install owlrunkit profiles <detect|reconcile|validate|impact> [options]");
3266
3469
  }
3267
3470
  if (command === "lease") {
3268
3471
  const root = workspace(options);
@@ -3314,10 +3517,28 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3314
3517
  if (commandArgv.length === 0) {
3315
3518
  throw new Error("Usage: runkit-cli.mjs quick-verify --workspace <path> -- <executable> [args...]");
3316
3519
  }
3317
- return runQuickVerification({
3520
+ const verification = await runQuickVerification({
3318
3521
  workspaceRoot: workspace(options),
3319
3522
  commandArgv,
3523
+ stdinFile: options["stdin-file"],
3320
3524
  });
3525
+ if (options.attest !== true || typeof verification.receiptPath !== "string") {
3526
+ return verification;
3527
+ }
3528
+ const details = attestQuickReceiptDetails({
3529
+ receiptPath: verification.receiptPath,
3530
+ workspaceRoot: workspace(options),
3531
+ });
3532
+ return {
3533
+ ...verification,
3534
+ exitCode: details.exitCode === 0 ? verification.exitCode : details.exitCode,
3535
+ attestationDecision: details.attestation.decision,
3536
+ attestation: details.attestation,
3537
+ nextAllowedAction: details.attestation.decision === "GO"
3538
+ ? "consume_attestation"
3539
+ : "inspect_attestation_issues",
3540
+ authorizationGranted: false,
3541
+ };
3321
3542
  }
3322
3543
  if (command === "quick-attest") {
3323
3544
  const details = attestQuickReceiptDetails({
@@ -3339,10 +3560,9 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3339
3560
  };
3340
3561
  }
3341
3562
  if (command === "quick-metrics") {
3342
- if (options.local !== true) {
3343
- throw new Error("Quick metrics requires --local; network telemetry is not available.");
3344
- }
3345
- const local = readLocalQuickMetrics(workspace(options));
3563
+ const local = readLocalQuickMetrics(workspace(options), {
3564
+ verbose: options.verbose === true,
3565
+ });
3346
3566
  return {
3347
3567
  ...local,
3348
3568
  metrics: local.quick,
@@ -3405,7 +3625,7 @@ export async function runCli(argv = process.argv.slice(2), runtimeHooks = {}) {
3405
3625
  return withControlTransaction(root, () => closeout(options));
3406
3626
  }
3407
3627
  if (command === "finish") return finishExecution(options);
3408
- throw new Error("Usage: owlrunkit <init|doctor|adopt|mode|assurance|fleet|profiles|project|status|formal|candidate|deployment|core-successor|start|verify|repair|offline-export|offline-import|quick-verify|quick-attest|quick-metrics|finish|plan|inspect|lease|delivery|coverage-adopt|resume|verify-plan|resource-preflight|snapshot|visual-smoke|finalize|ready-for-commit|closeout> [options]");
3628
+ throw new Error("Usage: npx --no-install owlrunkit <init|doctor|adopt|mode|assurance|fleet|profiles|project|status|formal|candidate|deployment|core-successor|start|verify|repair|offline-export|offline-import|quick-verify|quick-attest|quick-metrics|finish|plan|inspect|lease|delivery|coverage-adopt|resume|verify-plan|resource-preflight|snapshot|visual-smoke|finalize|ready-for-commit|closeout> [options]");
3409
3629
  } catch (error) {
3410
3630
  return {
3411
3631
  status: "invalid_input",