zob-harness 0.2.0 → 0.3.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 (214) hide show
  1. package/.pi/capabilities/zob-public-runtime-capabilities.json +4 -4
  2. package/.pi/extensions/zob-child-safety/AGENTS.md +12 -0
  3. package/.pi/extensions/zob-child-safety/index.ts +4 -105
  4. package/.pi/extensions/zob-child-safety/src/AGENTS.md +10 -0
  5. package/.pi/extensions/zob-child-safety/src/policy.ts +106 -0
  6. package/.pi/extensions/zob-harness/AGENTS.md +2 -0
  7. package/.pi/extensions/zob-harness/index.ts +94 -94
  8. package/.pi/extensions/zob-harness/src/AGENTS.md +4 -0
  9. package/.pi/extensions/zob-harness/src/core/AGENTS.md +24 -0
  10. package/.pi/extensions/zob-harness/src/{constants.ts → core/constants.ts} +10 -1
  11. package/.pi/extensions/zob-harness/src/core/utils/AGENTS.md +23 -0
  12. package/.pi/extensions/zob-harness/src/{utils → core/utils}/formatting.ts +1 -1
  13. package/.pi/extensions/zob-harness/src/{utils → core/utils}/records.ts +1 -1
  14. package/.pi/extensions/zob-harness/src/{utils → core/utils}/resources.ts +1 -1
  15. package/.pi/extensions/zob-harness/src/domains/AGENTS.md +23 -0
  16. package/.pi/extensions/zob-harness/src/domains/autonomy/AGENTS.md +21 -0
  17. package/.pi/extensions/zob-harness/src/{autonomous-runtime.ts → domains/autonomy/autonomous-runtime.ts} +22 -22
  18. package/.pi/extensions/zob-harness/src/{autonomy-readiness.ts → domains/autonomy/autonomy-readiness.ts} +18 -18
  19. package/.pi/extensions/zob-harness/src/{daemon-policy.ts → domains/autonomy/daemon-policy.ts} +6 -6
  20. package/.pi/extensions/zob-harness/src/{daemon-readiness.ts → domains/autonomy/daemon-readiness.ts} +7 -7
  21. package/.pi/extensions/zob-harness/src/{daemon-runtime.ts → domains/autonomy/daemon-runtime.ts} +2 -2
  22. package/.pi/extensions/zob-harness/src/{full-autonomy-test.ts → domains/autonomy/full-autonomy-test.ts} +4 -4
  23. package/.pi/extensions/zob-harness/src/{interactive-autonomy.ts → domains/autonomy/interactive-autonomy.ts} +2 -2
  24. package/.pi/extensions/zob-harness/src/{compute-profile.ts → domains/compute/compute-profile.ts} +3 -3
  25. package/.pi/extensions/zob-harness/src/{compute-workflow-shape.ts → domains/compute/compute-workflow-shape.ts} +3 -3
  26. package/.pi/extensions/zob-harness/src/domains/coms/AGENTS.md +21 -0
  27. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/envelope.ts +2 -2
  28. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/identity.ts +3 -3
  29. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/ledger-bridge.ts +2 -2
  30. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/local-transport.ts +1 -1
  31. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/policy.ts +3 -3
  32. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/presence.ts +1 -1
  33. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/registry.ts +3 -3
  34. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/response-capture.ts +1 -1
  35. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/transcript-capture.ts +2 -2
  36. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/zpeer-profile.ts +3 -3
  37. package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/zpeer.ts +3 -3
  38. package/.pi/extensions/zob-harness/src/{mission-control.ts → domains/coms/mission-control.ts} +8 -8
  39. package/.pi/extensions/zob-harness/src/{zagents.ts → domains/coms/zagents.ts} +86 -4
  40. package/.pi/extensions/zob-harness/src/domains/context/AGENTS.md +20 -0
  41. package/.pi/extensions/zob-harness/src/{context-gbrain.ts → domains/context/context-gbrain.ts} +4 -4
  42. package/.pi/extensions/zob-harness/src/domains/delegation/AGENTS.md +21 -0
  43. package/.pi/extensions/zob-harness/src/{agents.ts → domains/delegation/agents.ts} +2 -2
  44. package/.pi/extensions/zob-harness/src/{capabilities.ts → domains/delegation/capabilities.ts} +6 -6
  45. package/.pi/extensions/zob-harness/src/{child-runner.ts → domains/delegation/child-runner.ts} +8 -8
  46. package/.pi/extensions/zob-harness/src/{output-contracts.ts → domains/delegation/output-contracts.ts} +1 -1
  47. package/.pi/extensions/zob-harness/src/{prompt-packs.ts → domains/delegation/prompt-packs.ts} +4 -4
  48. package/.pi/extensions/zob-harness/src/domains/factory/AGENTS.md +21 -0
  49. package/.pi/extensions/zob-harness/src/{factory → domains/factory}/agentic-plan.ts +1 -1
  50. package/.pi/extensions/zob-harness/src/{factory-selector.ts → domains/factory/factory-selector.ts} +4 -4
  51. package/.pi/extensions/zob-harness/src/{factory → domains/factory}/quarantine.ts +5 -5
  52. package/.pi/extensions/zob-harness/src/{factory → domains/factory}/run.ts +5 -5
  53. package/.pi/extensions/zob-harness/src/{factory → domains/factory}/validation.ts +10 -10
  54. package/.pi/extensions/zob-harness/src/domains/git/AGENTS.md +20 -0
  55. package/.pi/extensions/zob-harness/src/{git-ops.ts → domains/git/git-ops.ts} +3 -3
  56. package/.pi/extensions/zob-harness/src/domains/goal/AGENTS.md +22 -0
  57. package/.pi/extensions/zob-harness/src/{goal-room.ts → domains/goal/goal-room.ts} +7 -7
  58. package/.pi/extensions/zob-harness/src/{goal-todo-imports.ts → domains/goal/goal-todo-imports.ts} +1 -1
  59. package/.pi/extensions/zob-harness/src/{goal-todo-types.ts → domains/goal/goal-todo-types.ts} +1 -1
  60. package/.pi/extensions/zob-harness/src/{goal-todos.ts → domains/goal/goal-todos.ts} +4 -4
  61. package/.pi/extensions/zob-harness/src/{goal.ts → domains/goal/goal.ts} +1 -1
  62. package/.pi/extensions/zob-harness/src/domains/governance/AGENTS.md +21 -0
  63. package/.pi/extensions/zob-harness/src/{budget-policy.ts → domains/governance/budget-policy.ts} +6 -6
  64. package/.pi/extensions/zob-harness/src/{governed-requests.ts → domains/governance/governed-requests.ts} +7 -7
  65. package/.pi/extensions/zob-harness/src/{launch-apply.ts → domains/governance/launch-apply.ts} +4 -4
  66. package/.pi/extensions/zob-harness/src/{merge-queue.ts → domains/governance/merge-queue.ts} +6 -6
  67. package/.pi/extensions/zob-harness/src/{rules.ts → domains/governance/rules.ts} +7 -7
  68. package/.pi/extensions/zob-harness/src/{safety.ts → domains/governance/safety.ts} +3 -3
  69. package/.pi/extensions/zob-harness/src/{sandbox.ts → domains/governance/sandbox.ts} +5 -5
  70. package/.pi/extensions/zob-harness/src/{worker-pool.ts → domains/governance/worker-pool.ts} +7 -7
  71. package/.pi/extensions/zob-harness/src/{workspace-claims.ts → domains/governance/workspace-claims.ts} +6 -6
  72. package/.pi/extensions/zob-harness/src/domains/models/AGENTS.md +20 -0
  73. package/.pi/extensions/zob-harness/src/{model-availability.ts → domains/models/model-availability.ts} +1 -1
  74. package/.pi/extensions/zob-harness/src/{model-routing.ts → domains/models/model-routing.ts} +6 -6
  75. package/.pi/extensions/zob-harness/src/domains/orchestration/AGENTS.md +21 -0
  76. package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/adaptive-delegation.ts +8 -8
  77. package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/adaptive-workflow.ts +4 -4
  78. package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/lead-plan.ts +5 -5
  79. package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/plan.ts +5 -5
  80. package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/room.ts +4 -4
  81. package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/run.ts +6 -6
  82. package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/supervised-readonly.ts +6 -6
  83. package/.pi/extensions/zob-harness/src/{orchestration → domains/orchestration}/widget-readers.ts +2 -2
  84. package/.pi/extensions/zob-harness/src/domains/project-dna/AGENTS.md +19 -0
  85. package/.pi/extensions/zob-harness/src/{project-dna.ts → domains/project-dna/project-dna.ts} +4 -4
  86. package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/candidate.ts +5 -5
  87. package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/coms.ts +3 -3
  88. package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/documentation.ts +4 -4
  89. package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/factory.ts +2 -2
  90. package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/temp-agent.ts +4 -4
  91. package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/write-lane.ts +3 -3
  92. package/.pi/extensions/zob-harness/src/domains/telemetry/AGENTS.md +19 -0
  93. package/.pi/extensions/zob-harness/src/{chronicle.ts → domains/telemetry/chronicle.ts} +3 -3
  94. package/.pi/extensions/zob-harness/src/{queue.ts → domains/telemetry/queue.ts} +7 -7
  95. package/.pi/extensions/zob-harness/src/{telemetry.ts → domains/telemetry/telemetry.ts} +4 -4
  96. package/.pi/extensions/zob-harness/src/{topology → domains/topology}/chains.ts +10 -10
  97. package/.pi/extensions/zob-harness/src/{topology → domains/topology}/coms.ts +3 -3
  98. package/.pi/extensions/zob-harness/src/{topology → domains/topology}/orchestration-profiles.ts +8 -8
  99. package/.pi/extensions/zob-harness/src/{topology → domains/topology}/teams.ts +8 -8
  100. package/.pi/extensions/zob-harness/src/runtime/adaptive-zmode.ts +2 -2
  101. package/.pi/extensions/zob-harness/src/runtime/auto-compaction.ts +2 -2
  102. package/.pi/extensions/zob-harness/src/runtime/commands.ts +49 -27
  103. package/.pi/extensions/zob-harness/src/runtime/compaction-policy.ts +2 -2
  104. package/.pi/extensions/zob-harness/src/runtime/delegation-feed.ts +1 -1
  105. package/.pi/extensions/zob-harness/src/runtime/delegation-monitor.ts +1 -1
  106. package/.pi/extensions/zob-harness/src/runtime/events.ts +52 -37
  107. package/.pi/extensions/zob-harness/src/{goal-runtime.ts → runtime/goal-runtime.ts} +9 -9
  108. package/.pi/extensions/zob-harness/src/runtime/goal-todo-overlay.ts +1 -1
  109. package/.pi/extensions/zob-harness/src/runtime/plan-capture.ts +2 -2
  110. package/.pi/extensions/zob-harness/src/runtime/state.ts +15 -13
  111. package/.pi/extensions/zob-harness/src/runtime/tools-autonomous.ts +2 -2
  112. package/.pi/extensions/zob-harness/src/runtime/tools-compute.ts +3 -3
  113. package/.pi/extensions/zob-harness/src/runtime/tools-coms.ts +15 -12
  114. package/.pi/extensions/zob-harness/src/runtime/tools-context.ts +2 -2
  115. package/.pi/extensions/zob-harness/src/runtime/tools-delegation.ts +13 -13
  116. package/.pi/extensions/zob-harness/src/runtime/tools-factory.ts +19 -19
  117. package/.pi/extensions/zob-harness/src/runtime/tools-goal-room.ts +3 -3
  118. package/.pi/extensions/zob-harness/src/runtime/tools-governed-requests.ts +3 -3
  119. package/.pi/extensions/zob-harness/src/runtime/tools-merge-queue.ts +3 -3
  120. package/.pi/extensions/zob-harness/src/runtime/tools-mission-control.ts +3 -3
  121. package/.pi/extensions/zob-harness/src/runtime/tools-orchestration.ts +9 -9
  122. package/.pi/extensions/zob-harness/src/runtime/tools-project-dna.ts +2 -2
  123. package/.pi/extensions/zob-harness/src/runtime/tools-worker-pool.ts +3 -3
  124. package/.pi/extensions/zob-harness/src/runtime/tools-workspace-claims.ts +3 -3
  125. package/.pi/extensions/zob-harness/src/runtime/tools-zcommit.ts +3 -3
  126. package/.pi/extensions/zob-harness/src/runtime/widget.ts +25 -8
  127. package/.pi/extensions/zob-harness/src/runtime/zobHarness.ts +1 -1
  128. package/.pi/extensions/zob-harness/src/types.ts +2 -2
  129. package/.pi/extensions/zob-switch/AGENTS.md +9 -0
  130. package/.pi/extensions/zob-switch/index.ts +9 -121
  131. package/.pi/extensions/zob-switch/src/AGENTS.md +8 -0
  132. package/.pi/extensions/zob-switch/src/autocomplete.ts +12 -0
  133. package/.pi/extensions/zob-switch/src/paths.ts +8 -0
  134. package/.pi/extensions/zob-switch/src/settings.ts +25 -0
  135. package/.pi/extensions/zob-switch/src/snapshot.ts +34 -0
  136. package/.pi/extensions/zob-switch/src/state.ts +57 -0
  137. package/.pi/factories/agentic-spec-team/README.md +35 -0
  138. package/.pi/factories/agentic-spec-team/batch-manifest.json +11 -0
  139. package/.pi/factories/agentic-spec-team/example-agentic-spec-manifest.json +19 -0
  140. package/.pi/factories/agentic-spec-team/factory.json +98 -0
  141. package/.pi/factories/agentic-spec-team/pilot-manifest.json +11 -0
  142. package/.pi/factories/agentic-spec-team/schemas/final-report.schema.json +15 -0
  143. package/.pi/factories/agentic-spec-team/schemas/manifest.schema.json +14 -0
  144. package/.pi/factories/agentic-spec-team/schemas/question.schema.json +18 -0
  145. package/.pi/factories/agentic-spec-team/schemas/source-register.schema.json +11 -0
  146. package/.pi/factories/agentic-spec-team/schemas/traceability.schema.json +11 -0
  147. package/.pi/factories/agentic-spec-team/smoke-manifest.json +11 -0
  148. package/.pi/skills/zob-agentic-spec-team/SKILL.md +145 -0
  149. package/.pi/skills/zob-split-refactor/SKILL.md +1 -1
  150. package/.pi/skills/zob-zagent-creator/SKILL.md +256 -12
  151. package/.pi/zagents/bdd-writer.json +20 -0
  152. package/.pi/zagents/data-profile-analyst.json +20 -0
  153. package/.pi/zagents/domain-modeler.json +20 -0
  154. package/.pi/zagents/planner-handoff-writer.json +20 -0
  155. package/.pi/zagents/prompts/agentic-spec-run-role.md +30 -0
  156. package/.pi/zagents/source-intake-steward.json +20 -0
  157. package/.pi/zagents/spec-chief.json +21 -0
  158. package/.pi/zagents/spec-oracle.json +20 -0
  159. package/.pi/zagents/spec-writer.json +20 -0
  160. package/.pi/zagents/ux-flow-analyst.json +20 -0
  161. package/.pi/zteams/agentic-spec-run.json +42 -0
  162. package/.pi/zteams/agentic-spec-run.tmux.sh +134 -0
  163. package/SOURCE_INDEX.md +1 -1
  164. package/package.json +9 -1
  165. package/scripts/README.md +1 -1
  166. package/scripts/agentic-spec-team/validate-bdd.mjs +13 -0
  167. package/scripts/agentic-spec-team/validate-final-report.mjs +14 -0
  168. package/scripts/agentic-spec-team/validate-manifest.mjs +14 -0
  169. package/scripts/agentic-spec-team/validate-oracle-ready.mjs +13 -0
  170. package/scripts/agentic-spec-team/validate-question-loop.mjs +15 -0
  171. package/scripts/agentic-spec-team/validate-run.mjs +11 -0
  172. package/scripts/agentic-spec-team/validate-source-register.mjs +17 -0
  173. package/scripts/agentic-spec-team/validate-traceability.mjs +20 -0
  174. package/scripts/agentic-spec-team/validate-workgraph.mjs +13 -0
  175. package/scripts/autonomy/mission-readiness-secret-smoke.mjs +5 -5
  176. package/scripts/git-ops/commit-policy-smoke.mjs +5 -4
  177. package/scripts/goal-todo/child-goal-ref-smoke.mjs +2 -2
  178. package/scripts/path-policy/validate-smoke.mjs +3 -3
  179. package/scripts/project-dna/AGENTS.md +39 -0
  180. package/scripts/project-dna/{validate-scaffold.mjs → validation/validate-scaffold.mjs} +7 -7
  181. package/scripts/spec-run.mjs +365 -0
  182. package/scripts/worker-pool/static-smoke.mjs +5 -5
  183. package/scripts/zagent-static-smoke.mjs +35 -6
  184. package/scripts/zpeer-local-e2e-smoke.mjs +6 -5
  185. package/scripts/zpeer-static-smoke.mjs +17 -17
  186. /package/.pi/extensions/zob-harness/src/{types → core/types}/core.ts +0 -0
  187. /package/.pi/extensions/zob-harness/src/{utils → core/utils}/hashing.ts +0 -0
  188. /package/.pi/extensions/zob-harness/src/{utils → core/utils}/json.ts +0 -0
  189. /package/.pi/extensions/zob-harness/src/{utils → core/utils}/paths.ts +0 -0
  190. /package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/AGENTS.md +0 -0
  191. /package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/pending-replies.ts +0 -0
  192. /package/.pi/extensions/zob-harness/src/{coms-v2 → domains/coms/coms-v2}/types.ts +0 -0
  193. /package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/ledger.ts +0 -0
  194. /package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/types.ts +0 -0
  195. /package/.pi/extensions/zob-harness/src/{promotion → domains/promotion}/validate.ts +0 -0
  196. /package/.pi/extensions/zob-harness/src/{schemas-project-dna.ts → runtime/schemas-project-dna.ts} +0 -0
  197. /package/.pi/extensions/zob-harness/src/{schemas.ts → runtime/schemas.ts} +0 -0
  198. /package/scripts/project-dna/{bench-smoke.mjs → benchmark/bench-smoke.mjs} +0 -0
  199. /package/scripts/project-dna/{build-capsules.mjs → capsules/build-capsules.mjs} +0 -0
  200. /package/scripts/project-dna/{emit-golden-cases.mjs → emit/emit-golden-cases.mjs} +0 -0
  201. /package/scripts/project-dna/{emit-ontology.mjs → emit/emit-ontology.mjs} +0 -0
  202. /package/scripts/project-dna/{oracle-review-smoke.mjs → oracle/oracle-review-smoke.mjs} +0 -0
  203. /package/scripts/project-dna/{query-context.mjs → query/query-context.mjs} +0 -0
  204. /package/scripts/project-dna/{query-steward.mjs → query/query-steward.mjs} +0 -0
  205. /package/scripts/project-dna/{build-sample-spec.mjs → sample/build-sample-spec.mjs} +0 -0
  206. /package/scripts/project-dna/{generate-sample.mjs → sample/generate-sample.mjs} +0 -0
  207. /package/scripts/project-dna/{validate-sample-project.mjs → sample/validate-sample-project.mjs} +0 -0
  208. /package/scripts/project-dna/{scan.mjs → scan/scan.mjs} +0 -0
  209. /package/scripts/project-dna/{validate-scan-artifacts.mjs → scan/validate-scan-artifacts.mjs} +0 -0
  210. /package/scripts/project-dna/{validate-5of5.mjs → validation/validate-5of5.mjs} +0 -0
  211. /package/scripts/project-dna/{validate-golden-cases.mjs → validation/validate-golden-cases.mjs} +0 -0
  212. /package/scripts/project-dna/{validate-ontology.mjs → validation/validate-ontology.mjs} +0 -0
  213. /package/scripts/project-dna/{plan-workflow.mjs → workflow/plan-workflow.mjs} +0 -0
  214. /package/scripts/project-dna/{validate-workflow.mjs → workflow/validate-workflow.mjs} +0 -0
@@ -103,7 +103,7 @@ const requiredFiles = [
103
103
  "scripts/project-dna/validate-golden-cases.mjs",
104
104
  "scripts/project-dna/query-steward.mjs",
105
105
  "scripts/project-dna/validate-5of5.mjs",
106
- ".pi/extensions/zob-harness/src/project-dna.ts",
106
+ ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts",
107
107
  ".pi/extensions/zob-harness/src/runtime/tools-project-dna.ts",
108
108
  "scripts/project-dna/bench-smoke.mjs",
109
109
  "scripts/project-dna/oracle-review-smoke.mjs",
@@ -331,12 +331,12 @@ assertIncludes(queryScript, "bounded_context_only", "scripts/project-dna/query-c
331
331
  assertIncludes(queryScript, "agent_loads_entire_project: false", "scripts/project-dna/query-context.mjs");
332
332
  assertIncludes(queryScript, "knowledge_backend_write_enabled: false", "scripts/project-dna/query-context.mjs");
333
333
 
334
- const runtimeProjectDna = requireFile(".pi/extensions/zob-harness/src/project-dna.ts");
335
- assertIncludes(runtimeProjectDna, "zob.project-dna-agentic-plan.v1", ".pi/extensions/zob-harness/src/project-dna.ts");
336
- assertIncludes(runtimeProjectDna, "zob.project-dna-query-result.v1", ".pi/extensions/zob-harness/src/project-dna.ts");
337
- assertIncludes(runtimeProjectDna, "zob.project-dna-federated-query-result.v1", ".pi/extensions/zob-harness/src/project-dna.ts");
338
- assertIncludes(runtimeProjectDna, "knowledge_backend_write_enabled: false", ".pi/extensions/zob-harness/src/project-dna.ts");
339
- assertIncludes(runtimeProjectDna, "durable_promotion_allowed: false", ".pi/extensions/zob-harness/src/project-dna.ts");
334
+ const runtimeProjectDna = requireFile(".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
335
+ assertIncludes(runtimeProjectDna, "zob.project-dna-agentic-plan.v1", ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
336
+ assertIncludes(runtimeProjectDna, "zob.project-dna-query-result.v1", ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
337
+ assertIncludes(runtimeProjectDna, "zob.project-dna-federated-query-result.v1", ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
338
+ assertIncludes(runtimeProjectDna, "knowledge_backend_write_enabled: false", ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
339
+ assertIncludes(runtimeProjectDna, "durable_promotion_allowed: false", ".pi/extensions/zob-harness/src/domains/project-dna/project-dna.ts");
340
340
 
341
341
  const runtimeProjectDnaTools = requireFile(".pi/extensions/zob-harness/src/runtime/tools-project-dna.ts");
342
342
  assertIncludes(runtimeProjectDnaTools, "zob_project_dna_plan_workflow", ".pi/extensions/zob-harness/src/runtime/tools-project-dna.ts");
@@ -0,0 +1,365 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs/promises";
3
+ import { existsSync, statSync } from "node:fs";
4
+ import path from "node:path";
5
+ import { spawnSync } from "node:child_process";
6
+
7
+ const RUNS_ROOT = "reports/agentic-spec-runs";
8
+ const TEAM_SCRIPT = ".pi/zteams/agentic-spec-run.tmux.sh";
9
+ const DEFAULT_AGENT = "spec-chief";
10
+ const args = process.argv.slice(2);
11
+ const command = args[0] && !args[0].startsWith("--") ? args[0] : "help";
12
+
13
+ try {
14
+ const result = await dispatch(command, command === "help" ? args : args.slice(1));
15
+ if (result) print(result);
16
+ if (result?.no_ship) process.exitCode = 1;
17
+ } catch (error) {
18
+ print({ schema: "agentic-spec-run.error.v1", status: "error", no_ship: true, message: error?.message || String(error) });
19
+ process.exitCode = 1;
20
+ }
21
+
22
+ async function dispatch(cmd, values) {
23
+ if (cmd === "help" || values.includes("--help") || args.includes("--help")) return help();
24
+ if (cmd === "init") return initRun(parseOptions(values));
25
+ if (cmd === "auto-pilot") return autoPilot(parseOptions(values));
26
+ if (cmd === "send-kickoff") return sendKickoff(values[0], parseOptions(values.slice(1)));
27
+ if (cmd === "team-start") return teamStart(values[0]);
28
+ if (cmd === "team-status") return teamStatus(parseRunOrSession(values));
29
+ if (cmd === "team-attach") return teamAttach(values[0], values[1] || DEFAULT_AGENT);
30
+ if (cmd === "team-close") return teamClose(parseRunOrSession(values));
31
+ if (cmd === "wait") return waitForCompletion(values[0], parseOptions(values.slice(1)));
32
+ if (cmd === "validate") return validateRun(values[0]);
33
+ if (cmd === "questions") return listQuestions(values[0], parseOptions(values.slice(1)));
34
+ if (cmd === "answer") return answerQuestion(values[0], values[1], parseOptions(values.slice(2)));
35
+ if (cmd === "resume") return resumeRun(values[0]);
36
+ if (cmd === "status") return readRunStatus(values[0]);
37
+ return { ...help(), status: "blocked", no_ship: true, message: `unknown command: ${cmd}` };
38
+ }
39
+
40
+ function help() {
41
+ return {
42
+ schema: "agentic-spec-run.help.v1",
43
+ usage: [
44
+ "node scripts/spec-run.mjs init --mission <text>|--mission-file <path> --source <path> [--source <path>] [--name name] [--run-id id] [--owner owner] [--prepare-only]",
45
+ "node scripts/spec-run.mjs auto-pilot --mission <text>|--mission-file <path> --source <path> [--timeout-ms 14400000] [--poll-ms 30000] [--no-submit] [--no-wait] [--no-close]",
46
+ "node scripts/spec-run.mjs send-kickoff reports/agentic-spec-runs/<run_id> --session agentic-spec-run-<run_id> --agent spec-chief --submit",
47
+ "node scripts/spec-run.mjs answer <run_id> Q-001 --text '<answer>' --answered-by owner",
48
+ "node scripts/spec-run.mjs validate <run_id>",
49
+ ],
50
+ output: "json",
51
+ v1_posture: "skill + factory + ZTeam + CLI; no runtime extension",
52
+ no_ship: false,
53
+ };
54
+ }
55
+
56
+ async function initRun(opts) {
57
+ const sources = opts.source ?? [];
58
+ const mission = await resolveMission(opts);
59
+ if (!mission) return blocked("init", "missing mission; use --mission or --mission-file");
60
+ if (!sources.length) return blocked("init", "missing at least one --source path");
61
+
62
+ const runId = safeRunId(opts.runId || `${opts.name || "spec"}-${timestamp()}`);
63
+ const runDir = path.join(RUNS_ROOT, runId);
64
+ const createdAt = new Date().toISOString();
65
+ await mkdirs(runDir, ["analysis", "spec", "validation", "handoff", "oracle", "checkpoints"]);
66
+
67
+ const sourceRows = sources.map((source, index) => inspectSource(source, index));
68
+ const manifest = {
69
+ schema: "agentic-spec-run.manifest.v1",
70
+ run_id: runId,
71
+ name: opts.name || runId,
72
+ owner: opts.owner || "owner",
73
+ created_at: createdAt,
74
+ mission,
75
+ mission_file: opts.missionFile || null,
76
+ source_count: sourceRows.length,
77
+ source_refs: sourceRows.map((row) => row.source_id),
78
+ run_dir: runDir,
79
+ team_id: "agentic-spec-run",
80
+ entry_agent: DEFAULT_AGENT,
81
+ expected_session: sessionName(runId),
82
+ policies: {
83
+ source_policy: "citation_only_by_default",
84
+ raw_secret_storage: false,
85
+ human_questions_block_completion: true,
86
+ final_oracle_required: true,
87
+ traceability_required: true,
88
+ runtime_extension_v1: false,
89
+ },
90
+ };
91
+ const teamPlan = {
92
+ schema: "agentic-spec.team-plan.v1",
93
+ run_id: runId,
94
+ session: sessionName(runId),
95
+ entry_agent: DEFAULT_AGENT,
96
+ agents: ["spec-chief", "source-intake-steward", "data-profile-analyst", "domain-modeler", "ux-flow-analyst", "spec-writer", "bdd-writer", "planner-handoff-writer", "spec-oracle"],
97
+ rooms: ["spec-control", "intake", "data", "domain", "ux", "writing", "validation", "handoff", "oracle"],
98
+ };
99
+ const status = {
100
+ schema: "agentic-spec-run.status.v1",
101
+ run_id: runId,
102
+ status: "ready",
103
+ phase: "init",
104
+ no_ship: false,
105
+ run_dir: runDir,
106
+ open_blocking_questions: 0,
107
+ final_oracle: "pending",
108
+ updated_at: createdAt,
109
+ };
110
+
111
+ await writeJson(path.join(runDir, "run-manifest.json"), manifest);
112
+ await writeJson(path.join(runDir, "source-register.json"), { schema: "agentic-spec.source-register.v1", run_id: runId, sources: sourceRows });
113
+ await writeJson(path.join(runDir, "team-plan.json"), teamPlan);
114
+ await writeJson(path.join(runDir, "status.json"), status);
115
+ await fs.writeFile(path.join(runDir, "source-register.md"), renderSourceRegister(sourceRows), "utf8");
116
+ await fs.writeFile(path.join(runDir, "chief-kickoff.md"), renderKickoff(manifest, sourceRows), "utf8");
117
+ await fs.writeFile(path.join(runDir, "questions.md"), "# Open Questions\n\nNo questions recorded yet.\n", "utf8");
118
+ await fs.writeFile(path.join(runDir, "answers.md"), "# Answers\n\nNo answers recorded yet.\n", "utf8");
119
+ await fs.writeFile(path.join(runDir, "questions.jsonl"), "", "utf8");
120
+ await fs.writeFile(path.join(runDir, "answers.jsonl"), "", "utf8");
121
+ await fs.writeFile(path.join(runDir, "assumptions.md"), "# Assumptions\n\n", "utf8");
122
+ await fs.writeFile(path.join(runDir, "validation/traceability-matrix.md"), "# Traceability Matrix\n\n| Source | Fact / answer / assumption | Requirement | Acceptance criteria | Task | Oracle check |\n| --- | --- | --- | --- | --- | --- |\n", "utf8");
123
+ await writeJson(path.join(runDir, "validation/traceability-matrix.json"), { schema: "agentic-spec.traceability.v1", run_id: runId, rows: [] });
124
+
125
+ return { schema: "agentic-spec-run.init-result.v1", status: "ready", no_ship: false, run_id: runId, run_dir: runDir, prepare_only: opts.prepareOnly !== false, full_team_launched: false, expected_session: sessionName(runId) };
126
+ }
127
+
128
+ async function autoPilot(opts) {
129
+ const timeoutMs = Number(opts.timeoutMs || 4 * 60 * 60 * 1000);
130
+ const pollMs = Number(opts.pollMs || 30 * 1000);
131
+ const submit = opts.submit !== false;
132
+ const wait = opts.wait !== false;
133
+ const close = opts.close !== false;
134
+ const init = await initRun({ ...opts, prepareOnly: true });
135
+ if (init.no_ship) return init;
136
+ const sessionGuard = validateSessionOverride(opts.session, sessionName(init.run_id));
137
+ if (sessionGuard.no_ship) return { schema: "agentic-spec-run.auto-pilot-result.v1", status: "blocked", no_ship: true, phase: "session-guard", init, session_guard: sessionGuard };
138
+ const team_start = teamStart(init.run_id);
139
+ if (team_start.no_ship) return { schema: "agentic-spec-run.auto-pilot-result.v1", status: "blocked", no_ship: true, phase: "team-start", init, team_start };
140
+ const kickoff = await sendKickoff(init.run_dir, { session: sessionGuard.session, agent: opts.agent || DEFAULT_AGENT, submit });
141
+ if (kickoff.no_ship) return { schema: "agentic-spec-run.auto-pilot-result.v1", status: "blocked", no_ship: true, phase: "send-kickoff", init, team_start, kickoff };
142
+ if (!wait) return { schema: "agentic-spec-run.auto-pilot-result.v1", status: "launched", no_ship: false, run_id: init.run_id, run_dir: init.run_dir, run_session: sessionGuard.session, waited: false, closed: false, next_command: `npm run spec-run -- team-status --session ${sessionGuard.session}` };
143
+ const completion = await waitForCompletion(init.run_id, { timeoutMs, pollMs });
144
+ if (completion.status !== "pass") return { schema: "agentic-spec-run.auto-pilot-result.v1", status: completion.status, no_ship: true, run_id: init.run_id, run_dir: init.run_dir, run_session: sessionGuard.session, completion, closed: false, close_skipped_reason: "completion_not_pass_no_ship_false" };
145
+ let closeResult = { status: "skipped", closed: false, reason: "--no-close" };
146
+ if (close) closeResult = teamClose({ runId: init.run_id, confirm: true, session: sessionGuard.session });
147
+ return { schema: "agentic-spec-run.auto-pilot-result.v1", status: "pass", no_ship: false, run_id: init.run_id, run_dir: init.run_dir, run_session: sessionGuard.session, completion, close: closeResult, closed: closeResult.closed === true };
148
+ }
149
+
150
+ async function sendKickoff(runDirOrId, opts) {
151
+ const runDir = resolveRunDir(runDirOrId);
152
+ const manifest = await readJson(path.join(runDir, "run-manifest.json"));
153
+ const kickoffPath = path.join(runDir, "chief-kickoff.md");
154
+ const session = opts.session || sessionName(manifest.run_id);
155
+ const guard = validateSessionOverride(session, sessionName(manifest.run_id));
156
+ if (guard.no_ship) return { schema: "agentic-spec-run.kickoff-result.v1", status: "blocked", no_ship: true, session_guard: guard };
157
+ const agent = opts.agent || DEFAULT_AGENT;
158
+ if (!opts.submit) return { schema: "agentic-spec-run.kickoff-result.v1", status: "pass", no_ship: false, submitted: false, run_id: manifest.run_id, run_dir: runDir, kickoff_ref: kickoffPath, session, agent };
159
+ const target = `${session}:${agent}`;
160
+ const body = await fs.readFile(kickoffPath, "utf8");
161
+ const payload = `Please execute this Agentic Spec kickoff. Read ${kickoffPath} and coordinate the run.\n\n${body}`;
162
+ const sent = spawnSync("tmux", ["send-keys", "-t", target, payload, "C-m"], { encoding: "utf8" });
163
+ if (sent.status !== 0) return { schema: "agentic-spec-run.kickoff-result.v1", status: "blocked", no_ship: true, submitted: false, reason: "tmux_send_failed", stderr: sent.stderr?.trim(), target };
164
+ return { schema: "agentic-spec-run.kickoff-result.v1", status: "pass", no_ship: false, submitted: true, run_id: manifest.run_id, run_dir: runDir, kickoff_ref: kickoffPath, session, agent };
165
+ }
166
+
167
+ function teamStart(runId) {
168
+ if (!runId) return blocked("team-start", "missing run_id");
169
+ return runTeamScript(["start-detached", runId], "agentic-spec-run.team-start-result.v1");
170
+ }
171
+
172
+ function teamStatus(spec) {
173
+ const session = spec.session || (spec.runId ? sessionName(spec.runId) : null);
174
+ if (!session) return blocked("team-status", "missing --session or run_id");
175
+ const runId = spec.runId || session.replace(/^agentic-spec-run-/u, "");
176
+ return runTeamScript(["status", runId], "agentic-spec-run.team-status-result.v1", { session });
177
+ }
178
+
179
+ function teamAttach(runId, agent) {
180
+ if (!runId) return blocked("team-attach", "missing run_id");
181
+ return runTeamScript(["attach", runId, agent || DEFAULT_AGENT], "agentic-spec-run.team-attach-result.v1");
182
+ }
183
+
184
+ function teamClose(spec) {
185
+ const session = spec.session || (spec.runId ? sessionName(spec.runId) : null);
186
+ const runId = spec.runId || session?.replace(/^agentic-spec-run-/u, "");
187
+ if (!runId || !session) return blocked("team-close", "missing --session or run_id");
188
+ const guard = validateSessionOverride(session, sessionName(runId));
189
+ if (guard.no_ship) return { schema: "agentic-spec-run.team-close-result.v1", status: "blocked", no_ship: true, closed: false, session_guard: guard };
190
+ if (!spec.confirm) return { schema: "agentic-spec-run.team-close-result.v1", status: "blocked", no_ship: true, closed: false, reason: "team-close requires --confirm" };
191
+ return runTeamScript(["close", runId], "agentic-spec-run.team-close-result.v1", { session, closed: true });
192
+ }
193
+
194
+ async function waitForCompletion(runId, opts) {
195
+ const runDir = resolveRunDir(runId);
196
+ const timeoutMs = Number(opts.timeoutMs || 4 * 60 * 60 * 1000);
197
+ const pollMs = Number(opts.pollMs || 30 * 1000);
198
+ const deadline = Date.now() + timeoutMs;
199
+ const checked = [];
200
+ while (Date.now() <= deadline) {
201
+ for (const file of [path.join(runDir, "final-report.json"), path.join(runDir, "status.json")]) {
202
+ const parsed = await readJsonIfExists(file);
203
+ if (!parsed) continue;
204
+ checked.push(file);
205
+ if (isPassingCompletion(parsed)) return { schema: "agentic-spec-run.wait-result.v1", status: "pass", no_ship: false, completion_ref: file, report: parsed };
206
+ if (isBlockingCompletion(parsed)) return { schema: "agentic-spec-run.wait-result.v1", status: "blocked", no_ship: true, completion_ref: file, report: parsed };
207
+ }
208
+ await sleep(pollMs);
209
+ }
210
+ return { schema: "agentic-spec-run.wait-result.v1", status: "timeout", no_ship: true, timeout_ms: timeoutMs, checked_refs: [...new Set(checked)] };
211
+ }
212
+
213
+ async function validateRun(runIdOrDir) {
214
+ const runDir = resolveRunDir(runIdOrDir);
215
+ const required = ["run-manifest.json", "source-register.json", "source-register.md", "team-plan.json", "chief-kickoff.md", "status.json", "questions.md", "answers.md", "validation/traceability-matrix.json", "validation/traceability-matrix.md"];
216
+ const missing = required.filter((file) => !existsSync(path.join(runDir, file)));
217
+ const errors = [...missing.map((file) => `missing ${file}`)];
218
+ const manifest = await readJsonIfExists(path.join(runDir, "run-manifest.json"));
219
+ const sources = await readJsonIfExists(path.join(runDir, "source-register.json"));
220
+ const traceability = await readJsonIfExists(path.join(runDir, "validation/traceability-matrix.json"));
221
+ if (manifest?.schema !== "agentic-spec-run.manifest.v1") errors.push("manifest schema mismatch");
222
+ if (!Array.isArray(sources?.sources) || sources.sources.length < 1) errors.push("source-register must include at least one source");
223
+ if (!Array.isArray(traceability?.rows)) errors.push("traceability rows must be an array");
224
+ const questions = await readJsonlIfExists(path.join(runDir, "questions.jsonl"));
225
+ const openBlocking = questions.filter((q) => q?.blocking === true && q?.status !== "answered" && q?.status !== "closed");
226
+ if (openBlocking.length > 0) errors.push(`open blocking questions: ${openBlocking.map((q) => q.question_id).join(", ")}`);
227
+ return { schema: "agentic-spec-run.validation-result.v1", status: errors.length ? "fail" : "pass", no_ship: errors.length > 0, run_dir: runDir, errors, checked_files: required };
228
+ }
229
+
230
+ async function listQuestions(runId, opts) {
231
+ const runDir = resolveRunDir(runId);
232
+ const questions = await readJsonlIfExists(path.join(runDir, "questions.jsonl"));
233
+ const rows = opts.openOnly ? questions.filter((q) => q.status === "open") : questions;
234
+ return { schema: "agentic-spec-run.questions-result.v1", status: "pass", no_ship: false, run_id: path.basename(runDir), questions: rows };
235
+ }
236
+
237
+ async function answerQuestion(runId, questionId, opts) {
238
+ if (!runId || !questionId) return blocked("answer", "usage: answer <run_id> <question_id> --text '<answer>'");
239
+ if (!opts.text) return blocked("answer", "missing --text answer");
240
+ const runDir = resolveRunDir(runId);
241
+ const answer = {
242
+ schema: "agentic-spec.answer.v1",
243
+ question_id: questionId,
244
+ answered_by: opts.answeredBy || "owner",
245
+ answer_summary: opts.text,
246
+ selected_option: opts.option || null,
247
+ raw_answer_stored: false,
248
+ answered_at: new Date().toISOString(),
249
+ };
250
+ await fs.appendFile(path.join(runDir, "answers.jsonl"), `${JSON.stringify(answer)}\n`, "utf8");
251
+ await fs.appendFile(path.join(runDir, "answers.md"), `\n## ${questionId}\n\nAnswered by: ${answer.answered_by}\n\n${answer.answer_summary}\n`, "utf8");
252
+ const statusPath = path.join(runDir, "status.json");
253
+ const status = await readJsonIfExists(statusPath) || {};
254
+ status.status = "answer_recorded";
255
+ status.phase = "human-clarification";
256
+ status.no_ship = true;
257
+ status.updated_at = new Date().toISOString();
258
+ status.next_command = `npm run spec-run -- resume ${path.basename(runDir)}`;
259
+ await writeJson(statusPath, status);
260
+ return { schema: "agentic-spec-run.answer-result.v1", status: "pass", no_ship: false, run_id: path.basename(runDir), answer_ref: path.join(runDir, "answers.md"), next_command: status.next_command };
261
+ }
262
+
263
+ async function resumeRun(runId) {
264
+ const runDir = resolveRunDir(runId);
265
+ const statusPath = path.join(runDir, "status.json");
266
+ const status = await readJsonIfExists(statusPath) || {};
267
+ status.status = "ready";
268
+ status.phase = "resume_after_human_answer";
269
+ status.no_ship = false;
270
+ status.updated_at = new Date().toISOString();
271
+ await writeJson(statusPath, status);
272
+ return { schema: "agentic-spec-run.resume-result.v1", status: "pass", no_ship: false, run_id: path.basename(runDir), status_ref: statusPath, next_step: `send kickoff or attach spec-chief in ${sessionName(path.basename(runDir))}` };
273
+ }
274
+
275
+ async function readRunStatus(runId) {
276
+ const runDir = resolveRunDir(runId);
277
+ return await readJson(path.join(runDir, "status.json"));
278
+ }
279
+
280
+ function runTeamScript(teamArgs, schema, extra = {}) {
281
+ if (!existsSync(TEAM_SCRIPT)) return { schema, status: "blocked", no_ship: true, reason: `missing ${TEAM_SCRIPT}` };
282
+ const result = spawnSync("bash", [TEAM_SCRIPT, ...teamArgs], { encoding: "utf8", cwd: process.cwd(), env: process.env });
283
+ if (result.status !== 0) return { schema, status: "blocked", no_ship: true, stdout: result.stdout?.trim(), stderr: result.stderr?.trim(), ...extra };
284
+ return { schema, status: "pass", no_ship: false, stdout: result.stdout?.trim(), ...extra };
285
+ }
286
+
287
+ function parseOptions(values) {
288
+ const opts = { source: [], submit: true, wait: true, close: true, prepareOnly: true };
289
+ for (let i = 0; i < values.length; i++) {
290
+ const arg = values[i];
291
+ if (arg === "--source") opts.source.push(values[++i]);
292
+ else if (arg === "--mission") opts.mission = values[++i];
293
+ else if (arg === "--mission-file") opts.missionFile = values[++i];
294
+ else if (arg === "--name") opts.name = values[++i];
295
+ else if (arg === "--run-id") opts.runId = values[++i];
296
+ else if (arg === "--owner") opts.owner = values[++i];
297
+ else if (arg === "--session") opts.session = values[++i];
298
+ else if (arg === "--agent") opts.agent = values[++i];
299
+ else if (arg === "--timeout-ms") opts.timeoutMs = values[++i];
300
+ else if (arg === "--poll-ms") opts.pollMs = values[++i];
301
+ else if (arg === "--answered-by") opts.answeredBy = values[++i];
302
+ else if (arg === "--text") opts.text = values[++i];
303
+ else if (arg === "--option") opts.option = values[++i];
304
+ else if (arg === "--prepare-only") opts.prepareOnly = true;
305
+ else if (arg === "--no-submit") opts.submit = false;
306
+ else if (arg === "--no-wait") opts.wait = false;
307
+ else if (arg === "--no-close") opts.close = false;
308
+ else if (arg === "--open-only") opts.openOnly = true;
309
+ else if (arg === "--confirm") opts.confirm = true;
310
+ }
311
+ return opts;
312
+ }
313
+
314
+ function parseRunOrSession(values) {
315
+ const opts = parseOptions(values);
316
+ const runId = values.find((value) => !value.startsWith("--") && ![opts.session].includes(value));
317
+ return { runId, session: opts.session, confirm: opts.confirm };
318
+ }
319
+
320
+ async function resolveMission(opts) {
321
+ if (opts.missionFile) return fs.readFile(opts.missionFile, "utf8");
322
+ return opts.mission || "";
323
+ }
324
+
325
+ function inspectSource(source, index) {
326
+ const exists = existsSync(source);
327
+ const stat = exists ? statSync(source) : null;
328
+ return {
329
+ source_id: `SRC-${String(index + 1).padStart(3, "0")}`,
330
+ path: source,
331
+ exists,
332
+ kind: stat?.isDirectory() ? "directory" : stat?.isFile() ? "file" : "missing",
333
+ size_bytes: stat?.isFile() ? stat.size : null,
334
+ policy: "citation_only",
335
+ sensitivity: "unknown_until_intake",
336
+ };
337
+ }
338
+
339
+ function renderSourceRegister(rows) {
340
+ return `# Source Register\n\n| Source | Path | Kind | Exists | Policy | Sensitivity |\n| --- | --- | --- | --- | --- | --- |\n${rows.map((row) => `| ${row.source_id} | ${row.path} | ${row.kind} | ${row.exists} | ${row.policy} | ${row.sensitivity} |`).join("\n")}\n`;
341
+ }
342
+
343
+ function renderKickoff(manifest, sources) {
344
+ return `# Agentic Spec Run Kickoff\n\nRun: ${manifest.run_id}\nSession: ${manifest.expected_session}\nEntry agent: ${manifest.entry_agent}\n\n## Mission\n\n${manifest.mission}\n\n## Sources\n\n${sources.map((row) => `- ${row.source_id}: ${row.path} (${row.kind}, policy=${row.policy})`).join("\n")}\n\n## Required outputs\n\n- source register and source quality report\n- data profile / domain model / UX flows as applicable\n- mission spec, requirements, BDD acceptance criteria\n- validation/traceability-matrix.md and .json\n- handoff/workgraph.md and implementation tasks\n- oracle/final-oracle-review.json and final-report.json\n\n## Rules\n\nSpec Chief is the only human interlocutor. Do not invent answers to blocking business questions. Completion requires oracle PASS and no_ship=false.\n`;
345
+ }
346
+
347
+ async function mkdirs(root, children) {
348
+ await fs.mkdir(root, { recursive: true });
349
+ for (const child of children) await fs.mkdir(path.join(root, child), { recursive: true });
350
+ }
351
+
352
+ function sessionName(runId) { return `agentic-spec-run-${safeRunId(runId)}`; }
353
+ function safeRunId(value) { return String(value || "").trim().replace(/[^A-Za-z0-9_-]+/gu, "-").replace(/^-+|-+$/gu, "").slice(0, 120) || "spec-run"; }
354
+ function timestamp() { return new Date().toISOString().replace(/[-:TZ.]/gu, "").slice(0, 14); }
355
+ function resolveRunDir(runIdOrDir) { return String(runIdOrDir || "").startsWith(RUNS_ROOT) ? runIdOrDir : path.join(RUNS_ROOT, safeRunId(runIdOrDir)); }
356
+ function validateSessionOverride(requestedSession, expectedSession) { const session = requestedSession || expectedSession; return session === expectedSession ? { status: "pass", no_ship: false, session, expected_session: expectedSession } : { status: "blocked", no_ship: true, session, expected_session: expectedSession, reason: "session_must_equal_isolated_agentic_spec_run_session" }; }
357
+ function isPassingCompletion(value) { return value?.no_ship === false && ["pass", "complete", "completed"].includes(String(value?.status || value?.verdict || "").toLowerCase()); }
358
+ function isBlockingCompletion(value) { return value?.no_ship === true || ["blocked", "fail", "failed", "needs_human"].includes(String(value?.status || value?.verdict || "").toLowerCase()); }
359
+ function blocked(phase, reason) { return { schema: "agentic-spec-run.blocked.v1", status: "blocked", no_ship: true, phase, reason }; }
360
+ async function readJson(file) { return JSON.parse(await fs.readFile(file, "utf8")); }
361
+ async function readJsonIfExists(file) { try { return await readJson(file); } catch { return null; } }
362
+ async function readJsonlIfExists(file) { try { const text = await fs.readFile(file, "utf8"); return text.split(/\n/u).filter(Boolean).map((line) => JSON.parse(line)); } catch { return []; } }
363
+ async function writeJson(file, value) { await fs.writeFile(file, `${JSON.stringify(value, null, 2)}\n`, "utf8"); }
364
+ function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); }
365
+ function print(value) { console.log(JSON.stringify(value, null, 2)); }
@@ -2,12 +2,12 @@
2
2
  import { readFileSync } from "node:fs";
3
3
 
4
4
  const files = {
5
- workerPool: ".pi/extensions/zob-harness/src/worker-pool.ts",
5
+ workerPool: ".pi/extensions/zob-harness/src/domains/governance/worker-pool.ts",
6
6
  runtime: ".pi/extensions/zob-harness/src/runtime/tools-worker-pool.ts",
7
- goalRoom: ".pi/extensions/zob-harness/src/goal-room.ts",
8
- constants: ".pi/extensions/zob-harness/src/constants.ts",
9
- schemas: ".pi/extensions/zob-harness/src/schemas.ts",
10
- governedRequests: ".pi/extensions/zob-harness/src/governed-requests.ts",
7
+ goalRoom: ".pi/extensions/zob-harness/src/domains/goal/goal-room.ts",
8
+ constants: ".pi/extensions/zob-harness/src/core/constants.ts",
9
+ schemas: ".pi/extensions/zob-harness/src/runtime/schemas.ts",
10
+ governedRequests: ".pi/extensions/zob-harness/src/domains/governance/governed-requests.ts",
11
11
  governedRuntime: ".pi/extensions/zob-harness/src/runtime/tools-governed-requests.ts",
12
12
  registry: ".pi/capabilities/zob-public-runtime-capabilities.json",
13
13
  };
@@ -2,12 +2,12 @@
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
3
 
4
4
  const files = [
5
- '.pi/extensions/zob-harness/src/zagents.ts',
5
+ '.pi/extensions/zob-harness/src/domains/coms/zagents.ts',
6
6
  '.pi/extensions/zob-harness/src/runtime/commands.ts',
7
7
  '.pi/extensions/zob-harness/src/runtime/events.ts',
8
8
  '.pi/extensions/zob-harness/src/runtime/state.ts',
9
9
  '.pi/extensions/zob-harness/src/runtime/widget.ts',
10
- '.pi/extensions/zob-harness/src/coms-v2/zpeer.ts',
10
+ '.pi/extensions/zob-harness/src/domains/coms/coms-v2/zpeer.ts',
11
11
  '.pi/capabilities/zob-public-runtime-capabilities.json',
12
12
  '.pi/skills/zob-zagent-creator/SKILL.md',
13
13
  ];
@@ -20,8 +20,8 @@ function requireIncludes(file, needles, label = file) {
20
20
  }
21
21
  }
22
22
 
23
- const zagents = contents['.pi/extensions/zob-harness/src/zagents.ts'];
24
- requireIncludes('.pi/extensions/zob-harness/src/zagents.ts', [
23
+ const zagents = contents['.pi/extensions/zob-harness/src/domains/coms/zagents.ts'];
24
+ requireIncludes('.pi/extensions/zob-harness/src/domains/coms/zagents.ts', [
25
25
  'const ZAGENTS_DIR = ".pi/zagents"',
26
26
  'const ZTEAMS_DIR = ".pi/zteams"',
27
27
  'const ZAGENT_PROMPTS_DIR = ".pi/zagents/prompts"',
@@ -32,7 +32,11 @@ requireIncludes('.pi/extensions/zob-harness/src/zagents.ts', [
32
32
  'export function listZagentManifests',
33
33
  'export function listZteamManifests',
34
34
  'export function zteamAllowsZpeerContact',
35
+ 'export function resolveZagentTeamMemberships',
36
+ 'export function resolveZagentRuntimeRoomBindings',
35
37
  'localOnly: true',
38
+ 'zagent.model must be a safe Pi --model pattern',
39
+ 'zagent.defaultMode must be one of',
36
40
  'networkEnabled: false',
37
41
  'bodyStored: false',
38
42
  ]);
@@ -54,6 +58,10 @@ requireIncludes('.pi/extensions/zob-harness/src/runtime/commands.ts', [
54
58
  'normalizeZagentRoomBindings',
55
59
  'readZagentPrompt',
56
60
  'ZOB_ZAGENT_ID=${member.id} pi',
61
+ '--model ${model}',
62
+ 'modelIdHashes: plan.modelIds.map((modelId) => sha256(modelId))',
63
+ 'defaultModeHashes: plan.defaultModes.map((mode) => sha256(mode))',
64
+ 'defaultMode=${defaultMode}',
57
65
  'After each session starts, run /zagent use <id> to bind its ZPeer alias/rooms.',
58
66
  'Project-local full-session ZAgents',
59
67
  'Project-local ZTeams',
@@ -68,12 +76,15 @@ requireIncludes('.pi/extensions/zob-harness/src/runtime/events.ts', [
68
76
  'process.env.ZOB_ZAGENT_ID?.trim()',
69
77
  'loadZagentManifest(repoRoot, zagentId)',
70
78
  'readZagentPrompt(repoRoot, manifest.promptRef)',
71
- 'normalizeZagentRoomBindings(manifest.rooms, manifest.defaultRoom, manifest.activeRoom)',
79
+ 'resolveZagentRuntimeRoomBindings(repoRoot, manifest)',
72
80
  'state.zagent = nextZagent',
81
+ 'defaultMode: manifest.defaultMode',
73
82
  'loadActiveZagentFromEnv(state, ctx.cwd)',
83
+ 'state.zagent.defaultMode && state.zagent.defaultMode !== state.activeMode',
74
84
  'ZAGENT RUNTIME ACTIVATION',
75
85
  'ZAgents are full Pi sessions tied to ZPeer/live coordination, not delegate subagents.',
76
86
  'team: zagent?.team ?? basePeer.team',
87
+ 'teams: resolved.teamIds',
77
88
  'roleId: zagent?.id ?? basePeer.roleId',
78
89
  'agent: zagent?.id ?? basePeer.agent',
79
90
  'team: zagent?.team ?? state.zobLive.peerCard.team',
@@ -84,14 +95,16 @@ requireIncludes('.pi/extensions/zob-harness/src/runtime/events.ts', [
84
95
  requireIncludes('.pi/extensions/zob-harness/src/runtime/state.ts', [
85
96
  'export interface ZagentRuntimeState',
86
97
  'team?: string;',
98
+ 'teams?: string[];',
87
99
  'role?: string;',
88
100
  'alias?: string;',
89
101
  'rooms: ZAgentRoomBinding[];',
102
+ 'defaultMode?: ModeName;',
90
103
  'zagent: ZagentRuntimeState;',
91
104
  'zagent: { rooms: [], errors: [] }',
92
105
  ], 'state');
93
106
 
94
- requireIncludes('.pi/extensions/zob-harness/src/coms-v2/zpeer.ts', [
107
+ requireIncludes('.pi/extensions/zob-harness/src/domains/coms/coms-v2/zpeer.ts', [
95
108
  'import { loadZteamManifest, zteamAllowsZpeerContact } from "../zagents.js"',
96
109
  'const zteam = loadZteamManifest(repoRoot, self.team)',
97
110
  'zteam fallback blocked',
@@ -138,8 +151,24 @@ requireIncludes('.pi/skills/zob-zagent-creator/SKILL.md', [
138
151
  '/zteam launch-plan <team-id>',
139
152
  'ZOB_ZAGENT_ID=<id> pi',
140
153
  'do not automatically spawn processes',
154
+ '.pi/model-catalog.json',
155
+ '.pi/model-catalog.example.json',
156
+ '.pi/model-routing.json',
157
+ 'costTier',
158
+ 'qualityTier',
159
+ 'ZOB_ZAGENT_ID=<id> pi --model <model>',
160
+ 'Default ZOB mode selection',
161
+ 'defaultMode',
162
+ 'never choose `vanilla` by default',
141
163
  'Do not add a scaffold slash command',
142
164
  'J\'ai besoin d\'une team de trois agents',
165
+ 'metadata.entryAgent',
166
+ 'start [agent]',
167
+ 'attach [agent]',
168
+ 'window <agent>',
169
+ 'list',
170
+ 'resolve_target_agent',
171
+ 'Unknown agent/window',
143
172
  ], 'zagent skill');
144
173
 
145
174
  const scaffoldCommand = ['/zteam', 'scaffold'].join(' ');
@@ -96,12 +96,13 @@ async function main() {
96
96
  if (existsSync(repoNodeModules)) symlinkSync(repoNodeModules, join(outDir, 'node_modules'), 'dir');
97
97
 
98
98
  const compiledSrc = join(outDir, '.pi/extensions/zob-harness/src');
99
- const zpeer = await import(`${compiledSrc}/coms-v2/zpeer.js`);
100
- const zpeerProfile = await import(`${compiledSrc}/coms-v2/zpeer-profile.js`);
99
+ const compiledComsV2 = `${compiledSrc}/domains/coms/coms-v2`;
100
+ const zpeer = await import(`${compiledComsV2}/zpeer.js`);
101
+ const zpeerProfile = await import(`${compiledComsV2}/zpeer-profile.js`);
101
102
  const toolsComs = await import(`${compiledSrc}/runtime/tools-coms.js`);
102
- const localTransport = await import(`${compiledSrc}/coms-v2/local-transport.js`);
103
- const envelope = await import(`${compiledSrc}/coms-v2/envelope.js`);
104
- const hashing = await import(`${compiledSrc}/utils/hashing.js`);
103
+ const localTransport = await import(`${compiledComsV2}/local-transport.js`);
104
+ const envelope = await import(`${compiledComsV2}/envelope.js`);
105
+ const hashing = await import(`${compiledSrc}/core/utils/hashing.js`);
105
106
 
106
107
  process.env.ZOB_ZPEER_PROFILE_ID = 'profile-alpha';
107
108
  delete process.env.ZPEER_PROFILE;