zob-harness 0.12.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/.pi/capabilities/zob-public-runtime-capabilities.json +21 -2
  2. package/.pi/extensions/zob-harness/index.ts +297 -1
  3. package/.pi/extensions/zob-harness/src/core/artifact-roots.ts +55 -0
  4. package/.pi/extensions/zob-harness/src/core/constants.ts +6 -5
  5. package/.pi/extensions/zob-harness/src/domains/autonomy/autonomous-runtime/report-writers.ts +42 -41
  6. package/.pi/extensions/zob-harness/src/domains/capability/AGENTS.md +72 -0
  7. package/.pi/extensions/zob-harness/src/domains/capability/capability-contract.ts +121 -0
  8. package/.pi/extensions/zob-harness/src/domains/capability/launch-gate.ts +185 -0
  9. package/.pi/extensions/zob-harness/src/domains/capability/nudge-policy.ts +397 -0
  10. package/.pi/extensions/zob-harness/src/domains/capability/primitives.ts +192 -0
  11. package/.pi/extensions/zob-harness/src/domains/capability/types.ts +94 -0
  12. package/.pi/extensions/zob-harness/src/domains/coms/coms-v2/envelope.ts +22 -1
  13. package/.pi/extensions/zob-harness/src/domains/coms/coms-v2/local-transport.ts +23 -4
  14. package/.pi/extensions/zob-harness/src/domains/coms/coms-v2/local-transport.ts.bak.1781340854 +147 -0
  15. package/.pi/extensions/zob-harness/src/domains/coms/coms-v2/registry.ts +127 -2
  16. package/.pi/extensions/zob-harness/src/domains/coms/coms-v2/transcript-capture.ts +2 -1
  17. package/.pi/extensions/zob-harness/src/domains/coms/coms-v2/zpeer.ts +90 -21
  18. package/.pi/extensions/zob-harness/src/domains/coms/mission-control.ts +10 -7
  19. package/.pi/extensions/zob-harness/src/domains/environment/AGENTS.md +62 -0
  20. package/.pi/extensions/zob-harness/src/domains/environment/auto-resolve.ts +408 -0
  21. package/.pi/extensions/zob-harness/src/domains/environment/environment-contract.ts +104 -0
  22. package/.pi/extensions/zob-harness/src/domains/environment/launch-gate.ts +158 -0
  23. package/.pi/extensions/zob-harness/src/domains/environment/primitives.ts +134 -0
  24. package/.pi/extensions/zob-harness/src/domains/environment/types.ts +90 -0
  25. package/.pi/extensions/zob-harness/src/domains/factory/run.ts +2 -1
  26. package/.pi/extensions/zob-harness/src/domains/plan/plan-todos.ts +2 -1
  27. package/.pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts +2 -2
  28. package/.pi/extensions/zob-harness/src/domains/worklist/AGENTS.md +73 -0
  29. package/.pi/extensions/zob-harness/src/domains/worklist/dag.ts +495 -0
  30. package/.pi/extensions/zob-harness/src/domains/worklist/delivery.ts +451 -0
  31. package/.pi/extensions/zob-harness/src/domains/worklist/evidence-contract.ts +188 -0
  32. package/.pi/extensions/zob-harness/src/domains/worklist/reducer-contract.ts +193 -0
  33. package/.pi/extensions/zob-harness/src/domains/worklist/store.ts +534 -0
  34. package/.pi/extensions/zob-harness/src/domains/worklist/types.ts +203 -0
  35. package/.pi/extensions/zob-harness/src/domains/worklist/watchdog.ts +477 -0
  36. package/.pi/extensions/zob-harness/src/runtime/commands/plans.ts +12 -5
  37. package/.pi/extensions/zob-harness/src/runtime/commands/zlive.ts +80 -13
  38. package/.pi/extensions/zob-harness/src/runtime/events.ts +213 -47
  39. package/.pi/extensions/zob-harness/src/runtime/plan-capture.ts +34 -12
  40. package/.pi/extensions/zob-harness/src/runtime/plan-launch.ts +79 -9
  41. package/.pi/extensions/zob-harness/src/runtime/schemas.ts +43 -1
  42. package/.pi/extensions/zob-harness/src/runtime/state.ts +20 -3
  43. package/.pi/extensions/zob-harness/src/runtime/tools-coms.ts +38 -15
  44. package/.pi/extensions/zob-harness/src/runtime/tools-plan.ts +9 -7
  45. package/.pi/extensions/zob-harness/src/runtime/tools-worklist.ts +365 -0
  46. package/.pi/extensions/zob-harness/src/runtime/zobHarness.ts +3 -0
  47. package/.pi/prompts/implement.md +1 -0
  48. package/.pi/prompts/orchestrator.md +2 -1
  49. package/.pi/skills/zob-coms-safety/SKILL.md +5 -0
  50. package/.pi/skills/zob-coms-v2-live/SKILL.md +4 -0
  51. package/.pi/skills/zob-goal-todo-tree/SKILL.md +1 -1
  52. package/.pi/skills/zob-harness/SKILL.md +1 -1
  53. package/.pi/skills/zob-tool-router/SKILL.md +1 -0
  54. package/.pi/skills/zob-worklist/SKILL.md +52 -0
  55. package/AGENTS.md +1 -0
  56. package/README.md +2 -2
  57. package/SOURCE_INDEX.md +3 -3
  58. package/package.json +27 -25
  59. package/scripts/agentic-spec-team/validate-bdd.mjs +1 -1
  60. package/scripts/agentic-spec-team/validate-final-report.mjs +1 -1
  61. package/scripts/agentic-spec-team/validate-manifest.mjs +1 -1
  62. package/scripts/agentic-spec-team/validate-question-loop.mjs +1 -1
  63. package/scripts/agentic-spec-team/validate-source-register.mjs +1 -1
  64. package/scripts/agentic-spec-team/validate-traceability.mjs +1 -1
  65. package/scripts/agentic-spec-team/validate-workgraph.mjs +1 -1
  66. package/scripts/context-discovery/query.mjs +9 -2
  67. package/scripts/harness-intake/lib/cli-io.mjs +3 -3
  68. package/scripts/harness-intake/lib/constants.mjs +2 -1
  69. package/scripts/harness-intake/lib.mjs +1 -1
  70. package/scripts/package-surface/validate-script-refs.mjs +87 -0
  71. package/scripts/project-dna/emit/emit-golden-cases.mjs +1 -1
  72. package/scripts/project-dna/emit/emit-ontology.mjs +1 -1
  73. package/scripts/project-dna/sample/generate-sample.mjs +2 -2
  74. package/scripts/project-dna/scan/scan.mjs +1 -1
  75. package/scripts/project-dna/workflow/plan-workflow.mjs +3 -3
  76. package/scripts/project-dna/workflow/validate-workflow.mjs +2 -2
  77. package/scripts/spec-run.mjs +10 -3
  78. package/scripts/worklist/static-smoke.mjs +30 -0
  79. package/scripts/zpeer-local-e2e-smoke.mjs +29 -2
  80. package/scripts/zpeer-static-smoke.mjs +9 -3
@@ -338,7 +338,7 @@
338
338
  ".pi/extensions/zob-harness/src/AGENTS.md",
339
339
  "AGENTS.md"
340
340
  ],
341
- "noShipNotes": "Launches a saved plan TODO sidecar into runtime goal/TODO metadata; does not edit source files and must not recreate TODOs from prose. Blocks on active-goal/relaunch conflicts unless explicitly gated."
341
+ "noShipNotes": "Launches a saved plan TODO sidecar into runtime goal/TODO metadata; does not edit source files and must not recreate TODOs from prose. Safely auto-attaches to a non-complete active goal by default, remains idempotent for the same launched goal, and blocks true relaunch conflicts unless explicitly gated."
342
342
  },
343
343
  {
344
344
  "name": "create_goal",
@@ -719,7 +719,7 @@
719
719
  "docRefs": [
720
720
  ".pi/extensions/zob-harness/src/AGENTS.md"
721
721
  ],
722
- "noShipNotes": "Agent-initiated visible ZPeer ask; local_socket only, room-scoped with optional explicit roomId, mode defaults async, rate/loop guarded, raw bodies transient and durable records hash-only."
722
+ "noShipNotes": "Agent-initiated visible ZPeer ask; local_socket only, room-scoped with optional explicit roomId, mode defaults async, normal/urgent/force are rate/loop guarded, force requires a hashed reason and role/topology guards, raw bodies transient and durable records hash-only."
723
723
  },
724
724
  {
725
725
  "name": "zob_goal_room_send",
@@ -972,6 +972,25 @@
972
972
  ],
973
973
  "noShipNotes": "Lists metadata-only merge queue; no raw diffs or source writes."
974
974
  },
975
+ {
976
+ "name": "zob_worklist",
977
+ "family": "worklist",
978
+ "modes": [
979
+ "plan",
980
+ "implement",
981
+ "factory",
982
+ "orchestrator"
983
+ ],
984
+ "skillRefs": [
985
+ ".pi/skills/zob-worklist/SKILL.md",
986
+ ".pi/skills/zob-coms-safety/SKILL.md"
987
+ ],
988
+ "docRefs": [
989
+ ".pi/extensions/zob-harness/src/domains/worklist/AGENTS.md",
990
+ ".pi/extensions/zob-harness/src/AGENTS.md"
991
+ ],
992
+ "noShipNotes": "Append-only metadata-only/body-free/network-disabled worklist blackboard; claim/satisfy by content hash (lease-gated, idempotent); observe is true only when no directive is open; never stores raw bodies or dispatches live transport."
993
+ },
975
994
  {
976
995
  "name": "zob_coms_readiness",
977
996
  "family": "mission-control",
@@ -46,7 +46,7 @@ export type { ZobModeIntent, ZobModeIntentConfidence, ZobModeIntentRisk, ZobMode
46
46
  export { capturePlanArtifact, extractPlanTitle, listCapturedPlanEntries, shouldCapturePlanResponse, updateCapturedPlanEntry } from "./src/runtime/plan-capture.js";
47
47
  export type { PlanCaptureInput, PlanCaptureResult, PlanIndexEntry } from "./src/runtime/plan-capture.js";
48
48
  export { launchCapturedPlan, previewCapturedPlanLaunch, resolveCapturedPlanForLaunch } from "./src/runtime/plan-launch.js";
49
- export type { PlanLaunchInput, PlanLaunchResult, PlanLaunchSelector } from "./src/runtime/plan-launch.js";
49
+ export type { PlanActiveGoalStrategy, PlanLaunchInput, PlanLaunchResult, PlanLaunchSelector } from "./src/runtime/plan-launch.js";
50
50
  export { PLAN_TODOS_BLOCK_END, PLAN_TODOS_BLOCK_START, PLAN_TODOS_CANONICAL_SCHEMA, PLAN_TODOS_DISPLAY_CARD_END, PLAN_TODOS_DISPLAY_CARD_START, PLAN_TODOS_INPUT_SCHEMA, PLAN_TODOS_SIDECAR_SCHEMA, buildPlanTodoSidecar, canonicalManifestHash, compileMarkdownPlanTodoManifest, extractAndNormalizePlanTodoManifest, extractPlanTodosJson, formatPlanTodoManifestDisplayCard, formatPlanTodoManifestTree, normalizePlanTodoManifest, planTodoSidecarRelativePath, readPlanTodoSidecar, redactPlanTodosBlockForDisplay, validatePlanTodoSidecar, writePlanTodoSidecar } from "./src/domains/plan/plan-todos.js";
51
51
  export type { PlanLaunchStatus, PlanTodoCanonicalItem, PlanTodoCanonicalManifest, PlanTodoDisplayCardOptions, PlanTodoDisplayRedactionResult, PlanTodoManifestQuality, PlanTodoManifestResult, PlanTodoManifestSource, PlanTodoSidecar } from "./src/domains/plan/plan-todos.js";
52
52
  export { ZOB_COMPACTION_CONTINUITY_CONTRACT, ZOB_TOOL_ROUTING_CONTRACT } from "./src/core/constants.js";
@@ -129,6 +129,302 @@ export { createWorkerPoolOwnerDecision, createWorkerPoolOwnerRequest, createWork
129
129
  export type { WorkerPoolAssignmentInput, WorkerPoolAssignmentRecord, WorkerPoolCommunicationPolicyInput, WorkerPoolCommunicationPolicyMode, WorkerPoolCommunicationPolicyRecord, WorkerPoolConflictRecord, WorkerPoolDecision, WorkerPoolOwnerDecisionInput, WorkerPoolOwnerDecisionRecord, WorkerPoolOwnerRequestInput, WorkerPoolOwnerRequestRecord, WorkerPoolPlanInput, WorkerPoolPlanRecord, WorkerPoolStatusInput } from "./src/domains/governance/worker-pool.js";
130
130
  export { decideMergeCandidate, isMergeCandidateRecord, isMergeDecisionRecord, listMergeQueue, mergeQueueBodyFreeViolations, submitMergeCandidate } from "./src/domains/governance/merge-queue.js";
131
131
  export type { MergeCandidateInput, MergeCandidatePriority, MergeCandidateRecord, MergeCandidateRisk, MergeDecision, MergeDecisionInput, MergeDecisionRecord, MergeQueueListInput } from "./src/domains/governance/merge-queue.js";
132
+ export {
133
+ GENERIC_WORKLIST_REDUCER_ID,
134
+ buildDirective,
135
+ evaluateEvidenceForDirective,
136
+ genericWorklistReducer,
137
+ listWorklistReducerIds,
138
+ registerWorklistReducer,
139
+ resolveWorklistReducer,
140
+ } from "./src/domains/worklist/reducer-contract.js";
141
+ export type { BuildDirectiveInput, WorklistReducer } from "./src/domains/worklist/reducer-contract.js";
142
+ // WS-EH1: the typed evidence pillar (canonical-evidence-model PART II). The
143
+ // EvidenceContract + registry + shapes + body-free validator. Backward compatible
144
+ // (WorklistDeps.evidence is now EvidenceInput with optional gates/deps).
145
+ export {
146
+ emptyEvidenceInput,
147
+ evidenceBodyFreeViolations,
148
+ gateVerdictIsValid,
149
+ listEvidenceContractIds,
150
+ normalizeEvidenceInput,
151
+ registerEvidenceContract,
152
+ resolveEvidenceContract,
153
+ } from "./src/domains/worklist/evidence-contract.js";
154
+ export type {
155
+ DepEntry,
156
+ EvidenceContract,
157
+ EvidenceInput,
158
+ EvidenceKind,
159
+ EvidenceVerdict,
160
+ GateEntry,
161
+ TaskView,
162
+ } from "./src/domains/worklist/evidence-contract.js";
163
+ export {
164
+ FORBIDDEN_PLAINTEXT_KEYS,
165
+ WORKLIST_DIRECTIVE_SCHEMA,
166
+ WORKLIST_EVENT_SCHEMA,
167
+ WORKLIST_LEASE_SCHEMA,
168
+ WORKLIST_PROJECTION_SCHEMA,
169
+ directiveHash,
170
+ } from "./src/domains/worklist/types.js";
171
+ export type {
172
+ Directive,
173
+ ProjectedDirective,
174
+ WorklistDeps,
175
+ WorklistEvent,
176
+ WorklistEventInput,
177
+ WorklistLease,
178
+ WorklistLeaseStatus,
179
+ WorklistProjection,
180
+ WorklistValidation,
181
+ } from "./src/domains/worklist/types.js";
182
+ export {
183
+ appendWorklistEvent,
184
+ claimWorklistDirective,
185
+ isWorklistEvent,
186
+ isWorklistLease,
187
+ listWorklistDirectives,
188
+ listWorklistEvents,
189
+ listWorklistLeases,
190
+ openWorklistStore,
191
+ projectWorklist,
192
+ recoverStaleWorklistLeases,
193
+ satisfyWorklistDirective,
194
+ validateWorklist,
195
+ worklistBodyFreeViolations,
196
+ } from "./src/domains/worklist/store.js";
197
+ export type { WorklistClaimOptions, WorklistStore, WorklistStoreOptions } from "./src/domains/worklist/store.js";
198
+ export {
199
+ DEFAULT_RESEND_INTERVAL_MS,
200
+ DIRECTIVE_DELIVERY_REASON_DIRECTIVE_SATISFIED,
201
+ DIRECTIVE_DELIVERY_REASON_IN_FLIGHT,
202
+ DIRECTIVE_DELIVERY_REASON_NEW,
203
+ DIRECTIVE_DELIVERY_REASON_NO_HASH,
204
+ DIRECTIVE_DELIVERY_REASON_REDELIVER,
205
+ DIRECTIVE_DELIVERY_REASON_SEEN_ACTED,
206
+ DIRECTIVE_READY_NOTIFICATION_SCHEMA,
207
+ WORKLIST_DIRECTIVE_DELIVERY_ACTED_SCHEMA,
208
+ WORKLIST_DIRECTIVE_DELIVERY_LEDGER_SCHEMA,
209
+ deliverDirectiveNotification,
210
+ deliverDirectives,
211
+ listDeliveries,
212
+ loadDirectiveDeliveryLedger,
213
+ markDirectiveActed,
214
+ markDirectiveDeliveredActed,
215
+ planDirectiveDelivery,
216
+ reconcileDirectiveLedger,
217
+ recordDirectiveDelivery,
218
+ } from "./src/domains/worklist/delivery.js";
219
+ export type {
220
+ DeliverDirectiveNotificationOptions,
221
+ DirectiveDeliveryLedger,
222
+ DirectiveDeliveryPlan,
223
+ DirectiveDeliveryRecord,
224
+ DirectiveDeliveryResult,
225
+ DirectiveReadyNotification,
226
+ } from "./src/domains/worklist/delivery.js";
227
+ export {
228
+ DECISION_TIMEOUT_DEFAULT_MS,
229
+ ESCALATE_TO_HUMAN_DEFAULT_MS,
230
+ ESCALATE_TO_LLM_DEFAULT_MS,
231
+ ESCALATION_LEVEL_ACT_NOW,
232
+ ESCALATION_LEVEL_AUTO,
233
+ ESCALATION_LEVEL_HUMAN_BLOCK,
234
+ ESCALATION_LEVEL_NUDGE_LLM,
235
+ ESCALATION_LEVEL_WAIT,
236
+ WATCHDOG_ESCALATION_SCHEMA,
237
+ WATCHDOG_EVALUATION_SCHEMA,
238
+ WATCHDOG_TICK_RESULT_SCHEMA,
239
+ computeWatchdogEscalation,
240
+ evaluateWorklistWatchdog,
241
+ listWatchdogEscalations,
242
+ runWorklistWatchdogTick,
243
+ } from "./src/domains/worklist/watchdog.js";
244
+ export type {
245
+ WatchdogBudgets,
246
+ WatchdogEscalation,
247
+ WatchdogEscalationEntry,
248
+ WatchdogEscalationEvent,
249
+ WatchdogEvaluation,
250
+ WatchdogTickDeps,
251
+ WatchdogTickResult,
252
+ } from "./src/domains/worklist/watchdog.js";
253
+ export {
254
+ DAG_STATUSES,
255
+ WORKLIST_DAG_SCHEMA,
256
+ WORKLIST_DAG_STATE_SCHEMA,
257
+ buildDag,
258
+ buildDagOrThrow,
259
+ butterflySeedNext,
260
+ computeDownstreamImpact,
261
+ dagBodyFreeViolations,
262
+ dagFingerprint,
263
+ dependencySatisfied,
264
+ detectCycle,
265
+ isCrossScopeRef,
266
+ nodeDepsSatisfied,
267
+ parseCrossScopeRef,
268
+ readyNodes,
269
+ readDagState,
270
+ resolveCrossScopeDependency,
271
+ writeDagState,
272
+ } from "./src/domains/worklist/dag.js";
273
+ export type {
274
+ CrossScopeResolver,
275
+ DagBuildResult,
276
+ DagGraph,
277
+ DagNode,
278
+ DagNodeInput,
279
+ DagNodeStatus,
280
+ DagState,
281
+ DownstreamImpact,
282
+ } from "./src/domains/worklist/dag.js";
283
+ export { registerWorklistTools } from "./src/runtime/tools-worklist.js";
284
+ // WS-PH1 (environment-precondition PART II keystone): the typed EnvironmentContract
285
+ // pillar (the 4th pillar alongside computeWorklist/EvidenceContract). The contract
286
+ // shape + registry + PURE primitives (no node:fs/node:child_process); the body +
287
+ // snapshotEnvironment IO are project-registered (WS-PH4). Metadata-only / body-free
288
+ // / network-disabled: Precondition/PreconditionVerdict/EnvironmentSnapshot carry
289
+ // paths, counts, channel names, command strings only; FORBIDDEN_PLAINTEXT_KEYS
290
+ // applies (reused from the worklist domain).
291
+ export {
292
+ commandPresent,
293
+ dirEmpty,
294
+ pathWritable,
295
+ toolchainInstalled,
296
+ } from "./src/domains/environment/primitives.js";
297
+ export type {
298
+ CommandPresentResult,
299
+ DirEmptyResult,
300
+ PathWritableResult,
301
+ ToolchainInstalledResult,
302
+ } from "./src/domains/environment/primitives.js";
303
+ export {
304
+ environmentBodyFreeViolations,
305
+ listEnvironmentContractIds,
306
+ registerEnvironmentContract,
307
+ resolveEnvironmentContract,
308
+ } from "./src/domains/environment/environment-contract.js";
309
+ export type {
310
+ EnvironmentContract,
311
+ PreconditionScope,
312
+ } from "./src/domains/environment/environment-contract.js";
313
+ export type {
314
+ CheckPhase,
315
+ EnvironmentSnapshot,
316
+ Precondition,
317
+ PreconditionKind,
318
+ PreconditionVerdict,
319
+ } from "./src/domains/environment/types.js";
320
+ // WS-PH2 (environment-precondition PART II): the launch-time gate primitive.
321
+ // runLaunchGate snapshots once, evaluates all check_phase:"launch" preconditions,
322
+ // returns { ok, verdicts, fix_packet, shouldStart } with shouldStart === ok BY
323
+ // CONSTRUCTION (fail-closed, no opt-out). Pure over (contract, snapshot); never
324
+ // starts anything itself (mechanism in harness, action in app). Idempotent +
325
+ // re-runnable (re-snapshots on re-call). Metadata-only / body-free / network-
326
+ // disabled. No node:fs/node:child_process (the purity grep returns nothing).
327
+ export { runLaunchGate } from "./src/domains/environment/launch-gate.js";
328
+ export type {
329
+ FixPacketEntry,
330
+ LaunchGateOptions,
331
+ LaunchGateResult,
332
+ } from "./src/domains/environment/launch-gate.js";
333
+ // WS-PH3 (environment-precondition PART II — SAFETY-CRITICAL slice): the auto-resolve
334
+ // framework. applyAutoResolve applies ONLY allowlisted + REVERSIBLE strategies;
335
+ // REFUSES reversible:false ALWAYS (structurally unresolvable); SKIPS requires_network
336
+ // unless options.network===true; dispatches via PROJECT-REGISTERED
337
+ // ResolutionStrategyFn (the harness NEVER hardcodes a shell command); REFUSES
338
+ // missing-strategy + no-allowlist-match (fail-safe); DRY-RUN-FIRST (after_state:null,
339
+ // io.exec guarded). Incapable-by-construction of irreversible ops: the allowlist
340
+ // filter rejects reversible:false BEFORE dispatch. node:fs is used ONLY for the
341
+ // audit-log writer (appendFileSync); no node:child_process / direct spawn.
342
+ // Metadata-only / body-free / network-disabled (environmentBodyFreeViolations per entry).
343
+ export { AUTO_RESOLVE_AUDIT_SCHEMA, applyAutoResolve, registerResolutionStrategy } from "./src/domains/environment/auto-resolve.js";
344
+ export type {
345
+ AutoResolveAllowlist,
346
+ AutoResolveAuditEntry,
347
+ AutoResolveEntry,
348
+ AutoResolveIO,
349
+ AutoResolveOptions,
350
+ AutoResolveOutcome,
351
+ AutoResolveResult,
352
+ AutoResolveVerdict,
353
+ ResolutionStrategyFn,
354
+ } from "./src/domains/environment/auto-resolve.js";
355
+ // WS-CH1 (capability-validation PART II keystone): the typed CapabilityContract
356
+ // pillar (the 5th pillar alongside computeWorklist/EvidenceContract/EnvironmentContract).
357
+ // The contract shape + registry + PURE primitives (no node:fs/node:child_process); the
358
+ // body + readManifest IO + the role->required-tools map are project-registered (WS-CH3).
359
+ // Metadata-only / body-free / network-disabled: AgentManifest/RoleRequirement/
360
+ // CapabilityVerdict carry agent ids, tool names, mode names, manifest paths, fixCommand
361
+ // strings only; FORBIDDEN_PLAINTEXT_KEYS applies (reused from the worklist domain).
362
+ // CRITICAL SAFETY: NO auto-resolve on the contract (manifest edit = security-sensitive =
363
+ // operator-gated, unlike Round 4 env auto-resolve).
364
+ export {
365
+ buildFixPacket,
366
+ compareCapability,
367
+ manifestHasTool,
368
+ modePermitsWrite,
369
+ requiredToolsForRole,
370
+ } from "./src/domains/capability/primitives.js";
371
+ export type { CapabilityFixPacketEntry } from "./src/domains/capability/primitives.js";
372
+ export {
373
+ capabilityBodyFreeViolations,
374
+ listCapabilityContractIds,
375
+ registerCapabilityContract,
376
+ resolveCapabilityContract,
377
+ } from "./src/domains/capability/capability-contract.js";
378
+ export type { CapabilityContract } from "./src/domains/capability/capability-contract.js";
379
+ export type {
380
+ AgentManifest,
381
+ CapabilityVerdict,
382
+ RoleName,
383
+ RoleRequirement,
384
+ } from "./src/domains/capability/types.js";
385
+ // WS-CH2 (capability-validation PART II): the launch-time gate primitive + the
386
+ // runtime nudge-backoff/gap primitives. runCapabilityGate reads each manifest once
387
+ // (via the contract's readManifest), evaluates every agent against its role's
388
+ // requirement, returns { ok, verdicts, fix_packet, shouldStart } with
389
+ // shouldStart === ok BY CONSTRUCTION (fail-closed, no opt-out). Pure over
390
+ // (contract, agentIds); never starts anything itself (mechanism in harness, action
391
+ // in app). Idempotent + re-runnable (re-reads manifests on re-call). The nudge-
392
+ // policy primitives compose the supervisor anti-spam policy: planBackoffNudge
393
+ // (60s→2m→5m→15m cap + the structural capability_gap_stop), detectCapabilityGap
394
+ // (gates escalation — slow-but-capable stays gap===false), capabilityGapFixPacket
395
+ // (the metadata-only alert_no_ship fix packet), transitionOnCapabilityGap (forces
396
+ // the terminal capability_gap:true stop once gap===true). Metadata-only /
397
+ // body-free / network-disabled. No node:fs/node:child_process (the purity grep
398
+ // returns nothing). CRITICAL SAFETY: NO auto-resolve (manifest edit = security-
399
+ // sensitive = operator-gated, intentional divergence from Round 4 env auto-resolve).
400
+ export { runCapabilityGate } from "./src/domains/capability/launch-gate.js";
401
+ // NOTE: aliased as CapabilityLaunchGateOptions / CapabilityLaunchGateResult to
402
+ // avoid a name collision with the WS-PH2 environment pillar's identically-named
403
+ // LaunchGateOptions / LaunchGateResult exports above (index.ts ~L330). Both
404
+ // shapes exist; consumers pick the capability gate via the `Capability*` prefix.
405
+ export type {
406
+ LaunchGateOptions as CapabilityLaunchGateOptions,
407
+ LaunchGateResult as CapabilityLaunchGateResult,
408
+ } from "./src/domains/capability/launch-gate.js";
409
+ export {
410
+ DEFAULT_NUDGE_SCHEDULE,
411
+ NUDGE_BACKOFF_CAP_MS,
412
+ capabilityGapFixPacket,
413
+ detectCapabilityGap,
414
+ planBackoffNudge,
415
+ transitionOnCapabilityGap,
416
+ } from "./src/domains/capability/nudge-policy.js";
417
+ export type {
418
+ CapabilityGapAction,
419
+ CapabilityGapFixPacket,
420
+ CapabilityGapTransition,
421
+ DetectCapabilityGapInput,
422
+ DriverRecord,
423
+ GapResult,
424
+ NudgePlan,
425
+ NudgeSchedule,
426
+ PlanBackoffNudgeInput,
427
+ } from "./src/domains/capability/nudge-policy.js";
132
428
  export { DEFAULT_PROMOTION_GATES, advancePromotionCandidate, appendPromotionLedger, createPromotionCandidate, promotionCandidateDir, promotionCandidateRef, promotionReportsDir, summarizePromotionCandidates, transitionAllowed, validatePromotionCandidate, writePromotionCandidate } from "./src/domains/promotion/candidate.js";
133
429
  export { addPromotionComsMessageRef, buildPromotionComsMessageRef, buildPromotionComsThread, validatePromotionComsMessageRef, validatePromotionComsReadiness, validatePromotionComsThread, writePromotionComsThread } from "./src/domains/promotion/coms.js";
134
430
  export { applyDocumentationPromotionInQuarantine, prepareDocumentationPromotion, validateDocumentationPromotion, validateDocumentationPromotionCandidate } from "./src/domains/promotion/documentation.js";
@@ -0,0 +1,55 @@
1
+ import { existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ export const PRIMARY_PLANS_ROOT = ".pi/plans";
5
+ export const LEGACY_PLANS_ROOT = "plans";
6
+ export const PRIMARY_REPORTS_ROOT = ".pi/reports";
7
+ export const LEGACY_REPORTS_ROOT = "reports";
8
+
9
+ export type ArtifactRootKind = "plans" | "reports";
10
+
11
+ function normalizeSegments(segments: string[]): string[] {
12
+ return segments.flatMap((segment) => segment.split("/")).filter(Boolean);
13
+ }
14
+
15
+ export function artifactRootRef(kind: ArtifactRootKind, legacy = false): string {
16
+ if (kind === "plans") return legacy ? LEGACY_PLANS_ROOT : PRIMARY_PLANS_ROOT;
17
+ return legacy ? LEGACY_REPORTS_ROOT : PRIMARY_REPORTS_ROOT;
18
+ }
19
+
20
+ export function artifactRootPath(repoRoot: string, kind: ArtifactRootKind, legacy = false): string {
21
+ return join(repoRoot, ...artifactRootRef(kind, legacy).split("/"));
22
+ }
23
+
24
+ export function artifactRef(kind: ArtifactRootKind, ...segments: string[]): string {
25
+ return [artifactRootRef(kind), ...normalizeSegments(segments)].join("/");
26
+ }
27
+
28
+ export function legacyArtifactRef(kind: ArtifactRootKind, ...segments: string[]): string {
29
+ return [artifactRootRef(kind, true), ...normalizeSegments(segments)].join("/");
30
+ }
31
+
32
+ export function artifactPath(repoRoot: string, kind: ArtifactRootKind, ...segments: string[]): string {
33
+ return join(artifactRootPath(repoRoot, kind), ...normalizeSegments(segments));
34
+ }
35
+
36
+ export function legacyArtifactPath(repoRoot: string, kind: ArtifactRootKind, ...segments: string[]): string {
37
+ return join(artifactRootPath(repoRoot, kind, true), ...normalizeSegments(segments));
38
+ }
39
+
40
+ export function isArtifactRef(value: string, kind: ArtifactRootKind, options: { legacy?: boolean } = {}): boolean {
41
+ const normalized = value.replace(/^\.\//, "");
42
+ const primary = artifactRootRef(kind);
43
+ const legacy = artifactRootRef(kind, true);
44
+ return normalized === primary || normalized.startsWith(`${primary}/`) || options.legacy === true && (normalized === legacy || normalized.startsWith(`${legacy}/`));
45
+ }
46
+
47
+ export function existingArtifactRoots(repoRoot: string, kind: ArtifactRootKind, ...segments: string[]): string[] {
48
+ const primary = artifactPath(repoRoot, kind, ...segments);
49
+ const legacy = legacyArtifactPath(repoRoot, kind, ...segments);
50
+ return [primary, legacy].filter((path, index, paths) => paths.indexOf(path) === index && existsSync(path));
51
+ }
52
+
53
+ export function firstExistingArtifactPath(repoRoot: string, kind: ArtifactRootKind, ...segments: string[]): string {
54
+ return existingArtifactRoots(repoRoot, kind, ...segments)[0] ?? artifactPath(repoRoot, kind, ...segments);
55
+ }
@@ -18,7 +18,7 @@ export { DEFAULT_RULES };
18
18
  export const ZOB_TOOL_ROUTING_CONTRACT = [
19
19
  "ZOB TOOL ROUTING CONTRACT",
20
20
  "- For non-trivial or tool-ambiguous work, run a lightweight routing loop before acting.",
21
- "- Classify applicable families: goal/TODO, delegation, orchestration, compute, context/ProjectDNA, factory, coms/goal-room, workspace/merge, autonomous-runtime, oracle.",
21
+ "- Classify applicable families: goal/TODO, delegation, orchestration, compute, context/ProjectDNA, factory, coms/goal-room, worklist/liveness, workspace/merge, autonomous-runtime, oracle.",
22
22
  "- Load .pi/skills/zob-tool-router/SKILL.md when routing is uncertain or work spans multiple families; then load the domain skill(s) named by the registry.",
23
23
  "- Use the smallest sufficient tool set: use, delegate, or explicitly skip applicable families with a reason.",
24
24
  "- Do not bypass mode/tool safety, approval, sandbox, budget, evidence, or oracle gates.",
@@ -51,6 +51,7 @@ export const ZOB_GOAL_ROOM_TOOLS = ["zob_goal_room_send", "zob_goal_room_list"]
51
51
  export const ZOB_GOVERNED_REQUEST_TOOLS = ["zob_governed_request_extract"] as const;
52
52
  export const ZOB_WORKSPACE_CLAIM_TOOLS = ["zob_workspace_claim", "zob_workspace_release", "zob_workspace_claims_list"] as const;
53
53
  export const ZOB_WORKER_POOL_TOOLS = ["zob_worker_pool_plan", "zob_worker_pool_status", "zob_worker_pool_owner_request", "zob_worker_pool_owner_decision"] as const;
54
+ export const ZOB_WORKLIST_TOOLS = ["zob_worklist"] as const;
54
55
  export const ZOB_MERGE_QUEUE_TOOLS = ["zob_merge_candidate_submit", "zob_merge_queue_decide", "zob_merge_queue_list"] as const;
55
56
  export const ZOB_ZCOMMIT_TOOLS = ["zob_zcommit_run"] as const;
56
57
  export const ZOB_ZAGENT_TOOLS = ["zob_zteam_hot_add", "zob_zteam_remove"] as const;
@@ -70,11 +71,11 @@ export const ZOB_AUTONOMOUS_FACTORY_TOOLS = ["zob_autonomous_dry_run", "zob_auto
70
71
 
71
72
  export const MODE_TOOLS: Record<ModeName, string[]> = {
72
73
  explore: ["read", "grep", "find", "ls", "bash", "delegate_agent", "delegate_task", "zob_coms_list", "zob_coms_get", "zob_coms_await", "zpeer_ask", "zob_goal_room_list", "zob_workspace_claims_list", "zob_worker_pool_status", "zob_merge_queue_list", ...ZOB_RUNTIME_GOAL_TOOLS, ...ZOB_DELEGATION_READ_TOOLS, ...ZOB_ZCOMMIT_TOOLS, ...ZOB_AUTONOMOUS_READ_TOOLS, ...ZOB_MISSION_CONTROL_READ_TOOLS, ...ZOB_CONTEXT_READ_TOOLS, ...ZOB_COMPUTE_READ_TOOLS, ...ZOB_PROJECT_DNA_READ_TOOLS],
73
- plan: ["read", "grep", "find", "ls", "delegate_agent", "delegate_task", "orchestrate_run", "chain_run", ...ZOB_PLAN_LAUNCH_TOOLS, ...ZOB_RUNTIME_GOAL_TOOLS, ...ZOB_DELEGATION_READ_TOOLS, ...ZOB_ZCOMMIT_TOOLS, ...ZOB_ZAGENT_TOOLS, ...ZOB_COMS_TOOLS, ...ZOB_GOAL_ROOM_TOOLS, ...ZOB_GOVERNED_REQUEST_TOOLS, ...ZOB_WORKSPACE_CLAIM_TOOLS, ...ZOB_WORKER_POOL_TOOLS, ...ZOB_MERGE_QUEUE_TOOLS, ...ZOB_MISSION_CONTROL_READ_TOOLS, ...ZOB_MISSION_CONTROL_PROPOSAL_TOOLS, ...ZOB_CONTEXT_READ_TOOLS, ...ZOB_CONTEXT_PROPOSAL_TOOLS, ...ZOB_COMPUTE_READ_TOOLS, ...ZOB_COMPUTE_REPORT_TOOLS, ...ZOB_PROJECT_DNA_READ_TOOLS, ...ZOB_PROJECT_DNA_PROPOSAL_TOOLS],
74
- implement: ["read", "bash", "edit", "write", "grep", "find", "ls", "delegate_agent", "delegate_task", ...ZOB_PLAN_LAUNCH_TOOLS, ...ZOB_RUNTIME_GOAL_TOOLS, ...ZOB_DELEGATION_READ_TOOLS, ...ZOB_ZCOMMIT_TOOLS, ...ZOB_ZAGENT_TOOLS, ...ZOB_COMS_TOOLS, ...ZOB_GOAL_ROOM_TOOLS, ...ZOB_GOVERNED_REQUEST_TOOLS, ...ZOB_WORKSPACE_CLAIM_TOOLS, ...ZOB_WORKER_POOL_TOOLS, ...ZOB_MERGE_QUEUE_TOOLS, ...ZOB_MISSION_CONTROL_READ_TOOLS, ...ZOB_MISSION_CONTROL_PROPOSAL_TOOLS, ...ZOB_CONTEXT_READ_TOOLS, ...ZOB_CONTEXT_PROPOSAL_TOOLS, ...ZOB_COMPUTE_READ_TOOLS, ...ZOB_COMPUTE_REPORT_TOOLS, ...ZOB_PROJECT_DNA_READ_TOOLS, ...ZOB_PROJECT_DNA_PROPOSAL_TOOLS],
74
+ plan: ["read", "grep", "find", "ls", "delegate_agent", "delegate_task", "orchestrate_run", "chain_run", ...ZOB_PLAN_LAUNCH_TOOLS, ...ZOB_RUNTIME_GOAL_TOOLS, ...ZOB_DELEGATION_READ_TOOLS, ...ZOB_ZCOMMIT_TOOLS, ...ZOB_ZAGENT_TOOLS, ...ZOB_COMS_TOOLS, ...ZOB_GOAL_ROOM_TOOLS, ...ZOB_GOVERNED_REQUEST_TOOLS, ...ZOB_WORKSPACE_CLAIM_TOOLS, ...ZOB_WORKER_POOL_TOOLS, ...ZOB_MERGE_QUEUE_TOOLS, ...ZOB_WORKLIST_TOOLS, ...ZOB_MISSION_CONTROL_READ_TOOLS, ...ZOB_MISSION_CONTROL_PROPOSAL_TOOLS, ...ZOB_CONTEXT_READ_TOOLS, ...ZOB_CONTEXT_PROPOSAL_TOOLS, ...ZOB_COMPUTE_READ_TOOLS, ...ZOB_COMPUTE_REPORT_TOOLS, ...ZOB_PROJECT_DNA_READ_TOOLS, ...ZOB_PROJECT_DNA_PROPOSAL_TOOLS],
75
+ implement: ["read", "bash", "edit", "write", "grep", "find", "ls", "delegate_agent", "delegate_task", ...ZOB_PLAN_LAUNCH_TOOLS, ...ZOB_RUNTIME_GOAL_TOOLS, ...ZOB_DELEGATION_READ_TOOLS, ...ZOB_ZCOMMIT_TOOLS, ...ZOB_ZAGENT_TOOLS, ...ZOB_COMS_TOOLS, ...ZOB_GOAL_ROOM_TOOLS, ...ZOB_GOVERNED_REQUEST_TOOLS, ...ZOB_WORKSPACE_CLAIM_TOOLS, ...ZOB_WORKER_POOL_TOOLS, ...ZOB_MERGE_QUEUE_TOOLS, ...ZOB_WORKLIST_TOOLS, ...ZOB_MISSION_CONTROL_READ_TOOLS, ...ZOB_MISSION_CONTROL_PROPOSAL_TOOLS, ...ZOB_CONTEXT_READ_TOOLS, ...ZOB_CONTEXT_PROPOSAL_TOOLS, ...ZOB_COMPUTE_READ_TOOLS, ...ZOB_COMPUTE_REPORT_TOOLS, ...ZOB_PROJECT_DNA_READ_TOOLS, ...ZOB_PROJECT_DNA_PROPOSAL_TOOLS],
75
76
  oracle: ["read", "grep", "find", "ls", "bash", "delegate_agent", "delegate_task", "zob_coms_list", "zob_coms_get", "zob_coms_await", "zpeer_ask", "zob_goal_room_list", "zob_workspace_claims_list", "zob_worker_pool_status", "zob_merge_queue_list", ...ZOB_RUNTIME_GOAL_TOOLS, ...ZOB_DELEGATION_READ_TOOLS, ...ZOB_ZCOMMIT_TOOLS, ...ZOB_AUTONOMOUS_READ_TOOLS, ...ZOB_MISSION_CONTROL_READ_TOOLS, ...ZOB_CONTEXT_READ_TOOLS, ...ZOB_COMPUTE_READ_TOOLS, ...ZOB_PROJECT_DNA_READ_TOOLS],
76
- orchestrator: ["read", "grep", "find", "ls", "delegate_agent", "delegate_task", "orchestrate_run", "chain_run", ...ZOB_PLAN_LAUNCH_TOOLS, ...ZOB_RUNTIME_GOAL_TOOLS, ...ZOB_DELEGATION_READ_TOOLS, ...ZOB_ZCOMMIT_TOOLS, ...ZOB_ZAGENT_TOOLS, ...ZOB_COMS_TOOLS, ...ZOB_GOAL_ROOM_TOOLS, ...ZOB_GOVERNED_REQUEST_TOOLS, ...ZOB_WORKSPACE_CLAIM_TOOLS, ...ZOB_WORKER_POOL_TOOLS, ...ZOB_MERGE_QUEUE_TOOLS, ...ZOB_MISSION_CONTROL_READ_TOOLS, ...ZOB_MISSION_CONTROL_PROPOSAL_TOOLS, ...ZOB_CONTEXT_READ_TOOLS, ...ZOB_CONTEXT_PROPOSAL_TOOLS, ...ZOB_COMPUTE_READ_TOOLS, ...ZOB_COMPUTE_REPORT_TOOLS],
77
- factory: ["read", "bash", "edit", "write", "grep", "find", "ls", "delegate_agent", "delegate_task", "orchestrate_run", "factory_run", "factory_quarantine_review", "factory_quarantine_activate", "factory_quarantine_verify_activation", "chain_run", ...ZOB_PLAN_LAUNCH_TOOLS, ...ZOB_RUNTIME_GOAL_TOOLS, ...ZOB_DELEGATION_READ_TOOLS, ...ZOB_ZCOMMIT_TOOLS, ...ZOB_ZAGENT_TOOLS, ...ZOB_AUTONOMOUS_READ_TOOLS, ...ZOB_AUTONOMOUS_FACTORY_TOOLS, ...ZOB_COMS_TOOLS, ...ZOB_GOAL_ROOM_TOOLS, ...ZOB_GOVERNED_REQUEST_TOOLS, ...ZOB_WORKSPACE_CLAIM_TOOLS, ...ZOB_WORKER_POOL_TOOLS, ...ZOB_MERGE_QUEUE_TOOLS, ...ZOB_MISSION_CONTROL_READ_TOOLS, ...ZOB_MISSION_CONTROL_PROPOSAL_TOOLS, ...ZOB_CONTEXT_READ_TOOLS, ...ZOB_CONTEXT_PROPOSAL_TOOLS, ...ZOB_COMPUTE_READ_TOOLS, ...ZOB_COMPUTE_REPORT_TOOLS, ...ZOB_PROJECT_DNA_READ_TOOLS, ...ZOB_PROJECT_DNA_PROPOSAL_TOOLS],
77
+ orchestrator: ["read", "grep", "find", "ls", "delegate_agent", "delegate_task", "orchestrate_run", "chain_run", ...ZOB_PLAN_LAUNCH_TOOLS, ...ZOB_RUNTIME_GOAL_TOOLS, ...ZOB_DELEGATION_READ_TOOLS, ...ZOB_ZCOMMIT_TOOLS, ...ZOB_ZAGENT_TOOLS, ...ZOB_COMS_TOOLS, ...ZOB_GOAL_ROOM_TOOLS, ...ZOB_GOVERNED_REQUEST_TOOLS, ...ZOB_WORKSPACE_CLAIM_TOOLS, ...ZOB_WORKER_POOL_TOOLS, ...ZOB_MERGE_QUEUE_TOOLS, ...ZOB_WORKLIST_TOOLS, ...ZOB_MISSION_CONTROL_READ_TOOLS, ...ZOB_MISSION_CONTROL_PROPOSAL_TOOLS, ...ZOB_CONTEXT_READ_TOOLS, ...ZOB_CONTEXT_PROPOSAL_TOOLS, ...ZOB_COMPUTE_READ_TOOLS, ...ZOB_COMPUTE_REPORT_TOOLS],
78
+ factory: ["read", "bash", "edit", "write", "grep", "find", "ls", "delegate_agent", "delegate_task", "orchestrate_run", "factory_run", "factory_quarantine_review", "factory_quarantine_activate", "factory_quarantine_verify_activation", "chain_run", ...ZOB_PLAN_LAUNCH_TOOLS, ...ZOB_RUNTIME_GOAL_TOOLS, ...ZOB_DELEGATION_READ_TOOLS, ...ZOB_ZCOMMIT_TOOLS, ...ZOB_ZAGENT_TOOLS, ...ZOB_AUTONOMOUS_READ_TOOLS, ...ZOB_AUTONOMOUS_FACTORY_TOOLS, ...ZOB_COMS_TOOLS, ...ZOB_GOAL_ROOM_TOOLS, ...ZOB_GOVERNED_REQUEST_TOOLS, ...ZOB_WORKSPACE_CLAIM_TOOLS, ...ZOB_WORKER_POOL_TOOLS, ...ZOB_MERGE_QUEUE_TOOLS, ...ZOB_WORKLIST_TOOLS, ...ZOB_MISSION_CONTROL_READ_TOOLS, ...ZOB_MISSION_CONTROL_PROPOSAL_TOOLS, ...ZOB_CONTEXT_READ_TOOLS, ...ZOB_CONTEXT_PROPOSAL_TOOLS, ...ZOB_COMPUTE_READ_TOOLS, ...ZOB_COMPUTE_REPORT_TOOLS, ...ZOB_PROJECT_DNA_READ_TOOLS, ...ZOB_PROJECT_DNA_PROPOSAL_TOOLS],
78
79
  // Vanilla is handled specially by applyMode: all currently available Pi tools are enabled.
79
80
  vanilla: [],
80
81
  };
@@ -1,5 +1,6 @@
1
1
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
2
  import { join } from "node:path";
3
+ import { artifactPath, artifactRef, firstExistingArtifactPath } from "../../../core/artifact-roots.js";
3
4
  import { runFactoryRun } from "../../factory/run.js";
4
5
  import { sha256 } from "../../../core/utils/hashing.js";
5
6
  import { safeFileStem } from "../../../core/utils/paths.js";
@@ -12,7 +13,7 @@ export function writeAutonomousRuntimeDryRunReport(repoRoot: string, input: Auto
12
13
  const report = buildAutonomousRuntimeDryRun(repoRoot, input);
13
14
  const runId = String(report.runId);
14
15
  const safeRunId = safeFileStem(runId);
15
- const runDir = join(repoRoot, "reports", "autonomous-runs", safeRunId);
16
+ const runDir = artifactPath(repoRoot, "reports", "autonomous-runs", safeRunId);
16
17
  mkdirSync(runDir, { recursive: true });
17
18
  const specGatePath = join(runDir, "spec-gate.json");
18
19
  const contextScopePath = join(runDir, "context-scope.json");
@@ -44,25 +45,25 @@ export function writeAutonomousRuntimeDryRunReport(repoRoot: string, input: Auto
44
45
  if (report.status === "dry_run_plan_ready") writeFileSync(join(runDir, "DRY_RUN_READY.sentinel"), "dry-run-ready\n");
45
46
  return {
46
47
  ...report,
47
- specGatePath: `reports/autonomous-runs/${safeRunId}/spec-gate.json`,
48
- contextScopePath: `reports/autonomous-runs/${safeRunId}/context-scope.json`,
49
- contextLookupPath: `reports/autonomous-runs/${safeRunId}/context-lookup.json`,
50
- contextPackPath: `reports/autonomous-runs/${safeRunId}/context-pack.json`,
51
- runtimeGatesPath: `reports/autonomous-runs/${safeRunId}/runtime-gates.json`,
52
- modelRoutingPlanPath: `reports/autonomous-runs/${safeRunId}/model-routing-plan.json`,
53
- runGraphPath: `reports/autonomous-runs/${safeRunId}/run-graph.json`,
54
- factorySelectionPath: `reports/autonomous-runs/${safeRunId}/factory-selection.json`,
55
- proofPlanPath: `reports/autonomous-runs/${safeRunId}/proof-plan.json`,
56
- reportPath: `reports/autonomous-runs/${safeRunId}/dry-run-report.json`,
57
- validationPath: `reports/autonomous-runs/${safeRunId}/validation.json`,
58
- finalReportPath: `reports/autonomous-runs/${safeRunId}/final-report.md`,
59
- sentinelPath: report.status === "dry_run_plan_ready" ? `reports/autonomous-runs/${safeRunId}/DRY_RUN_READY.sentinel` : undefined,
48
+ specGatePath: artifactRef("reports", "autonomous-runs", safeRunId, "spec-gate.json"),
49
+ contextScopePath: artifactRef("reports", "autonomous-runs", safeRunId, "context-scope.json"),
50
+ contextLookupPath: artifactRef("reports", "autonomous-runs", safeRunId, "context-lookup.json"),
51
+ contextPackPath: artifactRef("reports", "autonomous-runs", safeRunId, "context-pack.json"),
52
+ runtimeGatesPath: artifactRef("reports", "autonomous-runs", safeRunId, "runtime-gates.json"),
53
+ modelRoutingPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "model-routing-plan.json"),
54
+ runGraphPath: artifactRef("reports", "autonomous-runs", safeRunId, "run-graph.json"),
55
+ factorySelectionPath: artifactRef("reports", "autonomous-runs", safeRunId, "factory-selection.json"),
56
+ proofPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "proof-plan.json"),
57
+ reportPath: artifactRef("reports", "autonomous-runs", safeRunId, "dry-run-report.json"),
58
+ validationPath: artifactRef("reports", "autonomous-runs", safeRunId, "validation.json"),
59
+ finalReportPath: artifactRef("reports", "autonomous-runs", safeRunId, "final-report.md"),
60
+ sentinelPath: report.status === "dry_run_plan_ready" ? artifactRef("reports", "autonomous-runs", safeRunId, "DRY_RUN_READY.sentinel") : undefined,
60
61
  };
61
62
  }
62
63
  export function writeAutonomousReadOnlySmokeRunReport(repoRoot: string, input: AutonomousReadOnlySmokeRunInput): Record<string, unknown> {
63
64
  const runId = safeFileStem(input.runId ?? `autonomous-readonly-smoke-${sha256(input.userNeed || "missing-spec").slice(0, 12)}`);
64
65
  const safeRunId = safeFileStem(runId);
65
- const runDir = join(repoRoot, "reports", "autonomous-runs", safeRunId);
66
+ const runDir = artifactPath(repoRoot, "reports", "autonomous-runs", safeRunId);
66
67
  const smokeAutonomySentinelPath = join(runDir, "SMOKE_AUTONOMY_PASSED.sentinel");
67
68
  if (existsSync(smokeAutonomySentinelPath)) throw new Error(`Autonomous smoke run already passed; choose a fresh run_id to avoid stale sentinel reuse: ${runId}`);
68
69
  const dryRun = writeAutonomousRuntimeDryRunReport(repoRoot, {
@@ -75,7 +76,7 @@ export function writeAutonomousReadOnlySmokeRunReport(repoRoot: string, input: A
75
76
  const selectedFactory = typeof factorySelection.selectedFactory === "string" ? factorySelection.selectedFactory : undefined;
76
77
  const manifestPath = selectedFactory ? `.pi/factories/${selectedFactory}/smoke-manifest.json` : undefined;
77
78
  const factoryRunId = safeFileStem(input.factoryRunId ?? `autonomous-smoke-${safeRunId}`);
78
- const factoryRunAlreadyExists = existsSync(join(repoRoot, "reports", "factory-runs", factoryRunId));
79
+ const factoryRunAlreadyExists = existsSync(firstExistingArtifactPath(repoRoot, "reports", "factory-runs", factoryRunId));
79
80
  const blockers = [
80
81
  ...(dryRun.status === "dry_run_plan_ready" ? [] : ["dry_run_not_ready"]),
81
82
  ...(isRecord(dryRun.validation) && Array.isArray(dryRun.validation.blockers) ? dryRun.validation.blockers.filter((blocker): blocker is string => typeof blocker === "string") : []),
@@ -99,7 +100,7 @@ export function writeAutonomousReadOnlySmokeRunReport(repoRoot: string, input: A
99
100
  budget: { strictRequested: true, strictEnabled: false, maxRuns: 1, estimatedRuns: 1, maxParallelChildren: 1, estimatedParallelChildren: 1 },
100
101
  model_routing: { enabled: false, risk: input.risk ?? "medium", contextTokens: input.maxContextTokens },
101
102
  }) : undefined;
102
- const factoryRunDir = join(repoRoot, "reports", "factory-runs", factoryRunId);
103
+ const factoryRunDir = firstExistingArtifactPath(repoRoot, "reports", "factory-runs", factoryRunId);
103
104
  const factoryValidationPath = join(factoryRunDir, "validation.json");
104
105
  const factoryValidationRead = readJsonArtifact(factoryValidationPath);
105
106
  const factoryValidation = isRecord(factoryValidationRead.parsed) ? factoryValidationRead.parsed : {};
@@ -164,12 +165,12 @@ export function writeAutonomousReadOnlySmokeRunReport(repoRoot: string, input: A
164
165
  checks: oracleChecks,
165
166
  failedChecks: oracleChecks.filter((check) => check.passed !== true).map((check) => check.name),
166
167
  evidenceRefs: [
167
- `reports/autonomous-runs/${safeRunId}/spec-gate.json`,
168
- `reports/autonomous-runs/${safeRunId}/context-pack.json`,
169
- `reports/autonomous-runs/${safeRunId}/runtime-gates.json`,
170
- `reports/autonomous-runs/${safeRunId}/model-routing-plan.json`,
171
- `reports/autonomous-runs/${safeRunId}/factory-selection.json`,
172
- `reports/autonomous-runs/${safeRunId}/factory-run-ref.json`,
168
+ artifactRef("reports", "autonomous-runs", safeRunId, "spec-gate.json"),
169
+ artifactRef("reports", "autonomous-runs", safeRunId, "context-pack.json"),
170
+ artifactRef("reports", "autonomous-runs", safeRunId, "runtime-gates.json"),
171
+ artifactRef("reports", "autonomous-runs", safeRunId, "model-routing-plan.json"),
172
+ artifactRef("reports", "autonomous-runs", safeRunId, "factory-selection.json"),
173
+ artifactRef("reports", "autonomous-runs", safeRunId, "factory-run-ref.json"),
173
174
  relativeFactoryRunPath(factoryRunId, "validation.json"),
174
175
  relativeFactoryRunPath(factoryRunId, "SMOKE_PASSED.sentinel"),
175
176
  relativeFactoryRunPath(factoryRunId, "DONE.sentinel"),
@@ -303,23 +304,23 @@ export function writeAutonomousReadOnlySmokeRunReport(repoRoot: string, input: A
303
304
  finalNoShipOracle,
304
305
  completionGate,
305
306
  validation,
306
- factoryRunRefPath: `reports/autonomous-runs/${safeRunId}/factory-run-ref.json`,
307
- oracleReviewPath: `reports/autonomous-runs/${safeRunId}/oracle-review.json`,
308
- promotionPlanPath: `reports/autonomous-runs/${safeRunId}/promotion-plan.json`,
309
- promotionProofPlanPath: `reports/autonomous-runs/${safeRunId}/promotion-proof-plan.json`,
310
- schedulerPlanPath: `reports/autonomous-runs/${safeRunId}/scheduler-plan.json`,
311
- schedulerProofPlanPath: `reports/autonomous-runs/${safeRunId}/scheduler-proof-plan.json`,
312
- missionControlPlanPath: `reports/autonomous-runs/${safeRunId}/mission-control-plan.json`,
313
- missionControlProofPlanPath: `reports/autonomous-runs/${safeRunId}/mission-control-proof-plan.json`,
314
- sandboxApplyPlanPath: `reports/autonomous-runs/${safeRunId}/sandbox-apply-plan.json`,
315
- strictBudgetProofPlanPath: `reports/autonomous-runs/${safeRunId}/strict-budget-proof-plan.json`,
316
- modelRoutingProofPlanPath: `reports/autonomous-runs/${safeRunId}/model-routing-proof-plan.json`,
317
- currentSourceFingerprintPath: `reports/autonomous-runs/${safeRunId}/current-source-fingerprint.json`,
318
- finalE2EProofPlanPath: `reports/autonomous-runs/${safeRunId}/final-e2e-proof-plan.json`,
319
- finalNoShipOraclePath: `reports/autonomous-runs/${safeRunId}/final-no-ship-oracle.json`,
320
- completionGatePath: `reports/autonomous-runs/${safeRunId}/completion-gate.json`,
321
- validationPath: `reports/autonomous-runs/${safeRunId}/validation.json`,
322
- finalReportPath: `reports/autonomous-runs/${safeRunId}/final-report.md`,
323
- smokeSentinelPath: structuralOraclePassed ? `reports/autonomous-runs/${safeRunId}/SMOKE_AUTONOMY_PASSED.sentinel` : undefined,
307
+ factoryRunRefPath: artifactRef("reports", "autonomous-runs", safeRunId, "factory-run-ref.json"),
308
+ oracleReviewPath: artifactRef("reports", "autonomous-runs", safeRunId, "oracle-review.json"),
309
+ promotionPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "promotion-plan.json"),
310
+ promotionProofPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "promotion-proof-plan.json"),
311
+ schedulerPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "scheduler-plan.json"),
312
+ schedulerProofPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "scheduler-proof-plan.json"),
313
+ missionControlPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "mission-control-plan.json"),
314
+ missionControlProofPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "mission-control-proof-plan.json"),
315
+ sandboxApplyPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "sandbox-apply-plan.json"),
316
+ strictBudgetProofPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "strict-budget-proof-plan.json"),
317
+ modelRoutingProofPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "model-routing-proof-plan.json"),
318
+ currentSourceFingerprintPath: artifactRef("reports", "autonomous-runs", safeRunId, "current-source-fingerprint.json"),
319
+ finalE2EProofPlanPath: artifactRef("reports", "autonomous-runs", safeRunId, "final-e2e-proof-plan.json"),
320
+ finalNoShipOraclePath: artifactRef("reports", "autonomous-runs", safeRunId, "final-no-ship-oracle.json"),
321
+ completionGatePath: artifactRef("reports", "autonomous-runs", safeRunId, "completion-gate.json"),
322
+ validationPath: artifactRef("reports", "autonomous-runs", safeRunId, "validation.json"),
323
+ finalReportPath: artifactRef("reports", "autonomous-runs", safeRunId, "final-report.md"),
324
+ smokeSentinelPath: structuralOraclePassed ? artifactRef("reports", "autonomous-runs", safeRunId, "SMOKE_AUTONOMY_PASSED.sentinel") : undefined,
324
325
  };
325
326
  }