zob-harness 0.1.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 (356) hide show
  1. package/.pi/adapters/registry.json +103 -0
  2. package/.pi/agents/architecture-cartographer.md +53 -0
  3. package/.pi/agents/chief-vision.md +39 -0
  4. package/.pi/agents/clarifier.md +58 -0
  5. package/.pi/agents/context-steward.md +52 -0
  6. package/.pi/agents/doc-steward.md +34 -0
  7. package/.pi/agents/explore.md +49 -0
  8. package/.pi/agents/factory.md +41 -0
  9. package/.pi/agents/implementer.md +44 -0
  10. package/.pi/agents/librarian.md +32 -0
  11. package/.pi/agents/oracle-merge.md +50 -0
  12. package/.pi/agents/oracle.md +55 -0
  13. package/.pi/agents/pattern-miner.md +53 -0
  14. package/.pi/agents/planner.md +39 -0
  15. package/.pi/agents/project-dna-golden-evaluator.md +32 -0
  16. package/.pi/agents/project-dna-ontology-steward.md +30 -0
  17. package/.pi/agents/project-dna-oracle.md +56 -0
  18. package/.pi/agents/project-dna-orchestrator.md +60 -0
  19. package/.pi/agents/project-dna-query-steward.md +38 -0
  20. package/.pi/agents/project-dna-safety-preflight.md +54 -0
  21. package/.pi/agents/project-dna-test-linker.md +27 -0
  22. package/.pi/agents/qa.md +38 -0
  23. package/.pi/agents/refactor-cartographer.md +28 -0
  24. package/.pi/agents/refactor-mover.md +31 -0
  25. package/.pi/agents/refactor-oracle.md +49 -0
  26. package/.pi/agents/repo-scout.md +60 -0
  27. package/.pi/agents/sample-architect.md +48 -0
  28. package/.pi/agents/specifier.md +57 -0
  29. package/.pi/agents/symbol-range-curator.md +41 -0
  30. package/.pi/agents/synthesis.md +52 -0
  31. package/.pi/agents/temp-agent-creator.md +35 -0
  32. package/.pi/autonomy-policy.json +67 -0
  33. package/.pi/budget-policy.json +54 -0
  34. package/.pi/capabilities/zob-public-runtime-capabilities.json +1700 -0
  35. package/.pi/chains/explore-plan-oracle.json +78 -0
  36. package/.pi/chains/explore-spec-clarify-plan-oracle.json +64 -0
  37. package/.pi/chains/explore-spec-plan-oracle.json +53 -0
  38. package/.pi/chains/spec-clarify-plan-oracle.json +53 -0
  39. package/.pi/chains/spec-factory-oracle.json +42 -0
  40. package/.pi/chains/spec-plan-oracle.json +42 -0
  41. package/.pi/compute-profiles/defaults.json +19 -0
  42. package/.pi/compute-profiles/overrides.json +13 -0
  43. package/.pi/compute-profiles/risk-rules.json +16 -0
  44. package/.pi/daemon-policy.json +80 -0
  45. package/.pi/damage-control-rules.json +45 -0
  46. package/.pi/extensions/zob-child-safety/index.ts +212 -0
  47. package/.pi/extensions/zob-harness/AGENTS.md +28 -0
  48. package/.pi/extensions/zob-harness/index.ts +391 -0
  49. package/.pi/extensions/zob-harness/src/AGENTS.md +25 -0
  50. package/.pi/extensions/zob-harness/src/agents.ts +82 -0
  51. package/.pi/extensions/zob-harness/src/autonomous-runtime.ts +2912 -0
  52. package/.pi/extensions/zob-harness/src/autonomy-readiness.ts +778 -0
  53. package/.pi/extensions/zob-harness/src/budget-policy.ts +308 -0
  54. package/.pi/extensions/zob-harness/src/capabilities.ts +249 -0
  55. package/.pi/extensions/zob-harness/src/child-runner.ts +249 -0
  56. package/.pi/extensions/zob-harness/src/chronicle.ts +262 -0
  57. package/.pi/extensions/zob-harness/src/compute-profile.ts +602 -0
  58. package/.pi/extensions/zob-harness/src/compute-workflow-shape.ts +168 -0
  59. package/.pi/extensions/zob-harness/src/coms-v2/AGENTS.md +16 -0
  60. package/.pi/extensions/zob-harness/src/coms-v2/envelope.ts +121 -0
  61. package/.pi/extensions/zob-harness/src/coms-v2/identity.ts +53 -0
  62. package/.pi/extensions/zob-harness/src/coms-v2/ledger-bridge.ts +67 -0
  63. package/.pi/extensions/zob-harness/src/coms-v2/local-transport.ts +147 -0
  64. package/.pi/extensions/zob-harness/src/coms-v2/pending-replies.ts +80 -0
  65. package/.pi/extensions/zob-harness/src/coms-v2/policy.ts +125 -0
  66. package/.pi/extensions/zob-harness/src/coms-v2/presence.ts +55 -0
  67. package/.pi/extensions/zob-harness/src/coms-v2/registry.ts +113 -0
  68. package/.pi/extensions/zob-harness/src/coms-v2/response-capture.ts +50 -0
  69. package/.pi/extensions/zob-harness/src/coms-v2/transcript-capture.ts +164 -0
  70. package/.pi/extensions/zob-harness/src/coms-v2/types.ts +149 -0
  71. package/.pi/extensions/zob-harness/src/coms-v2/zpeer-profile.ts +140 -0
  72. package/.pi/extensions/zob-harness/src/coms-v2/zpeer.ts +452 -0
  73. package/.pi/extensions/zob-harness/src/constants.ts +108 -0
  74. package/.pi/extensions/zob-harness/src/context-gbrain.ts +465 -0
  75. package/.pi/extensions/zob-harness/src/daemon-policy.ts +223 -0
  76. package/.pi/extensions/zob-harness/src/daemon-readiness.ts +134 -0
  77. package/.pi/extensions/zob-harness/src/daemon-runtime.ts +393 -0
  78. package/.pi/extensions/zob-harness/src/factory/AGENTS.md +24 -0
  79. package/.pi/extensions/zob-harness/src/factory/agentic-plan.ts +65 -0
  80. package/.pi/extensions/zob-harness/src/factory/quarantine.ts +319 -0
  81. package/.pi/extensions/zob-harness/src/factory/run.ts +520 -0
  82. package/.pi/extensions/zob-harness/src/factory/validation.ts +454 -0
  83. package/.pi/extensions/zob-harness/src/factory-selector.ts +318 -0
  84. package/.pi/extensions/zob-harness/src/full-autonomy-test.ts +226 -0
  85. package/.pi/extensions/zob-harness/src/git-ops.ts +868 -0
  86. package/.pi/extensions/zob-harness/src/goal-room.ts +178 -0
  87. package/.pi/extensions/zob-harness/src/goal-runtime.ts +1569 -0
  88. package/.pi/extensions/zob-harness/src/goal-todo-imports.ts +111 -0
  89. package/.pi/extensions/zob-harness/src/goal-todo-types.ts +231 -0
  90. package/.pi/extensions/zob-harness/src/goal-todos.ts +1410 -0
  91. package/.pi/extensions/zob-harness/src/goal.ts +152 -0
  92. package/.pi/extensions/zob-harness/src/governed-requests.ts +436 -0
  93. package/.pi/extensions/zob-harness/src/interactive-autonomy.ts +595 -0
  94. package/.pi/extensions/zob-harness/src/launch-apply.ts +313 -0
  95. package/.pi/extensions/zob-harness/src/merge-queue.ts +290 -0
  96. package/.pi/extensions/zob-harness/src/mission-control.ts +573 -0
  97. package/.pi/extensions/zob-harness/src/model-availability.ts +52 -0
  98. package/.pi/extensions/zob-harness/src/model-routing.ts +429 -0
  99. package/.pi/extensions/zob-harness/src/orchestration/AGENTS.md +23 -0
  100. package/.pi/extensions/zob-harness/src/orchestration/adaptive-delegation.ts +547 -0
  101. package/.pi/extensions/zob-harness/src/orchestration/adaptive-workflow.ts +585 -0
  102. package/.pi/extensions/zob-harness/src/orchestration/lead-plan.ts +192 -0
  103. package/.pi/extensions/zob-harness/src/orchestration/plan.ts +168 -0
  104. package/.pi/extensions/zob-harness/src/orchestration/room.ts +346 -0
  105. package/.pi/extensions/zob-harness/src/orchestration/run.ts +134 -0
  106. package/.pi/extensions/zob-harness/src/orchestration/supervised-readonly.ts +1147 -0
  107. package/.pi/extensions/zob-harness/src/orchestration/widget-readers.ts +132 -0
  108. package/.pi/extensions/zob-harness/src/output-contracts.ts +656 -0
  109. package/.pi/extensions/zob-harness/src/project-dna.ts +533 -0
  110. package/.pi/extensions/zob-harness/src/promotion/AGENTS.md +24 -0
  111. package/.pi/extensions/zob-harness/src/promotion/candidate.ts +336 -0
  112. package/.pi/extensions/zob-harness/src/promotion/coms.ts +127 -0
  113. package/.pi/extensions/zob-harness/src/promotion/documentation.ts +142 -0
  114. package/.pi/extensions/zob-harness/src/promotion/factory.ts +107 -0
  115. package/.pi/extensions/zob-harness/src/promotion/ledger.ts +2 -0
  116. package/.pi/extensions/zob-harness/src/promotion/temp-agent.ts +151 -0
  117. package/.pi/extensions/zob-harness/src/promotion/types.ts +149 -0
  118. package/.pi/extensions/zob-harness/src/promotion/validate.ts +6 -0
  119. package/.pi/extensions/zob-harness/src/promotion/write-lane.ts +162 -0
  120. package/.pi/extensions/zob-harness/src/prompt-packs.ts +239 -0
  121. package/.pi/extensions/zob-harness/src/queue.ts +386 -0
  122. package/.pi/extensions/zob-harness/src/rules.ts +225 -0
  123. package/.pi/extensions/zob-harness/src/runtime/AGENTS.md +26 -0
  124. package/.pi/extensions/zob-harness/src/runtime/adaptive-zmode.ts +116 -0
  125. package/.pi/extensions/zob-harness/src/runtime/auto-compaction.ts +715 -0
  126. package/.pi/extensions/zob-harness/src/runtime/commands.ts +1315 -0
  127. package/.pi/extensions/zob-harness/src/runtime/compaction-policy.ts +516 -0
  128. package/.pi/extensions/zob-harness/src/runtime/delegation-click-markers.ts +141 -0
  129. package/.pi/extensions/zob-harness/src/runtime/delegation-feed.ts +415 -0
  130. package/.pi/extensions/zob-harness/src/runtime/delegation-markdown.ts +97 -0
  131. package/.pi/extensions/zob-harness/src/runtime/delegation-monitor.ts +553 -0
  132. package/.pi/extensions/zob-harness/src/runtime/delegation-mouse.ts +205 -0
  133. package/.pi/extensions/zob-harness/src/runtime/delegation-overlay.ts +434 -0
  134. package/.pi/extensions/zob-harness/src/runtime/events.ts +736 -0
  135. package/.pi/extensions/zob-harness/src/runtime/goal-todo-overlay.ts +214 -0
  136. package/.pi/extensions/zob-harness/src/runtime/mode-intent.ts +144 -0
  137. package/.pi/extensions/zob-harness/src/runtime/plan-capture.ts +270 -0
  138. package/.pi/extensions/zob-harness/src/runtime/state.ts +403 -0
  139. package/.pi/extensions/zob-harness/src/runtime/tools-autonomous.ts +117 -0
  140. package/.pi/extensions/zob-harness/src/runtime/tools-compute.ts +136 -0
  141. package/.pi/extensions/zob-harness/src/runtime/tools-coms.ts +365 -0
  142. package/.pi/extensions/zob-harness/src/runtime/tools-context.ts +70 -0
  143. package/.pi/extensions/zob-harness/src/runtime/tools-delegation.ts +1854 -0
  144. package/.pi/extensions/zob-harness/src/runtime/tools-factory.ts +810 -0
  145. package/.pi/extensions/zob-harness/src/runtime/tools-goal-room.ts +46 -0
  146. package/.pi/extensions/zob-harness/src/runtime/tools-governed-requests.ts +38 -0
  147. package/.pi/extensions/zob-harness/src/runtime/tools-merge-queue.ts +61 -0
  148. package/.pi/extensions/zob-harness/src/runtime/tools-mission-control.ts +77 -0
  149. package/.pi/extensions/zob-harness/src/runtime/tools-orchestration.ts +106 -0
  150. package/.pi/extensions/zob-harness/src/runtime/tools-project-dna.ts +123 -0
  151. package/.pi/extensions/zob-harness/src/runtime/tools-worker-pool.ts +93 -0
  152. package/.pi/extensions/zob-harness/src/runtime/tools-workspace-claims.ts +62 -0
  153. package/.pi/extensions/zob-harness/src/runtime/tools-zcommit.ts +147 -0
  154. package/.pi/extensions/zob-harness/src/runtime/widget.ts +353 -0
  155. package/.pi/extensions/zob-harness/src/runtime/zobHarness.ts +60 -0
  156. package/.pi/extensions/zob-harness/src/safety.ts +338 -0
  157. package/.pi/extensions/zob-harness/src/sandbox.ts +1508 -0
  158. package/.pi/extensions/zob-harness/src/schemas-project-dna.ts +47 -0
  159. package/.pi/extensions/zob-harness/src/schemas.ts +695 -0
  160. package/.pi/extensions/zob-harness/src/telemetry.ts +373 -0
  161. package/.pi/extensions/zob-harness/src/topology/AGENTS.md +22 -0
  162. package/.pi/extensions/zob-harness/src/topology/chains.ts +236 -0
  163. package/.pi/extensions/zob-harness/src/topology/coms.ts +211 -0
  164. package/.pi/extensions/zob-harness/src/topology/orchestration-profiles.ts +204 -0
  165. package/.pi/extensions/zob-harness/src/topology/teams.ts +113 -0
  166. package/.pi/extensions/zob-harness/src/types/core.ts +47 -0
  167. package/.pi/extensions/zob-harness/src/types.ts +939 -0
  168. package/.pi/extensions/zob-harness/src/utils/AGENTS.md +22 -0
  169. package/.pi/extensions/zob-harness/src/utils/formatting.ts +34 -0
  170. package/.pi/extensions/zob-harness/src/utils/hashing.ts +11 -0
  171. package/.pi/extensions/zob-harness/src/utils/json.ts +28 -0
  172. package/.pi/extensions/zob-harness/src/utils/paths.ts +54 -0
  173. package/.pi/extensions/zob-harness/src/utils/records.ts +25 -0
  174. package/.pi/extensions/zob-harness/src/utils/resources.ts +38 -0
  175. package/.pi/extensions/zob-harness/src/worker-pool.ts +672 -0
  176. package/.pi/extensions/zob-harness/src/workspace-claims.ts +297 -0
  177. package/.pi/extensions/zob-switch/index.ts +180 -0
  178. package/.pi/factories/budget-preflight-dry-run/batch-manifest.json +59 -0
  179. package/.pi/factories/budget-preflight-dry-run/factory.json +94 -0
  180. package/.pi/factories/budget-preflight-dry-run/pilot-manifest.json +50 -0
  181. package/.pi/factories/budget-preflight-dry-run/smoke-manifest.json +43 -0
  182. package/.pi/factories/code-review-matrix/batch-manifest.json +61 -0
  183. package/.pi/factories/code-review-matrix/factory.json +163 -0
  184. package/.pi/factories/code-review-matrix/pilot-manifest.json +41 -0
  185. package/.pi/factories/code-review-matrix/smoke-manifest.json +35 -0
  186. package/.pi/factories/factory-forge/batch-manifest.json +56 -0
  187. package/.pi/factories/factory-forge/factory.json +84 -0
  188. package/.pi/factories/factory-forge/pilot-manifest.json +32 -0
  189. package/.pi/factories/factory-forge/smoke-manifest.json +19 -0
  190. package/.pi/factories/opencode-pattern-canonizer/batch-manifest.json +54 -0
  191. package/.pi/factories/opencode-pattern-canonizer/factory.json +86 -0
  192. package/.pi/factories/opencode-pattern-canonizer/pilot-manifest.json +39 -0
  193. package/.pi/factories/opencode-pattern-canonizer/smoke-manifest.json +26 -0
  194. package/.pi/factories/project-dna/README.md +182 -0
  195. package/.pi/factories/project-dna/batch-manifest.json +37 -0
  196. package/.pi/factories/project-dna/example-project-dna-manifest-v2.json +80 -0
  197. package/.pi/factories/project-dna/example-project-dna-manifest.json +58 -0
  198. package/.pi/factories/project-dna/factory.json +131 -0
  199. package/.pi/factories/project-dna/golden-cases-smoke.json +62 -0
  200. package/.pi/factories/project-dna/pi-agentic-ontology.json +88 -0
  201. package/.pi/factories/project-dna/pilot-manifest.json +32 -0
  202. package/.pi/factories/project-dna/schemas/benchmark-suite.schema.json +27 -0
  203. package/.pi/factories/project-dna/schemas/code-knowledge-graph.schema.json +97 -0
  204. package/.pi/factories/project-dna/schemas/context-pack.schema.json +43 -0
  205. package/.pi/factories/project-dna/schemas/golden-case.schema.json +36 -0
  206. package/.pi/factories/project-dna/schemas/manifest-v2.schema.json +128 -0
  207. package/.pi/factories/project-dna/schemas/manifest.schema.json +77 -0
  208. package/.pi/factories/project-dna/schemas/ontology.schema.json +45 -0
  209. package/.pi/factories/project-dna/schemas/project-fingerprint.schema.json +28 -0
  210. package/.pi/factories/project-dna/schemas/query-steward-report.schema.json +52 -0
  211. package/.pi/factories/project-dna/smoke-manifest.json +27 -0
  212. package/.pi/factories/roadmap-smoke-lots/batch-manifest.json +49 -0
  213. package/.pi/factories/roadmap-smoke-lots/factory.json +89 -0
  214. package/.pi/factories/roadmap-smoke-lots/pilot-manifest.json +50 -0
  215. package/.pi/factories/roadmap-smoke-lots/smoke-manifest.json +35 -0
  216. package/.pi/git-policy.json +120 -0
  217. package/.pi/mission-control/zob_coms_transport.json +64 -0
  218. package/.pi/model-catalog.example.json +345 -0
  219. package/.pi/model-economy.example.json +196 -0
  220. package/.pi/model-routing.json +86 -0
  221. package/.pi/orchestrations/adaptive-chief-vision.json +193 -0
  222. package/.pi/orchestrations/ceo-feature-build.json +182 -0
  223. package/.pi/orchestrations/readonly-dynamic-smoke.json +75 -0
  224. package/.pi/output-contracts/agent-event.v1.json +19 -0
  225. package/.pi/output-contracts/base.v1.json +24 -0
  226. package/.pi/output-contracts/brain-lookup.v1.json +21 -0
  227. package/.pi/output-contracts/clarification.v1.json +21 -0
  228. package/.pi/output-contracts/context-pack.v1.json +20 -0
  229. package/.pi/output-contracts/context-request.v1.json +21 -0
  230. package/.pi/output-contracts/context-steward.v1.json +19 -0
  231. package/.pi/output-contracts/context-writeback-proposal.v1.json +18 -0
  232. package/.pi/output-contracts/delegation-request.v1.json +21 -0
  233. package/.pi/output-contracts/explore.v1.json +52 -0
  234. package/.pi/output-contracts/factory.v1.json +48 -0
  235. package/.pi/output-contracts/guidance-steward.v1.json +18 -0
  236. package/.pi/output-contracts/implement.v1.json +40 -0
  237. package/.pi/output-contracts/launch-authorization.v1.json +21 -0
  238. package/.pi/output-contracts/lead-plan.v1.json +22 -0
  239. package/.pi/output-contracts/mission-readiness.v1.json +20 -0
  240. package/.pi/output-contracts/oracle-merge.v1.json +44 -0
  241. package/.pi/output-contracts/oracle-request.v1.json +20 -0
  242. package/.pi/output-contracts/oracle.v1.json +44 -0
  243. package/.pi/output-contracts/orchestration-profile.v1.json +22 -0
  244. package/.pi/output-contracts/plan.v1.json +48 -0
  245. package/.pi/output-contracts/prompt-pack.v1.json +20 -0
  246. package/.pi/output-contracts/qa.v1.json +40 -0
  247. package/.pi/output-contracts/research.v1.json +36 -0
  248. package/.pi/output-contracts/spec.v1.json +22 -0
  249. package/.pi/output-contracts/synthesis.v1.json +44 -0
  250. package/.pi/output-contracts/temp-agent-card.v1.json +23 -0
  251. package/.pi/output-contracts/todo-child-result.v1.json +20 -0
  252. package/.pi/output-contracts/todo-child-result.v2.json +22 -0
  253. package/.pi/output-contracts/todo-claim-validation.v1.json +22 -0
  254. package/.pi/output-contracts/todo-split-request.v1.json +20 -0
  255. package/.pi/prompts/adaptive-workflow.md +63 -0
  256. package/.pi/prompts/autonomous-runtime.md +15 -0
  257. package/.pi/prompts/benchmark-contender.md +15 -0
  258. package/.pi/prompts/benchmark-judge.md +19 -0
  259. package/.pi/prompts/clarify-spec.md +20 -0
  260. package/.pi/prompts/compute-plan.md +36 -0
  261. package/.pi/prompts/compute-preview.md +42 -0
  262. package/.pi/prompts/contract.md +29 -0
  263. package/.pi/prompts/explore.md +13 -0
  264. package/.pi/prompts/factory-run.md +36 -0
  265. package/.pi/prompts/factory.md +20 -0
  266. package/.pi/prompts/implement.md +27 -0
  267. package/.pi/prompts/model-catalog.md +68 -0
  268. package/.pi/prompts/model-economy.md +64 -0
  269. package/.pi/prompts/oracle-merge.md +18 -0
  270. package/.pi/prompts/oracle.md +13 -0
  271. package/.pi/prompts/orchestrator.md +48 -0
  272. package/.pi/prompts/parallel-review.md +21 -0
  273. package/.pi/prompts/plan.md +21 -0
  274. package/.pi/prompts/project-dna.md +90 -0
  275. package/.pi/prompts/refactor-oracle.md +23 -0
  276. package/.pi/prompts/refactor-slice.md +24 -0
  277. package/.pi/prompts/research.md +20 -0
  278. package/.pi/prompts/spec.md +19 -0
  279. package/.pi/prompts/synthesis.md +18 -0
  280. package/.pi/rules/always.md +38 -0
  281. package/.pi/rules/docs.md +32 -0
  282. package/.pi/rules/factory.md +44 -0
  283. package/.pi/rules/oracle.md +34 -0
  284. package/.pi/rules/orchestration.md +44 -0
  285. package/.pi/rules/project.md +34 -0
  286. package/.pi/rules/prompts.md +43 -0
  287. package/.pi/rules/runtime.md +43 -0
  288. package/.pi/rules/sandbox.md +43 -0
  289. package/.pi/settings.json +28 -0
  290. package/.pi/skills/zob-agentic-access/SKILL.md +20 -0
  291. package/.pi/skills/zob-autonomous-runtime/SKILL.md +41 -0
  292. package/.pi/skills/zob-commit/SKILL.md +79 -0
  293. package/.pi/skills/zob-compaction-policy/SKILL.md +92 -0
  294. package/.pi/skills/zob-compute-profile/SKILL.md +108 -0
  295. package/.pi/skills/zob-coms-safety/SKILL.md +54 -0
  296. package/.pi/skills/zob-coms-v2-live/SKILL.md +47 -0
  297. package/.pi/skills/zob-delegation-routing/SKILL.md +82 -0
  298. package/.pi/skills/zob-factory/SKILL.md +28 -0
  299. package/.pi/skills/zob-goal-todo-tree/SKILL.md +279 -0
  300. package/.pi/skills/zob-harness/SKILL.md +68 -0
  301. package/.pi/skills/zob-mission-control-coms/SKILL.md +39 -0
  302. package/.pi/skills/zob-oracle/SKILL.md +21 -0
  303. package/.pi/skills/zob-owner-pool-drill-writer/SKILL.md +244 -0
  304. package/.pi/skills/zob-owner-pool-launcher/SKILL.md +261 -0
  305. package/.pi/skills/zob-project-dna/SKILL.md +275 -0
  306. package/.pi/skills/zob-sandbox/SKILL.md +29 -0
  307. package/.pi/skills/zob-spec/SKILL.md +25 -0
  308. package/.pi/skills/zob-split-refactor/SKILL.md +39 -0
  309. package/.pi/skills/zob-tool-router/SKILL.md +104 -0
  310. package/.pi/teams/zob-core.json +122 -0
  311. package/AGENTS.md +89 -0
  312. package/CONTRIBUTING.md +56 -0
  313. package/LICENSE +21 -0
  314. package/README.md +360 -0
  315. package/SECURITY.md +35 -0
  316. package/SOURCE_INDEX.md +46 -0
  317. package/package.json +135 -0
  318. package/scripts/README.md +57 -0
  319. package/scripts/autonomy/mission-readiness-secret-smoke.mjs +90 -0
  320. package/scripts/compute-profile/plan-workflow.mjs +85 -0
  321. package/scripts/compute-profile/preview.mjs +242 -0
  322. package/scripts/compute-profile/regression-smoke.mjs +38 -0
  323. package/scripts/compute-profile/summarize.mjs +72 -0
  324. package/scripts/compute-profile/validate-policy.mjs +50 -0
  325. package/scripts/compute-profile/validate-preview.mjs +95 -0
  326. package/scripts/compute-profile/validate-workflow.mjs +58 -0
  327. package/scripts/git-ops/commit-policy-smoke.mjs +221 -0
  328. package/scripts/goal-todo/child-goal-ref-smoke.mjs +252 -0
  329. package/scripts/harness-switch/static-smoke.mjs +43 -0
  330. package/scripts/model-catalog/validate-economy.mjs +223 -0
  331. package/scripts/model-catalog/validate.mjs +199 -0
  332. package/scripts/package-surface/validate-script-refs.mjs +190 -0
  333. package/scripts/path-policy/validate-smoke.mjs +103 -0
  334. package/scripts/project-dna/bench-smoke.mjs +217 -0
  335. package/scripts/project-dna/build-capsules.mjs +207 -0
  336. package/scripts/project-dna/build-sample-spec.mjs +140 -0
  337. package/scripts/project-dna/emit-golden-cases.mjs +75 -0
  338. package/scripts/project-dna/emit-ontology.mjs +75 -0
  339. package/scripts/project-dna/generate-sample.mjs +302 -0
  340. package/scripts/project-dna/oracle-review-smoke.mjs +157 -0
  341. package/scripts/project-dna/plan-workflow.mjs +289 -0
  342. package/scripts/project-dna/query-context.mjs +276 -0
  343. package/scripts/project-dna/query-steward.mjs +149 -0
  344. package/scripts/project-dna/scan.mjs +553 -0
  345. package/scripts/project-dna/validate-5of5.mjs +159 -0
  346. package/scripts/project-dna/validate-golden-cases.mjs +78 -0
  347. package/scripts/project-dna/validate-ontology.mjs +97 -0
  348. package/scripts/project-dna/validate-sample-project.mjs +105 -0
  349. package/scripts/project-dna/validate-scaffold.mjs +383 -0
  350. package/scripts/project-dna/validate-scan-artifacts.mjs +187 -0
  351. package/scripts/project-dna/validate-workflow.mjs +166 -0
  352. package/scripts/start-pi.sh +4 -0
  353. package/scripts/worker-pool/static-smoke.mjs +54 -0
  354. package/scripts/zpeer-local-e2e-smoke.mjs +395 -0
  355. package/scripts/zpeer-static-smoke.mjs +129 -0
  356. package/tsconfig.json +12 -0
@@ -0,0 +1,672 @@
1
+ import { appendFileSync, existsSync, mkdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import { DEFAULT_RULES } from "./constants.js";
5
+ import { appendGoalRoomMessage } from "./goal-room.js";
6
+ import type { TeamDefinition } from "./types.js";
7
+ import { sha256 } from "./utils/hashing.js";
8
+ import { readJsonl } from "./utils/json.js";
9
+ import { newRunId, pathMatches, resolveRepoPath, safeFileStem } from "./utils/paths.js";
10
+ import { isRecord } from "./utils/records.js";
11
+ import { listWorkspaceClaims, type WorkspaceClaimRecord } from "./workspace-claims.js";
12
+
13
+ export type WorkerPoolCommunicationPolicyMode = "goal_room_only" | "goal_room_with_optional_live";
14
+ export type WorkerPoolDecision = "approved" | "rejected" | "needs_parent" | "owner_will_handle";
15
+
16
+ export interface WorkerPoolCommunicationPolicyInput {
17
+ mode?: WorkerPoolCommunicationPolicyMode;
18
+ parent_visible?: boolean;
19
+ hidden_peer_chat?: boolean;
20
+ worker_to_worker_direct?: boolean;
21
+ required_local_live?: boolean;
22
+ goal_room_canonical?: boolean;
23
+ }
24
+
25
+ export interface WorkerPoolAssignmentInput {
26
+ worker_id: string;
27
+ agent_name: string;
28
+ owned_paths: string[];
29
+ write_paths: string[];
30
+ read_across_paths?: string[];
31
+ read_across_write_overlap_justification_hash?: string;
32
+ forbidden_paths?: string[];
33
+ todo_id?: string;
34
+ child_goal_id?: string;
35
+ run_id?: string;
36
+ workspace_claim_ids?: string[];
37
+ communication_policy?: WorkerPoolCommunicationPolicyInput;
38
+ }
39
+
40
+ export interface WorkerPoolPlanInput {
41
+ goal_id: string;
42
+ pool_id?: string;
43
+ run_id?: string;
44
+ todo_id?: string;
45
+ owner: string;
46
+ assignments: WorkerPoolAssignmentInput[];
47
+ forbidden_paths?: string[];
48
+ communication_policy?: WorkerPoolCommunicationPolicyInput;
49
+ }
50
+
51
+ export interface WorkerPoolStatusInput {
52
+ goal_id?: string;
53
+ pool_id?: string;
54
+ run_id?: string;
55
+ limit?: number;
56
+ }
57
+
58
+ export interface WorkerPoolOwnerRequestInput {
59
+ goal_id: string;
60
+ pool_id: string;
61
+ request_id?: string;
62
+ run_id?: string;
63
+ todo_id?: string;
64
+ requester: string;
65
+ owner_worker: string;
66
+ requested_paths: string[];
67
+ change_hash: string;
68
+ reason_hash: string;
69
+ evidence_refs?: string[];
70
+ artifact_refs?: string[];
71
+ }
72
+
73
+ export interface WorkerPoolOwnerDecisionInput {
74
+ goal_id: string;
75
+ pool_id: string;
76
+ request_id: string;
77
+ run_id?: string;
78
+ todo_id?: string;
79
+ decided_by: string;
80
+ owner_worker: string;
81
+ requester?: string;
82
+ decision: WorkerPoolDecision;
83
+ decision_hash: string;
84
+ evidence_refs?: string[];
85
+ artifact_refs?: string[];
86
+ }
87
+
88
+ export interface WorkerPoolCommunicationPolicyRecord {
89
+ mode: WorkerPoolCommunicationPolicyMode;
90
+ parentVisible: true;
91
+ hiddenPeerChat: false;
92
+ workerToWorkerDirect: false;
93
+ requiredLocalLive: boolean;
94
+ goalRoomCanonical: true;
95
+ }
96
+
97
+ export interface WorkerPoolAssignmentRecord {
98
+ workerId: string;
99
+ agentName: string;
100
+ ownedPaths: string[];
101
+ ownedPathHashes: string[];
102
+ writePaths: string[];
103
+ writePathHashes: string[];
104
+ readAcrossPaths: string[];
105
+ readAcrossPathHashes: string[];
106
+ readAcrossWriteOverlapJustificationHash: string | null;
107
+ forbiddenPaths: string[];
108
+ todoId: string | null;
109
+ childGoalId: string | null;
110
+ runId: string | null;
111
+ workspaceClaimIds: string[];
112
+ workspaceClaimsCoverWriteIntent: boolean;
113
+ communicationPolicy: WorkerPoolCommunicationPolicyRecord;
114
+ }
115
+
116
+ export interface WorkerPoolConflictRecord {
117
+ schema: "zob.worker-pool-conflict.v1";
118
+ type: "assignment_write_overlap" | "workspace_claim_overlap" | "owner_request_plan_mismatch";
119
+ poolId: string;
120
+ workerIds: string[];
121
+ paths: string[];
122
+ conflictHash: string;
123
+ parentOwnedResolutionRequired: true;
124
+ writesBlocked: true;
125
+ productionWritesPerformed: false;
126
+ autoApply: false;
127
+ bodyStored: false;
128
+ promptBodiesStored: false;
129
+ outputBodiesStored: false;
130
+ }
131
+
132
+ export interface WorkerPoolSafetyGateRecord {
133
+ schema: "zob.worker-pool-safety-gates.v1";
134
+ workspaceClaimsChecked: true;
135
+ ownerPathCoverageRequired: true;
136
+ sandboxIsolationRequired: true;
137
+ mergeQueueRequired: true;
138
+ rollbackMetadataRequired: true;
139
+ oracleReviewRequiredForRiskyMerge: true;
140
+ parentOwnedApplyOnly: true;
141
+ productionWritesPerformed: false;
142
+ autoApply: false;
143
+ }
144
+
145
+ export interface WorkerPoolPlanRecord {
146
+ schema: "zob.worker-pool-plan.v1";
147
+ poolId: string;
148
+ goalId: string;
149
+ runId: string | null;
150
+ todoId: string | null;
151
+ owner: string;
152
+ assignments: WorkerPoolAssignmentRecord[];
153
+ forbiddenPaths: string[];
154
+ communicationPolicy: WorkerPoolCommunicationPolicyRecord;
155
+ conflicts: WorkerPoolConflictRecord[];
156
+ status: "planned" | "blocked_conflict";
157
+ safetyGates: WorkerPoolSafetyGateRecord;
158
+ parentOwned: true;
159
+ readAcrossWriteByOwner: true;
160
+ productionWritesPerformed: false;
161
+ autoApply: false;
162
+ bodyStored: false;
163
+ promptBodiesStored: false;
164
+ outputBodiesStored: false;
165
+ createdAt: string;
166
+ }
167
+
168
+ export interface WorkerPoolOwnerRequestRecord {
169
+ schema: "zob.worker-pool-owner-request.v1";
170
+ requestId: string;
171
+ poolId: string;
172
+ goalId: string;
173
+ runId: string | null;
174
+ todoId: string | null;
175
+ requester: string;
176
+ ownerWorker: string;
177
+ requestedPaths: string[];
178
+ requestedPathHashes: string[];
179
+ changeHash: string;
180
+ reasonHash: string;
181
+ planValidation: "covered_by_owner" | "blocked_no_plan" | "blocked_unknown_owner" | "blocked_uncovered_paths";
182
+ parentOwnedConflict: boolean;
183
+ goalRoomMsgId: string;
184
+ parentVisible: true;
185
+ hiddenPeerChat: false;
186
+ workerToWorkerDirect: false;
187
+ parentOwnedDecisionRequired: true;
188
+ productionWritesPerformed: false;
189
+ autoApply: false;
190
+ bodyStored: false;
191
+ promptBodiesStored: false;
192
+ outputBodiesStored: false;
193
+ createdAt: string;
194
+ }
195
+
196
+ export interface WorkerPoolOwnerDecisionRecord {
197
+ schema: "zob.worker-pool-owner-decision.v1";
198
+ decisionId: string;
199
+ requestId: string;
200
+ poolId: string;
201
+ goalId: string;
202
+ runId: string | null;
203
+ todoId: string | null;
204
+ decidedBy: string;
205
+ ownerWorker: string;
206
+ requester: string | null;
207
+ decision: WorkerPoolDecision;
208
+ decisionHash: string;
209
+ goalRoomMsgId: string;
210
+ parentVisible: true;
211
+ hiddenPeerChat: false;
212
+ workerToWorkerDirect: false;
213
+ parentOwnedActions: true;
214
+ productionWritesPerformed: false;
215
+ autoApply: false;
216
+ bodyStored: false;
217
+ promptBodiesStored: false;
218
+ outputBodiesStored: false;
219
+ createdAt: string;
220
+ }
221
+
222
+ const SHA256_HEX = /^[a-f0-9]{64}$/i;
223
+ const MAX_ASSIGNMENTS = 32;
224
+ const MAX_PATHS = 100;
225
+ const FORBIDDEN_PLAINTEXT_KEYS = new Set(["body", "task", "prompt", "output", "content", "message", "text", "rationale", "diff", "patch"]);
226
+ const DECISIONS = new Set<WorkerPoolDecision>(["approved", "rejected", "needs_parent", "owner_will_handle"]);
227
+
228
+ function hasForbiddenPlaintextKeys(value: unknown): boolean {
229
+ if (!value || typeof value !== "object") return false;
230
+ if (Array.isArray(value)) return value.some(hasForbiddenPlaintextKeys);
231
+ return Object.entries(value as Record<string, unknown>).some(([key, child]) => FORBIDDEN_PLAINTEXT_KEYS.has(key) || hasForbiddenPlaintextKeys(child));
232
+ }
233
+
234
+ function workerPoolsDir(repoRoot: string): string {
235
+ return join(repoRoot, ".pi", "worker-pools");
236
+ }
237
+
238
+ function plansPath(repoRoot: string): string {
239
+ return join(workerPoolsDir(repoRoot), "plans.jsonl");
240
+ }
241
+
242
+ function requestsPath(repoRoot: string): string {
243
+ return join(workerPoolsDir(repoRoot), "owner-requests.jsonl");
244
+ }
245
+
246
+ function decisionsPath(repoRoot: string): string {
247
+ return join(workerPoolsDir(repoRoot), "owner-decisions.jsonl");
248
+ }
249
+
250
+ function knownRoleIds(definition: TeamDefinition): Set<string> {
251
+ return new Set([definition.orchestrator.id, ...definition.leads.map((lead) => lead.id), ...definition.workers.map((worker) => worker.id), "parent", "mission-control"]);
252
+ }
253
+
254
+ function normalizeUnique(values: string[] | undefined): string[] {
255
+ return [...new Set((values ?? []).map((value) => value.trim()).filter(Boolean))].sort();
256
+ }
257
+
258
+ function communicationPolicy(input?: WorkerPoolCommunicationPolicyInput): WorkerPoolCommunicationPolicyRecord {
259
+ return {
260
+ mode: input?.mode === "goal_room_with_optional_live" ? "goal_room_with_optional_live" : "goal_room_only",
261
+ parentVisible: true,
262
+ hiddenPeerChat: false,
263
+ workerToWorkerDirect: false,
264
+ requiredLocalLive: input?.required_local_live === true,
265
+ goalRoomCanonical: true,
266
+ };
267
+ }
268
+
269
+ function validatePathList(repoRoot: string, paths: string[] | undefined, label: string, allowZeroAccessDenyRefs = false): string[] {
270
+ const errors: string[] = [];
271
+ const normalized = normalizeUnique(paths);
272
+ if (normalized.length > MAX_PATHS) errors.push(`${label} are capped at ${MAX_PATHS}`);
273
+ for (const path of normalized) {
274
+ if (path.includes("\0")) {
275
+ errors.push(`${label} contains NUL byte`);
276
+ continue;
277
+ }
278
+ const resolved = resolveRepoPath(repoRoot, path);
279
+ errors.push(...resolved.errors.map((error) => `${label}: ${error}`));
280
+ if (!allowZeroAccessDenyRefs) {
281
+ for (const protectedPattern of DEFAULT_RULES.zeroAccessPaths) {
282
+ if (pathMatches(path, protectedPattern, repoRoot, repoRoot)) errors.push(`${label} references zero-access path: ${protectedPattern}`);
283
+ }
284
+ }
285
+ }
286
+ return errors;
287
+ }
288
+
289
+ function validateSafeIds(input: { goal_id?: string; pool_id?: string; run_id?: string; todo_id?: string; request_id?: string; child_goal_id?: string }, errors: string[]): void {
290
+ for (const [key, value] of Object.entries(input)) {
291
+ if (value && safeFileStem(value) !== value) errors.push(`${key} must be path-safe: ${value}`);
292
+ }
293
+ }
294
+
295
+ function validateWorkerPoolPlanInput(repoRoot: string, definition: TeamDefinition, input: WorkerPoolPlanInput): string[] {
296
+ const errors: string[] = [];
297
+ validateSafeIds({ goal_id: input.goal_id, pool_id: input.pool_id, run_id: input.run_id, todo_id: input.todo_id }, errors);
298
+ if (!input.goal_id) errors.push("worker pool goal_id is required");
299
+ if (!knownRoleIds(definition).has(input.owner)) errors.push(`Unknown worker-pool owner '${input.owner}'`);
300
+ if (!Array.isArray(input.assignments) || input.assignments.length === 0) errors.push("worker pool requires at least one assignment");
301
+ if ((input.assignments ?? []).length > MAX_ASSIGNMENTS) errors.push(`worker pool assignments are capped at ${MAX_ASSIGNMENTS}`);
302
+ if (hasForbiddenPlaintextKeys(input)) errors.push("worker pool input must not contain raw body/task/prompt/output/content/message/text/rationale/diff/patch keys");
303
+ errors.push(...validatePathList(repoRoot, input.forbidden_paths, "pool forbidden_paths", true));
304
+ for (const assignment of input.assignments ?? []) {
305
+ validateSafeIds({ run_id: assignment.run_id, todo_id: assignment.todo_id, child_goal_id: assignment.child_goal_id }, errors);
306
+ if (!knownRoleIds(definition).has(assignment.worker_id)) errors.push(`Unknown worker-pool assignment worker_id '${assignment.worker_id}'`);
307
+ if (!assignment.agent_name || assignment.agent_name.trim().length === 0) errors.push(`worker ${assignment.worker_id} requires agent_name`);
308
+ if (!Array.isArray(assignment.owned_paths) || assignment.owned_paths.length === 0) errors.push(`worker ${assignment.worker_id} requires owned_paths`);
309
+ if (!Array.isArray(assignment.write_paths) || assignment.write_paths.length === 0) errors.push(`worker ${assignment.worker_id} requires write_paths`);
310
+ errors.push(...validatePathList(repoRoot, assignment.owned_paths, `worker ${assignment.worker_id} owned_paths`));
311
+ errors.push(...validatePathList(repoRoot, assignment.write_paths, `worker ${assignment.worker_id} write_paths`));
312
+ errors.push(...validatePathList(repoRoot, assignment.read_across_paths, `worker ${assignment.worker_id} read_across_paths`));
313
+ errors.push(...validatePathList(repoRoot, assignment.forbidden_paths, `worker ${assignment.worker_id} forbidden_paths`, true));
314
+ for (const claimId of assignment.workspace_claim_ids ?? []) {
315
+ if (!claimId || safeFileStem(claimId) !== claimId) errors.push(`worker ${assignment.worker_id} workspace_claim_ids must be path-safe: ${claimId}`);
316
+ }
317
+ if (assignment.read_across_write_overlap_justification_hash !== undefined && !SHA256_HEX.test(assignment.read_across_write_overlap_justification_hash)) errors.push(`worker ${assignment.worker_id} read_across_write_overlap_justification_hash must be sha256 hex`);
318
+ if (Array.isArray(assignment.owned_paths) && Array.isArray(assignment.write_paths) && !pathsCoveredByOwnedPaths(repoRoot, assignment.write_paths, assignment.owned_paths)) errors.push(`worker ${assignment.worker_id} write_paths must be within owned_paths`);
319
+ const readWriteOverlap = (assignment.read_across_paths ?? []).some((readPath) => (assignment.write_paths ?? []).some((writePath) => pathsOverlap(repoRoot, readPath, writePath)));
320
+ if (readWriteOverlap && !assignment.read_across_write_overlap_justification_hash) errors.push(`worker ${assignment.worker_id} read_across_paths overlap write_paths and require read_across_write_overlap_justification_hash`);
321
+ if (assignment.communication_policy?.parent_visible === false || assignment.communication_policy?.hidden_peer_chat === true || assignment.communication_policy?.worker_to_worker_direct === true || assignment.communication_policy?.goal_room_canonical === false) {
322
+ errors.push(`worker ${assignment.worker_id} communication policy must be parent-visible, Goal Room canonical, and not direct hidden peer chat`);
323
+ }
324
+ }
325
+ if (input.communication_policy?.parent_visible === false || input.communication_policy?.hidden_peer_chat === true || input.communication_policy?.worker_to_worker_direct === true || input.communication_policy?.goal_room_canonical === false) {
326
+ errors.push("pool communication policy must be parent-visible, Goal Room canonical, and not direct hidden peer chat");
327
+ }
328
+ return errors;
329
+ }
330
+
331
+ function normalizedPath(repoRoot: string, path: string): string {
332
+ return resolveRepoPath(repoRoot, path).path.replace(/\/+$/g, "");
333
+ }
334
+
335
+ function pathsOverlap(repoRoot: string, left: string, right: string): boolean {
336
+ const a = normalizedPath(repoRoot, left);
337
+ const b = normalizedPath(repoRoot, right);
338
+ return a === b || a.startsWith(`${b}/`) || b.startsWith(`${a}/`);
339
+ }
340
+
341
+ function pathWithinOwnedPath(repoRoot: string, path: string, ownedPath: string): boolean {
342
+ const candidate = normalizedPath(repoRoot, path);
343
+ const owner = normalizedPath(repoRoot, ownedPath);
344
+ return candidate === owner || candidate.startsWith(`${owner}/`);
345
+ }
346
+
347
+ function pathsCoveredByOwnedPaths(repoRoot: string, paths: string[], ownedPaths: string[]): boolean {
348
+ return paths.every((path) => ownedPaths.some((ownedPath) => pathWithinOwnedPath(repoRoot, path, ownedPath)));
349
+ }
350
+
351
+ function safetyGates(): WorkerPoolSafetyGateRecord {
352
+ return {
353
+ schema: "zob.worker-pool-safety-gates.v1",
354
+ workspaceClaimsChecked: true,
355
+ ownerPathCoverageRequired: true,
356
+ sandboxIsolationRequired: true,
357
+ mergeQueueRequired: true,
358
+ rollbackMetadataRequired: true,
359
+ oracleReviewRequiredForRiskyMerge: true,
360
+ parentOwnedApplyOnly: true,
361
+ productionWritesPerformed: false,
362
+ autoApply: false,
363
+ };
364
+ }
365
+
366
+ function buildAssignmentOverlapConflicts(repoRoot: string, poolId: string, assignments: WorkerPoolAssignmentRecord[]): WorkerPoolConflictRecord[] {
367
+ const conflicts: WorkerPoolConflictRecord[] = [];
368
+ for (let i = 0; i < assignments.length; i += 1) {
369
+ for (let j = i + 1; j < assignments.length; j += 1) {
370
+ const left = assignments[i];
371
+ const right = assignments[j];
372
+ const paths = left.writePaths.filter((path) => right.writePaths.some((candidate) => pathsOverlap(repoRoot, path, candidate)));
373
+ if (paths.length === 0) continue;
374
+ const workerIds = [left.workerId, right.workerId].sort();
375
+ const normalizedPaths = normalizeUnique(paths);
376
+ conflicts.push({
377
+ schema: "zob.worker-pool-conflict.v1",
378
+ type: "assignment_write_overlap",
379
+ poolId,
380
+ workerIds,
381
+ paths: normalizedPaths,
382
+ conflictHash: sha256(JSON.stringify({ type: "assignment_write_overlap", poolId, workerIds, paths: normalizedPaths })),
383
+ parentOwnedResolutionRequired: true,
384
+ writesBlocked: true,
385
+ productionWritesPerformed: false,
386
+ autoApply: false,
387
+ bodyStored: false,
388
+ promptBodiesStored: false,
389
+ outputBodiesStored: false,
390
+ });
391
+ }
392
+ }
393
+ return conflicts;
394
+ }
395
+
396
+ function assignmentOwnClaimCoversPath(repoRoot: string, assignment: WorkerPoolAssignmentRecord, claim: WorkspaceClaimRecord, path: string): boolean {
397
+ return assignment.workspaceClaimIds.includes(claim.claimId) && claim.claimant === assignment.workerId && claim.mode === "write" && claim.paths.some((claimedPath) => pathWithinOwnedPath(repoRoot, path, claimedPath));
398
+ }
399
+
400
+ function workspaceClaimsCoverWriteIntent(repoRoot: string, assignment: WorkerPoolAssignmentRecord): boolean {
401
+ if (assignment.workspaceClaimIds.length === 0) return false;
402
+ const claims = listWorkspaceClaims(repoRoot, { include_expired: false, include_released: false, limit: 100 }) as WorkspaceClaimRecord[];
403
+ return assignment.writePaths.every((path) => claims.some((claim) => assignmentOwnClaimCoversPath(repoRoot, assignment, claim, path)));
404
+ }
405
+
406
+ function buildWorkspaceOverlapConflicts(repoRoot: string, poolId: string, assignments: WorkerPoolAssignmentRecord[]): WorkerPoolConflictRecord[] {
407
+ const claims = listWorkspaceClaims(repoRoot, { include_expired: false, include_released: false, limit: 100 }) as WorkspaceClaimRecord[];
408
+ const conflicts: WorkerPoolConflictRecord[] = [];
409
+ for (const assignment of assignments) {
410
+ assignment.workspaceClaimsCoverWriteIntent = workspaceClaimsCoverWriteIntent(repoRoot, assignment);
411
+ const overlaps = claims.flatMap((claim) => assignment.writePaths
412
+ .filter((path) => claim.paths.some((claimedPath) => pathsOverlap(repoRoot, path, claimedPath)) && !assignmentOwnClaimCoversPath(repoRoot, assignment, claim, path))
413
+ .map((path) => ({ claim, path })));
414
+ if (overlaps.length === 0) continue;
415
+ const claimIds = [...new Set(overlaps.map((overlap) => overlap.claim.claimId))].sort();
416
+ const paths = normalizeUnique(overlaps.map((overlap) => overlap.path));
417
+ conflicts.push({
418
+ schema: "zob.worker-pool-conflict.v1",
419
+ type: "workspace_claim_overlap",
420
+ poolId,
421
+ workerIds: [assignment.workerId, ...claimIds].sort(),
422
+ paths,
423
+ conflictHash: sha256(JSON.stringify({ type: "workspace_claim_overlap", poolId, workerId: assignment.workerId, claimIds, paths })),
424
+ parentOwnedResolutionRequired: true,
425
+ writesBlocked: true,
426
+ productionWritesPerformed: false,
427
+ autoApply: false,
428
+ bodyStored: false,
429
+ promptBodiesStored: false,
430
+ outputBodiesStored: false,
431
+ });
432
+ }
433
+ return conflicts;
434
+ }
435
+
436
+ function buildAssignment(input: WorkerPoolAssignmentInput): WorkerPoolAssignmentRecord {
437
+ const ownedPaths = normalizeUnique(input.owned_paths);
438
+ const writePaths = normalizeUnique(input.write_paths);
439
+ const readAcrossPaths = normalizeUnique(input.read_across_paths);
440
+ return {
441
+ workerId: input.worker_id,
442
+ agentName: input.agent_name,
443
+ ownedPaths,
444
+ ownedPathHashes: ownedPaths.map((path) => sha256(path)),
445
+ writePaths,
446
+ writePathHashes: writePaths.map((path) => sha256(path)),
447
+ readAcrossPaths,
448
+ readAcrossPathHashes: readAcrossPaths.map((path) => sha256(path)),
449
+ readAcrossWriteOverlapJustificationHash: input.read_across_write_overlap_justification_hash ?? null,
450
+ forbiddenPaths: normalizeUnique(input.forbidden_paths),
451
+ todoId: input.todo_id ?? null,
452
+ childGoalId: input.child_goal_id ?? null,
453
+ runId: input.run_id ?? null,
454
+ workspaceClaimIds: normalizeUnique(input.workspace_claim_ids),
455
+ workspaceClaimsCoverWriteIntent: false,
456
+ communicationPolicy: communicationPolicy(input.communication_policy),
457
+ };
458
+ }
459
+
460
+ export function createWorkerPoolPlan(repoRoot: string, definition: TeamDefinition, input: WorkerPoolPlanInput): WorkerPoolPlanRecord {
461
+ const errors = validateWorkerPoolPlanInput(repoRoot, definition, input);
462
+ if (errors.length > 0) throw new Error(errors.join("; "));
463
+ const poolId = input.pool_id ?? newRunId("wpool");
464
+ if (safeFileStem(poolId) !== poolId) throw new Error(`pool_id must be path-safe: ${poolId}`);
465
+ const assignments = input.assignments.map(buildAssignment);
466
+ const conflicts = [...buildAssignmentOverlapConflicts(repoRoot, poolId, assignments), ...buildWorkspaceOverlapConflicts(repoRoot, poolId, assignments)];
467
+ const record: WorkerPoolPlanRecord = {
468
+ schema: "zob.worker-pool-plan.v1",
469
+ poolId,
470
+ goalId: input.goal_id,
471
+ runId: input.run_id ?? null,
472
+ todoId: input.todo_id ?? null,
473
+ owner: input.owner,
474
+ assignments,
475
+ forbiddenPaths: normalizeUnique(input.forbidden_paths),
476
+ communicationPolicy: communicationPolicy(input.communication_policy),
477
+ conflicts,
478
+ status: conflicts.length > 0 ? "blocked_conflict" : "planned",
479
+ safetyGates: safetyGates(),
480
+ parentOwned: true,
481
+ readAcrossWriteByOwner: true,
482
+ productionWritesPerformed: false,
483
+ autoApply: false,
484
+ bodyStored: false,
485
+ promptBodiesStored: false,
486
+ outputBodiesStored: false,
487
+ createdAt: new Date().toISOString(),
488
+ };
489
+ if (hasForbiddenPlaintextKeys(record)) throw new Error("worker pool record would contain forbidden plaintext keys");
490
+ mkdirSync(workerPoolsDir(repoRoot), { recursive: true });
491
+ appendFileSync(plansPath(repoRoot), `${JSON.stringify(record)}\n`, "utf8");
492
+ return record;
493
+ }
494
+
495
+ function readPlans(repoRoot: string): WorkerPoolPlanRecord[] {
496
+ if (!existsSync(plansPath(repoRoot))) return [];
497
+ return readJsonl(plansPath(repoRoot)).filter(isWorkerPoolPlanRecord).map((record) => record as unknown as WorkerPoolPlanRecord);
498
+ }
499
+
500
+ export function listWorkerPoolPlans(repoRoot: string, input: WorkerPoolStatusInput = {}): WorkerPoolPlanRecord[] {
501
+ if (input.goal_id && safeFileStem(input.goal_id) !== input.goal_id) throw new Error(`goal_id must be path-safe: ${input.goal_id}`);
502
+ if (input.pool_id && safeFileStem(input.pool_id) !== input.pool_id) throw new Error(`pool_id must be path-safe: ${input.pool_id}`);
503
+ if (input.run_id && safeFileStem(input.run_id) !== input.run_id) throw new Error(`run_id must be path-safe: ${input.run_id}`);
504
+ const limit = Math.max(1, Math.min(100, Math.floor(input.limit ?? 20)));
505
+ return readPlans(repoRoot)
506
+ .filter((plan) => !input.goal_id || plan.goalId === input.goal_id)
507
+ .filter((plan) => !input.pool_id || plan.poolId === input.pool_id)
508
+ .filter((plan) => !input.run_id || plan.runId === input.run_id)
509
+ .slice(-limit);
510
+ }
511
+
512
+ function validateOwnerRequestAgainstPlan(repoRoot: string, input: WorkerPoolOwnerRequestInput): string[] {
513
+ const plan = readPlans(repoRoot).filter((candidate) => candidate.poolId === input.pool_id && candidate.goalId === input.goal_id).at(-1);
514
+ if (!plan) return [`owner request pool plan not found for ${input.pool_id}`];
515
+ const ownerAssignment = plan.assignments.find((assignment) => assignment.workerId === input.owner_worker);
516
+ if (!ownerAssignment) return [`owner request owner_worker '${input.owner_worker}' is not an assignment owner in pool ${input.pool_id}`];
517
+ const ownerCoverage = [...ownerAssignment.ownedPaths, ...ownerAssignment.writePaths];
518
+ if (!pathsCoveredByOwnedPaths(repoRoot, input.requested_paths, ownerCoverage)) return [`owner request requested_paths must be covered by owner_worker '${input.owner_worker}' owned/write paths`];
519
+ return [];
520
+ }
521
+
522
+ function validateOwnerRequest(repoRoot: string, definition: TeamDefinition, input: WorkerPoolOwnerRequestInput): string[] {
523
+ const errors: string[] = [];
524
+ validateSafeIds({ goal_id: input.goal_id, pool_id: input.pool_id, run_id: input.run_id, todo_id: input.todo_id, request_id: input.request_id }, errors);
525
+ if (!knownRoleIds(definition).has(input.requester)) errors.push(`Unknown owner request requester '${input.requester}'`);
526
+ if (!knownRoleIds(definition).has(input.owner_worker)) errors.push(`Unknown owner request owner_worker '${input.owner_worker}'`);
527
+ if (!SHA256_HEX.test(input.change_hash)) errors.push("owner request change_hash must be sha256 hex");
528
+ if (!SHA256_HEX.test(input.reason_hash)) errors.push("owner request reason_hash must be sha256 hex");
529
+ if (!Array.isArray(input.requested_paths) || input.requested_paths.length === 0) errors.push("owner request requires requested_paths");
530
+ errors.push(...validatePathList(repoRoot, input.requested_paths, "owner request requested_paths"));
531
+ if (Array.isArray(input.requested_paths) && input.requested_paths.length > 0) errors.push(...validateOwnerRequestAgainstPlan(repoRoot, input));
532
+ if (hasForbiddenPlaintextKeys(input)) errors.push("owner request input must not contain raw body/task/prompt/output/content/message/text/rationale/diff/patch keys");
533
+ return errors;
534
+ }
535
+
536
+ export function createWorkerPoolOwnerRequest(repoRoot: string, definition: TeamDefinition, input: WorkerPoolOwnerRequestInput): WorkerPoolOwnerRequestRecord {
537
+ const errors = validateOwnerRequest(repoRoot, definition, input);
538
+ if (errors.length > 0) throw new Error(errors.join("; "));
539
+ const requestId = input.request_id ?? newRunId("ownerreq");
540
+ if (safeFileStem(requestId) !== requestId) throw new Error(`request_id must be path-safe: ${requestId}`);
541
+ const requestedPaths = normalizeUnique(input.requested_paths);
542
+ const goalRoomMessage = appendGoalRoomMessage(repoRoot, definition, {
543
+ goal_id: input.goal_id,
544
+ run_id: input.run_id,
545
+ todo_id: input.todo_id,
546
+ sender: input.requester,
547
+ audience: "parent",
548
+ kind: "OWNER_CHANGE_REQUEST",
549
+ priority: "high",
550
+ body_hash: input.reason_hash,
551
+ task_id: requestId,
552
+ output_hash: input.change_hash,
553
+ evidence_refs: input.evidence_refs,
554
+ artifact_refs: input.artifact_refs,
555
+ requires_parent_action: true,
556
+ metadata: { schema: "zob.worker-pool-owner-request-ref.v1", poolId: input.pool_id, requestId, requester: input.requester, ownerWorker: input.owner_worker, requestedPaths, requestedPathHashes: requestedPaths.map((path) => sha256(path)), planValidation: "covered_by_owner", parentOwnedConflict: false, parentVisible: true, hiddenPeerChat: false, workerToWorkerDirect: false },
557
+ });
558
+ const record: WorkerPoolOwnerRequestRecord = {
559
+ schema: "zob.worker-pool-owner-request.v1",
560
+ requestId,
561
+ poolId: input.pool_id,
562
+ goalId: input.goal_id,
563
+ runId: input.run_id ?? null,
564
+ todoId: input.todo_id ?? null,
565
+ requester: input.requester,
566
+ ownerWorker: input.owner_worker,
567
+ requestedPaths,
568
+ requestedPathHashes: requestedPaths.map((path) => sha256(path)),
569
+ changeHash: input.change_hash,
570
+ reasonHash: input.reason_hash,
571
+ planValidation: "covered_by_owner",
572
+ parentOwnedConflict: false,
573
+ goalRoomMsgId: String(goalRoomMessage.msgId),
574
+ parentVisible: true,
575
+ hiddenPeerChat: false,
576
+ workerToWorkerDirect: false,
577
+ parentOwnedDecisionRequired: true,
578
+ productionWritesPerformed: false,
579
+ autoApply: false,
580
+ bodyStored: false,
581
+ promptBodiesStored: false,
582
+ outputBodiesStored: false,
583
+ createdAt: new Date().toISOString(),
584
+ };
585
+ if (hasForbiddenPlaintextKeys(record)) throw new Error("worker pool owner request record would contain forbidden plaintext keys");
586
+ mkdirSync(workerPoolsDir(repoRoot), { recursive: true });
587
+ appendFileSync(requestsPath(repoRoot), `${JSON.stringify(record)}\n`, "utf8");
588
+ return record;
589
+ }
590
+
591
+ function validateOwnerDecision(definition: TeamDefinition, input: WorkerPoolOwnerDecisionInput): string[] {
592
+ const errors: string[] = [];
593
+ validateSafeIds({ goal_id: input.goal_id, pool_id: input.pool_id, run_id: input.run_id, todo_id: input.todo_id, request_id: input.request_id }, errors);
594
+ if (!knownRoleIds(definition).has(input.decided_by)) errors.push(`Unknown owner decision decided_by '${input.decided_by}'`);
595
+ if (!knownRoleIds(definition).has(input.owner_worker)) errors.push(`Unknown owner decision owner_worker '${input.owner_worker}'`);
596
+ if (input.requester && !knownRoleIds(definition).has(input.requester)) errors.push(`Unknown owner decision requester '${input.requester}'`);
597
+ if (!DECISIONS.has(input.decision)) errors.push(`Invalid owner decision: ${input.decision}`);
598
+ if (!SHA256_HEX.test(input.decision_hash)) errors.push("owner decision decision_hash must be sha256 hex");
599
+ if (hasForbiddenPlaintextKeys(input)) errors.push("owner decision input must not contain raw body/task/prompt/output/content/message/text/rationale/diff/patch keys");
600
+ return errors;
601
+ }
602
+
603
+ export function createWorkerPoolOwnerDecision(repoRoot: string, definition: TeamDefinition, input: WorkerPoolOwnerDecisionInput): WorkerPoolOwnerDecisionRecord {
604
+ const errors = validateOwnerDecision(definition, input);
605
+ if (errors.length > 0) throw new Error(errors.join("; "));
606
+ const decisionId = newRunId("ownerdec");
607
+ const goalRoomMessage = appendGoalRoomMessage(repoRoot, definition, {
608
+ goal_id: input.goal_id,
609
+ run_id: input.run_id,
610
+ todo_id: input.todo_id,
611
+ sender: input.decided_by,
612
+ audience: "parent",
613
+ kind: "OWNER_CHANGE_DECISION",
614
+ priority: input.decision === "approved" || input.decision === "owner_will_handle" ? "high" : "normal",
615
+ body_hash: input.decision_hash,
616
+ task_id: input.request_id,
617
+ evidence_refs: input.evidence_refs,
618
+ artifact_refs: input.artifact_refs,
619
+ requires_parent_action: input.decision === "needs_parent",
620
+ metadata: { schema: "zob.worker-pool-owner-decision-ref.v1", poolId: input.pool_id, requestId: input.request_id, decisionId, decidedBy: input.decided_by, ownerWorker: input.owner_worker, requester: input.requester ?? null, decision: input.decision, parentVisible: true, hiddenPeerChat: false, workerToWorkerDirect: false },
621
+ });
622
+ const record: WorkerPoolOwnerDecisionRecord = {
623
+ schema: "zob.worker-pool-owner-decision.v1",
624
+ decisionId,
625
+ requestId: input.request_id,
626
+ poolId: input.pool_id,
627
+ goalId: input.goal_id,
628
+ runId: input.run_id ?? null,
629
+ todoId: input.todo_id ?? null,
630
+ decidedBy: input.decided_by,
631
+ ownerWorker: input.owner_worker,
632
+ requester: input.requester ?? null,
633
+ decision: input.decision,
634
+ decisionHash: input.decision_hash,
635
+ goalRoomMsgId: String(goalRoomMessage.msgId),
636
+ parentVisible: true,
637
+ hiddenPeerChat: false,
638
+ workerToWorkerDirect: false,
639
+ parentOwnedActions: true,
640
+ productionWritesPerformed: false,
641
+ autoApply: false,
642
+ bodyStored: false,
643
+ promptBodiesStored: false,
644
+ outputBodiesStored: false,
645
+ createdAt: new Date().toISOString(),
646
+ };
647
+ if (hasForbiddenPlaintextKeys(record)) throw new Error("worker pool owner decision record would contain forbidden plaintext keys");
648
+ mkdirSync(workerPoolsDir(repoRoot), { recursive: true });
649
+ appendFileSync(decisionsPath(repoRoot), `${JSON.stringify(record)}\n`, "utf8");
650
+ return record;
651
+ }
652
+
653
+ export function workerPoolBodyFreeViolations(value: unknown): string[] {
654
+ const violations: string[] = [];
655
+ const visit = (item: unknown, path: string): void => {
656
+ if (!item || typeof item !== "object") return;
657
+ if (Array.isArray(item)) {
658
+ item.forEach((child, index) => visit(child, `${path}[${index}]`));
659
+ return;
660
+ }
661
+ for (const [key, child] of Object.entries(item as Record<string, unknown>)) {
662
+ if (FORBIDDEN_PLAINTEXT_KEYS.has(key)) violations.push(`${path}.${key}`);
663
+ visit(child, `${path}.${key}`);
664
+ }
665
+ };
666
+ visit(value, "root");
667
+ return violations;
668
+ }
669
+
670
+ export function isWorkerPoolPlanRecord(value: unknown): value is WorkerPoolPlanRecord {
671
+ return isRecord(value) && value.schema === "zob.worker-pool-plan.v1" && typeof value.poolId === "string" && value.parentOwned === true && value.productionWritesPerformed === false && value.autoApply === false && value.bodyStored === false;
672
+ }