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,107 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import { sha256 } from "../utils/hashing.js";
5
+ import { isRecord } from "../utils/records.js";
6
+ import { advancePromotionCandidate, createPromotionCandidate, promotionCandidateDir, promotionCandidateRef, validatePromotionCandidate, writePromotionCandidate } from "./candidate.js";
7
+ import type { PromotionCandidateRecord } from "./types.js";
8
+
9
+ export interface FactoryPromotionInput {
10
+ candidateId?: string;
11
+ runId: string;
12
+ goalId?: string;
13
+ todoId?: string;
14
+ sourceRef: string;
15
+ factoryName: string;
16
+ manifest: Record<string, unknown>;
17
+ }
18
+
19
+ function safeFactoryName(value: string): boolean {
20
+ return /^[a-zA-Z0-9._-]+$/.test(value) && !value.includes("..") && value.length > 0;
21
+ }
22
+
23
+ function hasForbiddenRawKeys(value: unknown): boolean {
24
+ if (!value || typeof value !== "object") return false;
25
+ if (Array.isArray(value)) return value.some(hasForbiddenRawKeys);
26
+ return Object.entries(value as Record<string, unknown>).some(([key, child]) => ["body", "prompt", "output", "content", "message", "text", "rationale", "diff", "patch", "transcript"].includes(key) || hasForbiddenRawKeys(child));
27
+ }
28
+
29
+ export function prepareFactoryPromotion(repoRoot: string, input: FactoryPromotionInput): { candidate: PromotionCandidateRecord; manifestRef: string; validationRef: string } {
30
+ if (!safeFactoryName(input.factoryName)) throw new Error(`Unsafe factory name: ${input.factoryName}`);
31
+ if (hasForbiddenRawKeys(input.manifest)) throw new Error("factory promotion manifest metadata must be body-free/hash-only");
32
+ const candidate = createPromotionCandidate({
33
+ candidateId: input.candidateId,
34
+ kind: "factory",
35
+ runId: input.runId,
36
+ goalId: input.goalId,
37
+ todoId: input.todoId,
38
+ sourceRef: input.sourceRef,
39
+ allowedPaths: [`.pi/factories/${input.factoryName}`, `reports/factory-runs/${input.factoryName}`],
40
+ changedPaths: [`.pi/factories/${input.factoryName}/manifest.json`],
41
+ comsThreadRef: input.candidateId ? promotionCandidateRef(input.candidateId, "promotion-coms-thread.json") : undefined,
42
+ metadata: { lane: "factory", factoryName: input.factoryName },
43
+ });
44
+ const candidateDir = promotionCandidateDir(repoRoot, candidate.candidateId);
45
+ mkdirSync(join(candidateDir, "factory"), { recursive: true });
46
+ const manifestRecord = {
47
+ schema: "zob.factory-promotion-manifest-draft.v1",
48
+ candidateId: candidate.candidateId,
49
+ factoryName: input.factoryName,
50
+ manifestHash: sha256(JSON.stringify(input.manifest)),
51
+ manifestMetadata: input.manifest,
52
+ requiresSmoke: true,
53
+ requiresPilot: true,
54
+ requiresOracle: true,
55
+ requiresHumanApproval: true,
56
+ activationSentinelWritten: false,
57
+ bodyStored: false,
58
+ promptBodiesStored: false,
59
+ outputBodiesStored: false,
60
+ };
61
+ const manifestRef = promotionCandidateRef(candidate.candidateId, "factory/manifest-draft.json");
62
+ writeFileSync(join(repoRoot, manifestRef), JSON.stringify(manifestRecord, null, 2), "utf8");
63
+ const validationErrors = validateFactoryPromotionManifest(manifestRecord);
64
+ const validationRef = promotionCandidateRef(candidate.candidateId, "factory/validation.json");
65
+ writeFileSync(join(repoRoot, validationRef), JSON.stringify({ schema: "zob.factory-promotion-validation.v1", candidateId: candidate.candidateId, valid: validationErrors.length === 0, errors: validationErrors, bodyStored: false, promptBodiesStored: false, outputBodiesStored: false }, null, 2), "utf8");
66
+ const prepared = advancePromotionCandidate(repoRoot, { ...candidate, comsThreadRef: promotionCandidateRef(candidate.candidateId, "promotion-coms-thread.json") }, { toStatus: "prepared", preparedArtifactRef: manifestRef, validationRefs: validationErrors.length === 0 ? [validationRef] : [] });
67
+ writePromotionCandidate(repoRoot, prepared);
68
+ return { candidate: prepared, manifestRef, validationRef };
69
+ }
70
+
71
+ export function activateFactoryPromotionInQuarantine(repoRoot: string, candidate: PromotionCandidateRecord): { candidate: PromotionCandidateRecord; sentinelRef: string } {
72
+ if (candidate.kind !== "factory") throw new Error("candidate kind must be factory");
73
+ if (candidate.status !== "approved") throw new Error("factory activation requires approved candidate");
74
+ const preflightErrors = validateFactoryPromotionCandidate(repoRoot, candidate);
75
+ if (preflightErrors.length > 0) throw new Error(preflightErrors.join("; "));
76
+ const applied = advancePromotionCandidate(repoRoot, candidate, { toStatus: "applied", applyScope: "quarantine_test_directory", applyPerformed: true });
77
+ const sentinelRef = promotionCandidateRef(candidate.candidateId, "factory/ACTIVATED.sentinel");
78
+ writeFileSync(join(repoRoot, sentinelRef), `factory promotion activated in quarantine for ${candidate.candidateId}\n`, "utf8");
79
+ writePromotionCandidate(repoRoot, applied);
80
+ return { candidate: applied, sentinelRef };
81
+ }
82
+
83
+ export function validateFactoryPromotionManifest(artifact: unknown): string[] {
84
+ const errors: string[] = [];
85
+ if (!isRecord(artifact)) return ["factory promotion manifest must be an object"];
86
+ if (artifact.schema !== "zob.factory-promotion-manifest-draft.v1") errors.push("factory promotion manifest schema mismatch");
87
+ if (artifact.requiresSmoke !== true || artifact.requiresPilot !== true || artifact.requiresOracle !== true || artifact.requiresHumanApproval !== true) errors.push("factory promotion requires smoke, pilot, oracle, and human approval gates");
88
+ if (artifact.activationSentinelWritten !== false) errors.push("activation sentinel must not be written during preparation");
89
+ if (artifact.bodyStored !== false || artifact.promptBodiesStored !== false || artifact.outputBodiesStored !== false) errors.push("factory promotion manifest must keep body flags false");
90
+ if (hasForbiddenRawKeys(artifact)) errors.push("factory promotion manifest must not include raw body-like keys");
91
+ return errors;
92
+ }
93
+
94
+ export function validateFactoryPromotionCandidate(repoRoot: string, candidate: PromotionCandidateRecord): string[] {
95
+ const errors = validatePromotionCandidate(repoRoot, candidate);
96
+ if (candidate.kind !== "factory") errors.push("candidate kind must be factory");
97
+ if (candidate.productionWritesPerformed !== false || candidate.autoApply !== false) errors.push("factory candidate must not perform production writes or auto-apply");
98
+ if (["oracle_reviewed", "approved", "applied"].includes(candidate.status)) {
99
+ const smokeRef = candidate.validationRefs.find((ref) => ref.endsWith("/factory/smoke.json") || ref.endsWith("factory/smoke.json"));
100
+ const pilotRef = candidate.validationRefs.find((ref) => ref.endsWith("/factory/pilot.json") || ref.endsWith("factory/pilot.json"));
101
+ if (!smokeRef) errors.push("factory promotion requires persisted smoke ref before oracle/approval/apply");
102
+ else if (!existsSync(join(repoRoot, smokeRef))) errors.push(`factory smoke ref does not exist: ${smokeRef}`);
103
+ if (!pilotRef) errors.push("factory promotion requires persisted pilot ref before oracle/approval/apply");
104
+ else if (!existsSync(join(repoRoot, pilotRef))) errors.push(`factory pilot ref does not exist: ${pilotRef}`);
105
+ }
106
+ return errors;
107
+ }
@@ -0,0 +1,2 @@
1
+ export { appendPromotionLedger, writePromotionCandidate } from "./candidate.js";
2
+ export { writePromotionComsThread } from "./coms.js";
@@ -0,0 +1,151 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ import { sha256 } from "../utils/hashing.js";
5
+ import { safeFileStem } from "../utils/paths.js";
6
+ import { parseJsonFile } from "../utils/json.js";
7
+ import { isRecord } from "../utils/records.js";
8
+ import { advancePromotionCandidate, createPromotionCandidate, promotionCandidateDir, promotionCandidateRef, validatePromotionCandidate, writePromotionCandidate } from "./candidate.js";
9
+ import type { PromotionCandidateRecord } from "./types.js";
10
+
11
+ export interface TempAgentCardPromotionInput {
12
+ candidateId?: string;
13
+ runId: string;
14
+ goalId?: string;
15
+ todoId?: string;
16
+ sourceRef: string;
17
+ agentName: string;
18
+ description: string;
19
+ allowedTools: string[];
20
+ outputContract: string;
21
+ scope: string;
22
+ mustDo: string[];
23
+ mustNotDo: string[];
24
+ writeToolsGate?: boolean;
25
+ }
26
+
27
+ const KNOWN_TOOLS = new Set(["read", "grep", "find", "ls", "bash", "edit", "write", "delegate_agent", "delegate_task", "zob_coms_send", "zob_goal_room_send", "zob_governed_request_extract"]);
28
+ const WRITE_TOOLS = new Set(["bash", "edit", "write"]);
29
+
30
+ export function validateTempAgentCardForPromotion(repoRoot: string, input: TempAgentCardPromotionInput): string[] {
31
+ const errors: string[] = [];
32
+ if (safeFileStem(input.agentName) !== input.agentName) errors.push("temp agent name must be path-safe and equal to its safe stem");
33
+ if (!input.description || input.description.trim().length < 10) errors.push("temp agent description is required");
34
+ if (!Array.isArray(input.allowedTools) || input.allowedTools.length === 0) errors.push("temp agent allowedTools are required");
35
+ for (const tool of input.allowedTools ?? []) {
36
+ if (!KNOWN_TOOLS.has(tool)) errors.push(`unknown temp agent tool: ${tool}`);
37
+ if (WRITE_TOOLS.has(tool) && input.writeToolsGate !== true) errors.push(`write-capable tool requires explicit writeToolsGate: ${tool}`);
38
+ }
39
+ if (!/^[a-z0-9._-]+\.v\d+$/i.test(input.outputContract)) errors.push("outputContract must be a safe contract id like name.v1");
40
+ if (!existsSync(join(repoRoot, ".pi", "output-contracts", `${input.outputContract}.json`))) errors.push(`output contract not found: ${input.outputContract}`);
41
+ if (!input.scope || input.scope.trim().length === 0) errors.push("temp agent scope is required");
42
+ if (!Array.isArray(input.mustDo) || input.mustDo.length === 0) errors.push("mustDo is required");
43
+ if (!Array.isArray(input.mustNotDo) || input.mustNotDo.length === 0) errors.push("mustNotDo is required");
44
+ return errors;
45
+ }
46
+
47
+ function renderAgentDraft(input: TempAgentCardPromotionInput): string {
48
+ return [
49
+ `# ${input.agentName}`,
50
+ "",
51
+ input.description,
52
+ "",
53
+ "## Scope",
54
+ input.scope,
55
+ "",
56
+ "## Tools",
57
+ input.allowedTools.map((tool) => `- ${tool}`).join("\n"),
58
+ "",
59
+ "## Output contract",
60
+ input.outputContract,
61
+ "",
62
+ "## MUST DO",
63
+ input.mustDo.map((item) => `- ${item}`).join("\n"),
64
+ "",
65
+ "## MUST NOT",
66
+ input.mustNotDo.map((item) => `- ${item}`).join("\n"),
67
+ "",
68
+ "## Persistence policy",
69
+ "This draft is quarantined until promotion approval, smoke validation, and oracle PASS/no_ship=false.",
70
+ ].join("\n");
71
+ }
72
+
73
+ export function prepareTempAgentPromotion(repoRoot: string, input: TempAgentCardPromotionInput): { candidate: PromotionCandidateRecord; preparedArtifactRef: string; draftRef: string; validationRef: string } {
74
+ const cardErrors = validateTempAgentCardForPromotion(repoRoot, input);
75
+ if (cardErrors.length > 0) throw new Error(cardErrors.join("; "));
76
+ const candidate = createPromotionCandidate({
77
+ candidateId: input.candidateId,
78
+ kind: "temp_agent",
79
+ runId: input.runId,
80
+ goalId: input.goalId,
81
+ todoId: input.todoId,
82
+ sourceRef: input.sourceRef,
83
+ allowedPaths: [".pi/agents"],
84
+ changedPaths: [`.pi/agents/${input.agentName}.md`],
85
+ comsThreadRef: input.candidateId ? promotionCandidateRef(input.candidateId, "promotion-coms-thread.json") : undefined,
86
+ metadata: { lane: "temp_agent", agentName: input.agentName, outputContract: input.outputContract },
87
+ });
88
+ const candidateDir = promotionCandidateDir(repoRoot, candidate.candidateId);
89
+ const draftText = renderAgentDraft(input);
90
+ const draftRef = promotionCandidateRef(candidate.candidateId, `agents/${input.agentName}.md`);
91
+ mkdirSync(join(candidateDir, "agents"), { recursive: true });
92
+ writeFileSync(join(repoRoot, draftRef), draftText, "utf8");
93
+ const preparedArtifact = {
94
+ schema: "zob.temp-agent-promotion-prepared.v1",
95
+ candidateId: candidate.candidateId,
96
+ agentName: input.agentName,
97
+ draftRef,
98
+ draftHash: sha256(draftText),
99
+ allowedTools: input.allowedTools,
100
+ outputContract: input.outputContract,
101
+ durableAgentWritePerformed: false,
102
+ catalogSmokeRequired: true,
103
+ bodyStored: false,
104
+ promptBodiesStored: false,
105
+ outputBodiesStored: false,
106
+ };
107
+ const preparedArtifactRef = promotionCandidateRef(candidate.candidateId, "temp-agent/prepared.json");
108
+ mkdirSync(join(candidateDir, "temp-agent"), { recursive: true });
109
+ writeFileSync(join(repoRoot, preparedArtifactRef), JSON.stringify(preparedArtifact, null, 2), "utf8");
110
+ const validationErrors = validateTempAgentPromotionArtifact(preparedArtifact);
111
+ const validationRef = promotionCandidateRef(candidate.candidateId, "temp-agent/validation.json");
112
+ writeFileSync(join(repoRoot, validationRef), JSON.stringify({ schema: "zob.temp-agent-promotion-validation.v1", candidateId: candidate.candidateId, valid: validationErrors.length === 0, errors: validationErrors, bodyStored: false, promptBodiesStored: false, outputBodiesStored: false }, null, 2), "utf8");
113
+ const prepared = advancePromotionCandidate(repoRoot, { ...candidate, comsThreadRef: promotionCandidateRef(candidate.candidateId, "promotion-coms-thread.json") }, { toStatus: "prepared", preparedArtifactRef, validationRefs: validationErrors.length === 0 ? [validationRef] : [] });
114
+ writePromotionCandidate(repoRoot, prepared);
115
+ return { candidate: prepared, preparedArtifactRef, draftRef, validationRef };
116
+ }
117
+
118
+ export function validateTempAgentPromotionArtifact(artifact: unknown): string[] {
119
+ const errors: string[] = [];
120
+ if (!isRecord(artifact)) return ["temp-agent promotion artifact must be an object"];
121
+ if (artifact.schema !== "zob.temp-agent-promotion-prepared.v1") errors.push("temp-agent promotion artifact schema mismatch");
122
+ if (typeof artifact.agentName !== "string" || safeFileStem(artifact.agentName) !== artifact.agentName) errors.push("agentName must be safe");
123
+ if (artifact.durableAgentWritePerformed !== false) errors.push("temp-agent promotion must not perform durable agent write during preparation");
124
+ if (artifact.bodyStored !== false || artifact.promptBodiesStored !== false || artifact.outputBodiesStored !== false) errors.push("temp-agent promotion artifact must keep body flags false");
125
+ if (!Array.isArray(artifact.allowedTools) || artifact.allowedTools.some((tool) => typeof tool !== "string")) errors.push("allowedTools must be string array");
126
+ return errors;
127
+ }
128
+
129
+ export function applyTempAgentPromotionInQuarantine(repoRoot: string, candidate: PromotionCandidateRecord): { candidate: PromotionCandidateRecord; appliedAgentRef: string; appliedMetadataRef: string } {
130
+ if (candidate.kind !== "temp_agent") throw new Error("candidate kind must be temp_agent");
131
+ if (candidate.status !== "approved") throw new Error("temp-agent quarantine apply requires approved candidate");
132
+ if (!candidate.preparedArtifactRef) throw new Error("temp-agent quarantine apply requires preparedArtifactRef");
133
+ const prepared = parseJsonFile(join(repoRoot, candidate.preparedArtifactRef));
134
+ if (!isRecord(prepared) || typeof prepared.agentName !== "string" || typeof prepared.draftRef !== "string") throw new Error("temp-agent prepared artifact missing agentName/draftRef");
135
+ const draftText = readFileSync(join(repoRoot, prepared.draftRef), "utf8");
136
+ const appliedAgentRef = promotionCandidateRef(candidate.candidateId, `temp-agent/applied-test-workspace/.pi/agents/${safeFileStem(prepared.agentName)}.md`);
137
+ mkdirSync(join(repoRoot, promotionCandidateRef(candidate.candidateId, "temp-agent/applied-test-workspace/.pi/agents")), { recursive: true });
138
+ writeFileSync(join(repoRoot, appliedAgentRef), draftText, "utf8");
139
+ const appliedMetadataRef = promotionCandidateRef(candidate.candidateId, "temp-agent/applied-test-workspace/apply-metadata.json");
140
+ writeFileSync(join(repoRoot, appliedMetadataRef), JSON.stringify({ schema: "zob.temp-agent-quarantine-apply.v1", candidateId: candidate.candidateId, appliedAgentRef, productionWritesPerformed: false, autoApply: false, bodyStored: false, promptBodiesStored: false, outputBodiesStored: false }, null, 2), "utf8");
141
+ const applied = advancePromotionCandidate(repoRoot, candidate, { toStatus: "applied", applyScope: "quarantine_test_directory", applyPerformed: true });
142
+ writePromotionCandidate(repoRoot, applied);
143
+ return { candidate: applied, appliedAgentRef, appliedMetadataRef };
144
+ }
145
+
146
+ export function validateTempAgentPromotionCandidate(repoRoot: string, candidate: PromotionCandidateRecord): string[] {
147
+ const errors = validatePromotionCandidate(repoRoot, candidate);
148
+ if (candidate.kind !== "temp_agent") errors.push("candidate kind must be temp_agent");
149
+ if (candidate.productionWritesPerformed !== false || candidate.autoApply !== false) errors.push("temp-agent candidate must not auto-apply production writes");
150
+ return errors;
151
+ }
@@ -0,0 +1,149 @@
1
+ export const PROMOTION_KINDS = ["documentation_writeback", "temp_agent", "factory", "write_lane"] as const;
2
+ export type PromotionKind = typeof PROMOTION_KINDS[number];
3
+
4
+ export const PROMOTION_STATUSES = ["proposal", "prepared", "validated", "oracle_reviewed", "approved", "applied", "rejected", "blocked"] as const;
5
+ export type PromotionStatus = typeof PROMOTION_STATUSES[number];
6
+
7
+ export const PROMOTION_APPLY_SCOPES = ["none", "manual_apply_only", "quarantine_test_directory"] as const;
8
+ export type PromotionApplyScope = typeof PROMOTION_APPLY_SCOPES[number];
9
+
10
+ export interface PromotionGates {
11
+ comsThreadRequired: boolean;
12
+ sandboxRequired: boolean;
13
+ validationRequired: boolean;
14
+ oracleRequired: boolean;
15
+ humanApprovalRequired: boolean;
16
+ rollbackRequired: boolean;
17
+ }
18
+
19
+ export interface PromotionCandidateInput {
20
+ candidateId?: string;
21
+ kind: PromotionKind;
22
+ runId: string;
23
+ goalId?: string;
24
+ todoId?: string;
25
+ sourceRef: string;
26
+ sourceHash?: string;
27
+ comsThreadRef?: string;
28
+ goalRoomMessageRefs?: string[];
29
+ preparedArtifactRef?: string | null;
30
+ validationRefs?: string[];
31
+ oracleReviewRef?: string | null;
32
+ oracleVerdict?: "PASS" | "WARN" | "FAIL" | null;
33
+ oracleNoShip?: boolean | null;
34
+ approvalRef?: string | null;
35
+ rollbackRef?: string | null;
36
+ changedPaths?: string[];
37
+ allowedPaths?: string[];
38
+ forbiddenPaths?: string[];
39
+ gates?: Partial<PromotionGates>;
40
+ applyScope?: PromotionApplyScope;
41
+ metadata?: Record<string, unknown>;
42
+ }
43
+
44
+ export interface PromotionCandidateRecord {
45
+ schema: "zob.promotion-candidate.v1";
46
+ candidateId: string;
47
+ kind: PromotionKind;
48
+ runId: string;
49
+ goalId: string | null;
50
+ todoId: string | null;
51
+ status: PromotionStatus;
52
+ sourceRef: string;
53
+ sourceHash: string | null;
54
+ preparedArtifactRef: string | null;
55
+ validationRefs: string[];
56
+ oracleReviewRef: string | null;
57
+ oracleVerdict: "PASS" | "WARN" | "FAIL" | null;
58
+ oracleNoShip: boolean | null;
59
+ approvalRef: string | null;
60
+ rollbackRef: string | null;
61
+ comsThreadRef: string | null;
62
+ goalRoomMessageRefs: string[];
63
+ changedPaths: string[];
64
+ changedPathHashes: string[];
65
+ allowedPaths: string[];
66
+ forbiddenPaths: string[];
67
+ gates: PromotionGates;
68
+ applyScope: PromotionApplyScope;
69
+ applyPerformed: boolean;
70
+ productionWritesPerformed: false;
71
+ autoApply: false;
72
+ parentOwned: true;
73
+ bodyStored: false;
74
+ promptBodiesStored: false;
75
+ outputBodiesStored: false;
76
+ metadata: Record<string, unknown>;
77
+ createdAt: string;
78
+ updatedAt: string;
79
+ }
80
+
81
+ export interface PromotionTransitionInput {
82
+ toStatus: PromotionStatus;
83
+ preparedArtifactRef?: string;
84
+ validationRefs?: string[];
85
+ oracleReviewRef?: string;
86
+ oracleVerdict?: "PASS" | "WARN" | "FAIL";
87
+ oracleNoShip?: boolean;
88
+ approvalRef?: string;
89
+ rollbackRef?: string;
90
+ goalRoomMessageRefs?: string[];
91
+ applyScope?: PromotionApplyScope;
92
+ applyPerformed?: boolean;
93
+ metadata?: Record<string, unknown>;
94
+ }
95
+
96
+ export interface PromotionComsMessageRef {
97
+ msgId: string;
98
+ kind: "STATUS_UPDATE" | "FINDING" | "RISK" | "BLOCKER" | "NO_SHIP_ALERT" | "CONTEXT_REQUEST" | "DELEGATION_REQUEST" | "ORACLE_REQUEST" | "QUESTION" | "ANSWER";
99
+ sender: string;
100
+ status: "queued" | "acked" | "running" | "completed" | "blocked" | "timeout" | "stale" | "offline";
101
+ bodyHash: string;
102
+ outputHash?: string | null;
103
+ artifactRefs: string[];
104
+ evidenceRefs: string[];
105
+ requiresParentAction: boolean;
106
+ countsAsCompletion: boolean;
107
+ parentVisible: true;
108
+ hiddenPeerChat: false;
109
+ workerToWorkerDirect: false;
110
+ bodyStored: false;
111
+ promptBodiesStored: false;
112
+ outputBodiesStored: false;
113
+ }
114
+
115
+ export interface PromotionComsThreadInput {
116
+ threadId?: string;
117
+ goalId: string;
118
+ todoId?: string;
119
+ candidateId: string;
120
+ kind: PromotionKind;
121
+ messageRefs?: PromotionComsMessageRef[];
122
+ requiredAcks?: string[];
123
+ stalePolicy?: "stale_blocks_completion";
124
+ }
125
+
126
+ export interface PromotionComsThreadRecord {
127
+ schema: "zob.promotion-coms-thread.v1";
128
+ threadId: string;
129
+ goalId: string;
130
+ todoId: string | null;
131
+ candidateId: string;
132
+ kind: PromotionKind;
133
+ messageRefs: PromotionComsMessageRef[];
134
+ requiredAcks: string[];
135
+ stalePolicy: "stale_blocks_completion";
136
+ parentVisible: true;
137
+ parentOwnedActions: true;
138
+ hiddenPeerChat: false;
139
+ bodyStored: false;
140
+ promptBodiesStored: false;
141
+ outputBodiesStored: false;
142
+ createdAt: string;
143
+ updatedAt: string;
144
+ }
145
+
146
+ export interface PromotionValidationResult {
147
+ valid: boolean;
148
+ errors: string[];
149
+ }
@@ -0,0 +1,6 @@
1
+ export { validatePromotionCandidate, transitionAllowed } from "./candidate.js";
2
+ export { validatePromotionComsMessageRef, validatePromotionComsReadiness, validatePromotionComsThread } from "./coms.js";
3
+ export { validateDocumentationPromotion, validateDocumentationPromotionCandidate } from "./documentation.js";
4
+ export { validateFactoryPromotionCandidate, validateFactoryPromotionManifest } from "./factory.js";
5
+ export { validateTempAgentCardForPromotion, validateTempAgentPromotionArtifact, validateTempAgentPromotionCandidate } from "./temp-agent.js";
6
+ export { validateWriteLaneDiffMetadata, validateWriteLanePromotionCandidate } from "./write-lane.js";
@@ -0,0 +1,162 @@
1
+ import { mkdirSync, writeFileSync } from "node:fs";
2
+ import { dirname, join, resolve } from "node:path";
3
+
4
+ import { sha256 } from "../utils/hashing.js";
5
+ import { safeFileStem } from "../utils/paths.js";
6
+ import { isRecord } from "../utils/records.js";
7
+ import { advancePromotionCandidate, createPromotionCandidate, promotionCandidateDir, promotionCandidateRef, validatePromotionCandidate, writePromotionCandidate } from "./candidate.js";
8
+ import type { PromotionCandidateRecord } from "./types.js";
9
+
10
+ export interface WriteLaneChangeInput {
11
+ path: string;
12
+ draftText: string;
13
+ }
14
+
15
+ export interface PrepareWriteLanePromotionInput {
16
+ candidateId?: string;
17
+ runId: string;
18
+ goalId?: string;
19
+ todoId?: string;
20
+ sourceRef: string;
21
+ allowedPaths: string[];
22
+ forbiddenPaths?: string[];
23
+ changes: WriteLaneChangeInput[];
24
+ }
25
+
26
+ function validateLogicalPath(path: string): string[] {
27
+ const errors: string[] = [];
28
+ if (typeof path !== "string" || path.trim().length === 0) return ["path must be non-empty"];
29
+ if (path.startsWith("/") || path.includes("..") || path.includes("\\") || path.includes("\0")) errors.push(`path must be safe relative: ${path}`);
30
+ if (/(^|\/)\.env($|[./])|(^|\/)(\.ssh|\.aws)(\/|$)|secret|credential|\.pem$|\.p12$|\.pfx$/i.test(path)) errors.push(`path must not reference secrets: ${path}`);
31
+ return errors;
32
+ }
33
+
34
+ function insideAnyLogical(child: string, parents: string[]): boolean {
35
+ const c = child.replace(/\/+$/g, "");
36
+ return parents.some((parent) => {
37
+ const p = parent.replace(/\/+$/g, "");
38
+ return c === p || c.startsWith(`${p}/`);
39
+ });
40
+ }
41
+
42
+ function pathMatchesForbidden(path: string, forbiddenPaths: string[]): boolean {
43
+ return forbiddenPaths.some((forbidden) => path === forbidden || path.startsWith(`${forbidden.replace(/\/+$/g, "")}/`) || new RegExp(forbidden.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*")).test(path));
44
+ }
45
+
46
+ export function prepareWriteLanePromotion(repoRoot: string, input: PrepareWriteLanePromotionInput): { candidate: PromotionCandidateRecord; sandboxRootRef: string; diffMetadataRef: string; rollbackRef: string; validationRef: string } {
47
+ if (!Array.isArray(input.allowedPaths) || input.allowedPaths.length === 0) throw new Error("write lane requires explicit allowedPaths");
48
+ const pathErrors = [
49
+ ...input.allowedPaths.flatMap(validateLogicalPath),
50
+ ...(input.forbiddenPaths ?? []).flatMap(validateLogicalPath),
51
+ ...input.changes.flatMap((change) => validateLogicalPath(change.path)),
52
+ ];
53
+ for (const change of input.changes) {
54
+ if (!insideAnyLogical(change.path, input.allowedPaths)) pathErrors.push(`write lane change outside allowedPaths: ${change.path}`);
55
+ if (pathMatchesForbidden(change.path, input.forbiddenPaths ?? [])) pathErrors.push(`write lane change matches forbiddenPaths: ${change.path}`);
56
+ }
57
+ if (pathErrors.length > 0) throw new Error(pathErrors.join("; "));
58
+ const preliminary = createPromotionCandidate({
59
+ candidateId: input.candidateId,
60
+ kind: "write_lane",
61
+ runId: input.runId,
62
+ goalId: input.goalId,
63
+ todoId: input.todoId,
64
+ sourceRef: input.sourceRef,
65
+ comsThreadRef: input.candidateId ? promotionCandidateRef(input.candidateId, "promotion-coms-thread.json") : undefined,
66
+ metadata: { lane: "write_lane", logicalAllowedPaths: input.allowedPaths, logicalForbiddenPaths: input.forbiddenPaths ?? [] },
67
+ });
68
+ const sandboxRootRef = promotionCandidateRef(preliminary.candidateId, "write-lane/sandbox");
69
+ const sandboxRoot = join(repoRoot, sandboxRootRef);
70
+ const changedPaths: string[] = [];
71
+ const fileRecords = input.changes.map((change) => {
72
+ const safeParts = change.path.split("/").map((part) => safeFileStem(part));
73
+ const relativeSandboxPath = safeParts.join("/");
74
+ const targetRef = `${sandboxRootRef}/${relativeSandboxPath}`;
75
+ const targetPath = join(repoRoot, targetRef);
76
+ const resolvedTarget = resolve(targetPath);
77
+ const resolvedSandbox = resolve(sandboxRoot);
78
+ if (resolvedTarget !== resolvedSandbox && !resolvedTarget.startsWith(`${resolvedSandbox}/`)) throw new Error(`sandbox write escaped sandbox root: ${change.path}`);
79
+ mkdirSync(dirname(targetPath), { recursive: true });
80
+ writeFileSync(targetPath, change.draftText, "utf8");
81
+ changedPaths.push(targetRef);
82
+ return {
83
+ logicalPath: change.path,
84
+ sandboxRef: targetRef,
85
+ contentHash: sha256(change.draftText),
86
+ bodyStored: false,
87
+ };
88
+ });
89
+ const diffHash = sha256(JSON.stringify(fileRecords.map((record) => [record.logicalPath, record.sandboxRef, record.contentHash])));
90
+ const diffMetadata = {
91
+ schema: "zob.write-lane-diff-metadata.v1",
92
+ candidateId: preliminary.candidateId,
93
+ sandboxRootRef,
94
+ changedPaths,
95
+ fileRecords,
96
+ diffHash,
97
+ productionWritesPerformed: false,
98
+ autoApply: false,
99
+ bodyStored: false,
100
+ promptBodiesStored: false,
101
+ outputBodiesStored: false,
102
+ };
103
+ const rollback = {
104
+ schema: "zob.write-lane-rollback-metadata.v1",
105
+ candidateId: preliminary.candidateId,
106
+ rollbackStrategy: "delete_quarantine_test_workspace_or_discard_merge_candidate",
107
+ sandboxRootRef,
108
+ rollbackHash: sha256(JSON.stringify({ sandboxRootRef, changedPaths, diffHash })),
109
+ productionWritesPerformed: false,
110
+ bodyStored: false,
111
+ promptBodiesStored: false,
112
+ outputBodiesStored: false,
113
+ };
114
+ const candidateDir = promotionCandidateDir(repoRoot, preliminary.candidateId);
115
+ mkdirSync(join(candidateDir, "write-lane"), { recursive: true });
116
+ const diffMetadataRef = promotionCandidateRef(preliminary.candidateId, "write-lane/diff-metadata.json");
117
+ const rollbackRef = promotionCandidateRef(preliminary.candidateId, "write-lane/rollback.json");
118
+ writeFileSync(join(repoRoot, diffMetadataRef), JSON.stringify(diffMetadata, null, 2), "utf8");
119
+ writeFileSync(join(repoRoot, rollbackRef), JSON.stringify(rollback, null, 2), "utf8");
120
+ const validationErrors = validateWriteLaneDiffMetadata(diffMetadata);
121
+ const validationRef = promotionCandidateRef(preliminary.candidateId, "write-lane/validation.json");
122
+ writeFileSync(join(repoRoot, validationRef), JSON.stringify({ schema: "zob.write-lane-validation.v1", candidateId: preliminary.candidateId, valid: validationErrors.length === 0, errors: validationErrors, bodyStored: false, promptBodiesStored: false, outputBodiesStored: false }, null, 2), "utf8");
123
+ const candidate: PromotionCandidateRecord = {
124
+ ...preliminary,
125
+ changedPaths: changedPaths.sort(),
126
+ changedPathHashes: changedPaths.sort().map((path) => sha256(path)),
127
+ allowedPaths: [sandboxRootRef],
128
+ forbiddenPaths: [],
129
+ comsThreadRef: promotionCandidateRef(preliminary.candidateId, "promotion-coms-thread.json"),
130
+ metadata: { ...preliminary.metadata, diffHash, sandboxRootRef, logicalAllowedPaths: input.allowedPaths, logicalForbiddenPaths: input.forbiddenPaths ?? [] },
131
+ };
132
+ const prepared = advancePromotionCandidate(repoRoot, candidate, { toStatus: "prepared", preparedArtifactRef: diffMetadataRef, validationRefs: validationErrors.length === 0 ? [validationRef] : [], rollbackRef });
133
+ writePromotionCandidate(repoRoot, prepared);
134
+ return { candidate: prepared, sandboxRootRef, diffMetadataRef, rollbackRef, validationRef };
135
+ }
136
+
137
+ export function validateWriteLaneDiffMetadata(artifact: unknown): string[] {
138
+ const errors: string[] = [];
139
+ if (!isRecord(artifact)) return ["write-lane diff metadata must be an object"];
140
+ if (artifact.schema !== "zob.write-lane-diff-metadata.v1") errors.push("write-lane diff metadata schema mismatch");
141
+ if (!Array.isArray(artifact.changedPaths) || artifact.changedPaths.length === 0) errors.push("write lane requires changedPaths");
142
+ if (typeof artifact.diffHash !== "string" || !/^[a-f0-9]{64}$/i.test(artifact.diffHash)) errors.push("write lane requires diffHash");
143
+ if (artifact.productionWritesPerformed !== false || artifact.autoApply !== false) errors.push("write lane preparation must not perform production writes or auto-apply");
144
+ if (artifact.bodyStored !== false || artifact.promptBodiesStored !== false || artifact.outputBodiesStored !== false) errors.push("write-lane diff metadata must keep body flags false");
145
+ return errors;
146
+ }
147
+
148
+ export function markWriteLaneAppliedInQuarantine(repoRoot: string, candidate: PromotionCandidateRecord): PromotionCandidateRecord {
149
+ if (candidate.kind !== "write_lane") throw new Error("candidate kind must be write_lane");
150
+ if (candidate.status !== "approved") throw new Error("write lane quarantine apply requires approved candidate");
151
+ const applied = advancePromotionCandidate(repoRoot, candidate, { toStatus: "applied", applyScope: "quarantine_test_directory", applyPerformed: true });
152
+ writePromotionCandidate(repoRoot, applied);
153
+ return applied;
154
+ }
155
+
156
+ export function validateWriteLanePromotionCandidate(repoRoot: string, candidate: PromotionCandidateRecord): string[] {
157
+ const errors = validatePromotionCandidate(repoRoot, candidate);
158
+ if (candidate.kind !== "write_lane") errors.push("candidate kind must be write_lane");
159
+ if (candidate.productionWritesPerformed !== false || candidate.autoApply !== false) errors.push("write lane candidate must not perform production writes or auto-apply");
160
+ if (!String(candidate.metadata?.sandboxRootRef ?? "").startsWith(`reports/promotions/${candidate.candidateId}/write-lane/sandbox`)) errors.push("write lane sandboxRootRef must stay inside candidate promotion workspace");
161
+ return errors;
162
+ }