@khoavu882/doflow 2.0.0-beta.4 → 2.0.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 (497) hide show
  1. package/README.md +12 -11
  2. package/bin/doflow.js +21 -11
  3. package/core/.antigravity-plugin/plugin.json +1 -3
  4. package/core/.claude-plugin/plugin.json +1 -1
  5. package/core/.codex-plugin/plugin.json +1 -1
  6. package/core/.plugin/plugin.json +1 -1
  7. package/core/harnesses/claude/hooks/lib.sh +43 -24
  8. package/core/harnesses/claude/hooks/mcp-tool-guard.sh +7 -17
  9. package/core/harnesses/claude/hooks/permission-audit.sh +3 -0
  10. package/core/harnesses/claude/hooks/post-compact.sh +35 -32
  11. package/core/harnesses/claude/hooks/post-edit-lint.sh +2 -0
  12. package/core/harnesses/claude/hooks/post-shell-observe.sh +48 -0
  13. package/core/harnesses/claude/hooks/post-tool-failure.sh +3 -0
  14. package/core/harnesses/claude/hooks/pre-bash-guard.sh +7 -17
  15. package/core/harnesses/claude/hooks/pre-compact.sh +23 -27
  16. package/core/harnesses/claude/hooks/pre-implement-gate.sh +7 -18
  17. package/core/harnesses/claude/hooks/session-end.sh +23 -10
  18. package/core/harnesses/claude/hooks/session-start.sh +5 -3
  19. package/core/harnesses/claude/hooks/skill-config-audit.sh +3 -0
  20. package/core/harnesses/claude/hooks/stop-check.sh +5 -3
  21. package/core/harnesses/claude/hooks/subagent-audit.sh +5 -5
  22. package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -3
  23. package/core/harnesses/claude/settings/settings.json +18 -0
  24. package/core/harnesses/claude/statusline/doflow-statusline.sh +1 -0
  25. package/core/harnesses/codex/agents/core-implementer.toml +1 -0
  26. package/core/harnesses/codex/agents/delivery-lead.toml +10 -0
  27. package/core/harnesses/codex/agents/quality-guardian.toml +1 -1
  28. package/core/harnesses/codex/agents/research-writer.toml +1 -1
  29. package/core/harnesses/codex/agents/reviewer.toml +10 -0
  30. package/core/harnesses/codex/agents/spec-analyst.toml +1 -1
  31. package/core/harnesses/codex/agents/system-architect.toml +1 -1
  32. package/core/harnesses/codex/hooks/lib.sh +44 -25
  33. package/core/harnesses/codex/hooks/mcp-tool-guard.sh +7 -15
  34. package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +3 -1
  35. package/core/harnesses/codex/hooks/pre-bash-guard.sh +7 -15
  36. package/core/harnesses/codex/hooks/pre-compact.impl.sh +29 -26
  37. package/core/harnesses/codex/hooks/pre-implement-gate.sh +7 -16
  38. package/core/harnesses/codex/hooks/session-end.impl.sh +23 -10
  39. package/core/harnesses/codex/hooks/session-start.sh +5 -3
  40. package/core/harnesses/codex/hooks/stop-check.sh +6 -5
  41. package/core/harnesses/codex/hooks/subagent-audit.sh +18 -6
  42. package/core/harnesses/codex/hooks/user-prompt-submit.sh +5 -4
  43. package/core/harnesses/copilot/hooks/doflow-lib.sh +93 -0
  44. package/core/harnesses/copilot/hooks/doflow-mcp-tool-guard.sh +9 -0
  45. package/core/harnesses/copilot/hooks/doflow-pre-bash-guard.sh +9 -0
  46. package/core/harnesses/copilot/hooks/doflow-pre-implement-gate.sh +9 -0
  47. package/core/harnesses/copilot/hooks/doflow-session-start.sh +9 -0
  48. package/core/harnesses/copilot/hooks/doflow-stop-check.sh +9 -0
  49. package/core/harnesses/copilot/hooks/doflow-subagent-start.sh +9 -0
  50. package/core/harnesses/copilot/hooks/doflow-subagent-stop.sh +9 -0
  51. package/core/harnesses/copilot/hooks/doflow.json +57 -0
  52. package/core/harnesses/kiro/agents/doflow.json +1 -1
  53. package/core/harnesses/kiro/hooks/lib.sh +26 -6
  54. package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +21 -5
  55. package/core/harnesses/kiro/hooks/pre-bash-guard.sh +21 -5
  56. package/core/harnesses/kiro/hooks/pre-implement-gate.sh +21 -5
  57. package/core/harnesses/kiro/hooks/session-start.sh +12 -5
  58. package/core/harnesses/kiro/hooks/stop-check.sh +22 -30
  59. package/core/harnesses/pi/extensions/doflow-guard.js +167 -0
  60. package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +27 -12
  61. package/core/harnesses/shared/hooks/adapters/antigravity.js +14 -57
  62. package/core/harnesses/shared/hooks/bridge/bridge.sh +277 -0
  63. package/core/harnesses/shared/hooks/bridge/envelope.jq +129 -0
  64. package/core/harnesses/shared/hooks/bridge/observe-model.sh +75 -0
  65. package/core/harnesses/shared/hooks/bridge/respond.sh +70 -0
  66. package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +28 -14
  67. package/core/harnesses/shared/hooks/policies/capture-failure.sh +51 -16
  68. package/core/harnesses/shared/hooks/policies/compact-text.sh +46 -0
  69. package/core/harnesses/shared/hooks/policies/contract.sh +78 -0
  70. package/core/harnesses/shared/hooks/policies/deny-json.sh +35 -9
  71. package/core/harnesses/shared/hooks/policies/emission-rules.sh +37 -0
  72. package/core/harnesses/shared/hooks/policies/emission.jq +209 -0
  73. package/core/harnesses/shared/hooks/policies/emission.sh +383 -0
  74. package/core/harnesses/shared/hooks/policies/identity.sh +177 -0
  75. package/core/harnesses/shared/hooks/policies/lib.sh +65 -40
  76. package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +48 -35
  77. package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +284 -33
  78. package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +180 -110
  79. package/core/harnesses/shared/hooks/policies/session-context.sh +66 -7
  80. package/core/harnesses/shared/hooks/policies/stop-check.sh +61 -23
  81. package/core/harnesses/shared/hooks/policies/subagent-audit.sh +39 -6
  82. package/core/harnesses/shared/hooks/policies/summary-store.sh +347 -0
  83. package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +97 -159
  84. package/core/harnesses/shared/hooks/stream-hook-runner.js +114 -187
  85. package/core/harnesses/shared/locator/doflow-run +2 -3
  86. package/core/registry/advice.json +3 -3
  87. package/core/registry/assets.json +72 -80
  88. package/core/registry/capabilities.json +12 -0
  89. package/core/registry/contracts.json +60 -33
  90. package/core/registry/contribution-points.json +32 -0
  91. package/core/registry/gates.json +32 -0
  92. package/core/registry/guidance-caps.json +40 -0
  93. package/core/registry/harnesses.json +1542 -277
  94. package/core/registry/lifecycle.json +2837 -37
  95. package/core/registry/mcp.json +5 -1
  96. package/core/registry/models.json +7 -1
  97. package/core/registry/package-templates/README.md +19 -0
  98. package/core/registry/package-templates/agent/files/agent.md +9 -0
  99. package/core/registry/package-templates/agent/template.json +4 -0
  100. package/core/registry/package-templates/capability-provider/files/provider.json +9 -0
  101. package/core/registry/package-templates/capability-provider/template.json +11 -0
  102. package/core/registry/package-templates/debate-preset/files/preset.json +26 -0
  103. package/core/registry/package-templates/debate-preset/template.json +4 -0
  104. package/core/registry/package-templates/review-preset/files/preset.json +30 -0
  105. package/core/registry/package-templates/review-preset/template.json +4 -0
  106. package/core/registry/package-templates/skill/files/SKILL.md +8 -0
  107. package/core/registry/package-templates/skill/template.json +4 -0
  108. package/core/registry/package-templates/worker/files/worker.json +92 -0
  109. package/core/registry/package-templates/worker/template.json +11 -0
  110. package/core/registry/packages/doflow/doflow-package.json +15 -0
  111. package/core/registry/packages/doflow/presets/debate-3.json +26 -0
  112. package/core/registry/protocols.json +61 -0
  113. package/core/registry/routes.json +17 -0
  114. package/core/registry/rules.json +431 -0
  115. package/core/registry/settings.json +276 -0
  116. package/core/registry/storage.json +701 -30
  117. package/core/registry/telemetry.json +236 -0
  118. package/core/registry/transcripts.json +142 -0
  119. package/core/registry/verification.json +76 -1
  120. package/core/registry/workflows.json +55 -0
  121. package/core/shared/agent-specs/core-implementer.md +3 -0
  122. package/core/shared/agent-specs/delivery-lead.md +68 -0
  123. package/core/shared/agent-specs/quality-guardian.md +5 -1
  124. package/core/shared/agent-specs/research-writer.md +10 -3
  125. package/core/shared/agent-specs/reviewer.md +53 -0
  126. package/core/shared/agent-specs/spec-analyst.md +5 -6
  127. package/core/shared/agent-specs/system-architect.md +5 -1
  128. package/core/shared/guidance/DOFLOW_CORE.md +1 -5
  129. package/core/shared/guidance/modes/MODE_DeepResearch.md +1 -1
  130. package/core/shared/guidance/modes/MODE_Orchestration.md +4 -3
  131. package/core/shared/guidance/modes/MODE_Task_Management.md +14 -14
  132. package/core/shared/guidance/pointers/codex.md +1 -4
  133. package/core/shared/guidance/references/ARTIFACT_FORMAT.md +30 -16
  134. package/core/shared/guidance/references/ARTIFACT_VOICE.md +3 -2
  135. package/core/shared/guidance/references/CONSTITUTION_BASE.md +17 -15
  136. package/core/shared/guidance/references/DIAGRAM_GUIDE.md +1 -1
  137. package/core/shared/guidance/references/DOFLOW_CHAIN.md +17 -19
  138. package/core/shared/guidance/references/EVIDENCE_LEDGER.md +7 -8
  139. package/core/shared/guidance/references/MODEL_SELECTION.md +5 -3
  140. package/core/shared/guidance/references/ORCHESTRATION.md +1 -2
  141. package/core/shared/guidance/rules/RULES.md +45 -0
  142. package/core/shared/scripts/doflow/bash/do-args.sh +37 -0
  143. package/core/shared/scripts/doflow/bash/do-exec-paths.sh +4 -0
  144. package/core/shared/scripts/doflow/bash/do-git-state.sh +15 -4
  145. package/core/shared/scripts/doflow/bash/do-parallel-check.sh +4 -0
  146. package/core/shared/scripts/doflow/bash/do-paths.sh +40 -2
  147. package/core/shared/scripts/doflow/bash/do-prereqs.sh +2 -1
  148. package/core/shared/scripts/doflow/bash/do-review-package.sh +4 -0
  149. package/core/shared/scripts/doflow/bash/do-task-brief.sh +58 -16
  150. package/core/shared/scripts/doflow/bash/render-audit.sh +26 -2
  151. package/core/shared/scripts/doflow/bash/render-diagrams.sh +1 -0
  152. package/core/shared/scripts/doflow/bash/render-puml.sh +2 -1
  153. package/core/shared/scripts/doflow/bash/validate-artifacts.sh +48 -4
  154. package/core/shared/scripts/doflow/bin/doflow-run +154 -35
  155. package/core/shared/skills/do/SKILL.md +12 -10
  156. package/core/shared/skills/do/references/advice_calls.md +26 -0
  157. package/core/shared/skills/do/references/pm_routing.md +1 -2
  158. package/core/shared/skills/do/references/program_mode.md +31 -0
  159. package/core/shared/skills/do-brainstorm/SKILL.md +20 -74
  160. package/core/shared/skills/do-brainstorm/references/handoff_branches.md +35 -0
  161. package/core/shared/skills/do-brainstorm/references/intent_seed.md +21 -0
  162. package/core/shared/skills/do-brainstorm/references/round_log.md +17 -0
  163. package/core/shared/skills/do-code-review/SKILL.md +41 -144
  164. package/core/shared/skills/do-code-review/content-types/markdown.md +24 -2
  165. package/core/shared/skills/do-code-review/references/tools.md +90 -0
  166. package/core/shared/skills/do-code-review/scripts/doc_quality_checker.py +549 -7
  167. package/core/shared/skills/do-design/SKILL.md +24 -23
  168. package/core/shared/skills/do-diagnose/SKILL.md +14 -4
  169. package/core/shared/skills/do-document/SKILL.md +11 -1
  170. package/core/shared/skills/do-document/references/deep_research.md +1 -2
  171. package/core/shared/skills/do-document/references/embedded-research.md +18 -6
  172. package/core/shared/skills/do-document/references/implementation-flow.md +5 -6
  173. package/core/shared/skills/do-execute-plan/SKILL.md +17 -59
  174. package/core/shared/skills/do-execute-plan/references/handoff_record.md +7 -2
  175. package/core/shared/skills/do-execute-plan/references/parallel_dispatch.md +13 -0
  176. package/core/shared/skills/do-execute-plan/references/readiness_gate.md +28 -1
  177. package/core/shared/skills/do-execute-plan/references/run_position.md +13 -1
  178. package/core/shared/skills/do-execute-plan/references/scaffold.md +17 -9
  179. package/core/shared/skills/do-execute-plan/references/state_checkpoint.md +11 -0
  180. package/core/shared/skills/do-execute-plan/references/task_attempts.md +78 -24
  181. package/core/shared/skills/do-flow/SKILL.md +8 -9
  182. package/core/shared/skills/do-flow/references/task_classes.md +2 -2
  183. package/core/shared/skills/do-git/SKILL.md +4 -0
  184. package/core/shared/skills/do-implement/SKILL.md +7 -9
  185. package/core/shared/skills/do-plan/SKILL.md +29 -19
  186. package/core/shared/skills/do-test/SKILL.md +7 -4
  187. package/core/shared/templates/doflow/constitution-template.md +9 -3
  188. package/core/shared/templates/doflow/data-model-template.md +1 -1
  189. package/core/shared/templates/doflow/design-template.md +113 -16
  190. package/core/shared/templates/doflow/plan-template.md +11 -10
  191. package/core/shared/templates/doflow/question-log-template.md +14 -2
  192. package/core/shared/templates/doflow/requirement-template.md +1 -1
  193. package/core/worker-evidence/antigravity/checks.json +14 -0
  194. package/core/worker-evidence/codex/2026-10-18-cli-check.json +107 -0
  195. package/core/worker-evidence/codex/2026-10-18-live-run-edit.json +73 -0
  196. package/core/worker-evidence/codex/2026-10-18-live-run-read-only.json +62 -0
  197. package/core/worker-evidence/codex/2026-10-24-cli-check.json +126 -0
  198. package/core/worker-evidence/codex/checks.json +38 -0
  199. package/package.json +10 -6
  200. package/src/adapters/antigravity/index.js +226 -113
  201. package/src/adapters/claude/index.js +39 -5
  202. package/src/adapters/codex/agents.js +25 -15
  203. package/src/adapters/codex/hooks.js +40 -5
  204. package/src/adapters/codex/index.js +100 -22
  205. package/src/adapters/codex/native-projection.js +6 -2
  206. package/src/adapters/copilot/index.js +58 -23
  207. package/src/adapters/copy-tree.js +294 -48
  208. package/src/adapters/guidance-manifest.js +71 -0
  209. package/src/adapters/guidance-pointer.js +19 -0
  210. package/src/adapters/hook-commands.js +6 -10
  211. package/src/adapters/index.js +1 -0
  212. package/src/adapters/kiro/index.js +38 -13
  213. package/src/adapters/opencode/index.js +8 -8
  214. package/src/adapters/pi/hooks.js +120 -0
  215. package/src/adapters/pi/index.js +48 -16
  216. package/src/adapters/resolve-source.js +26 -2
  217. package/src/cli/commands/install.js +3 -2
  218. package/src/cli/commands/reconcile.js +53 -9
  219. package/src/cli/commands/remove.js +2 -2
  220. package/src/cli/commands/rollback.js +6 -3
  221. package/src/cli/commands/self-update.js +18 -9
  222. package/src/cli/commands/status.js +21 -2
  223. package/src/cli/commands/ui.js +99 -0
  224. package/src/cli/commands/update.js +3 -2
  225. package/src/cli/index.js +338 -33
  226. package/src/cli/runtime-commands.js +243 -52
  227. package/src/cli/shared.js +0 -2
  228. package/src/helper/git.js +1 -1
  229. package/src/helper/guardrails.js +1 -1
  230. package/src/helper/marker-merge.js +31 -13
  231. package/src/helper/package-ids.js +37 -0
  232. package/src/helper/semver.js +94 -0
  233. package/src/install/backup.js +105 -15
  234. package/src/install/context.js +1 -1
  235. package/src/install/targets.js +31 -16
  236. package/src/lifecycle/coverage.js +74 -0
  237. package/src/lifecycle/hook-step.js +61 -0
  238. package/src/lifecycle/hook-tier.js +160 -0
  239. package/src/lifecycle/index.js +434 -86
  240. package/src/lifecycle/retired-harnesses.js +318 -0
  241. package/src/lifecycle/view.js +35 -15
  242. package/src/registry/index.js +686 -32
  243. package/src/registry/worker-ids.js +45 -0
  244. package/src/release/build-package.js +0 -3
  245. package/src/release/docs-blocks.js +492 -0
  246. package/src/release/preflight.js +425 -0
  247. package/src/release/rehearse.js +401 -0
  248. package/src/release/release-workflow.js +733 -0
  249. package/src/release/sync-plugin-versions.js +43 -7
  250. package/src/runtime/advice/bench-gate.js +25 -0
  251. package/src/runtime/advice/cli.js +59 -16
  252. package/src/runtime/advice/client.js +32 -9
  253. package/src/runtime/advice/config.js +98 -133
  254. package/src/runtime/advice/doctor.js +1 -1
  255. package/src/runtime/advice/elevation.js +97 -0
  256. package/src/runtime/advice/endpoint-guard.js +9 -3
  257. package/src/runtime/advice/mode.js +37 -0
  258. package/src/runtime/advice/record.js +18 -5
  259. package/src/runtime/advice/registry.js +4 -1
  260. package/src/runtime/advice/shadow-config.js +229 -0
  261. package/src/runtime/advice/shadow-dispatcher.js +276 -0
  262. package/src/runtime/brief-rules.js +81 -0
  263. package/src/runtime/brief-tools.js +111 -34
  264. package/src/runtime/candidate.js +514 -0
  265. package/src/runtime/capabilities/executor.js +450 -0
  266. package/src/runtime/capabilities/loopback.js +41 -0
  267. package/src/runtime/capabilities/sanitizer.js +88 -0
  268. package/src/runtime/capability-router.js +135 -3
  269. package/src/runtime/checkouts.js +73 -11
  270. package/src/runtime/claims.js +27 -12
  271. package/src/runtime/cli-result.js +11 -4
  272. package/src/runtime/cli.js +221 -277
  273. package/src/runtime/config-home.js +42 -0
  274. package/src/runtime/context/arbitrate.js +767 -0
  275. package/src/runtime/context/budget.js +203 -0
  276. package/src/runtime/context/compose.js +1367 -0
  277. package/src/runtime/context/delivery-store.js +100 -0
  278. package/src/runtime/context/emission-rules.js +118 -0
  279. package/src/runtime/context/identity.js +227 -0
  280. package/src/runtime/context/mandatory.js +594 -0
  281. package/src/runtime/context/pointer.js +142 -0
  282. package/src/runtime/context/primary-command.js +117 -0
  283. package/src/runtime/context/primary.js +344 -0
  284. package/src/runtime/context/summary-store.js +655 -0
  285. package/src/runtime/context-pack.js +1106 -245
  286. package/src/runtime/decision-register.js +13 -4
  287. package/src/runtime/dispatch/admission.js +392 -0
  288. package/src/runtime/dispatch/attempt-end.js +274 -0
  289. package/src/runtime/dispatch/command.js +628 -0
  290. package/src/runtime/dispatch/controls.js +904 -0
  291. package/src/runtime/dispatch/envelope.js +276 -0
  292. package/src/runtime/dispatch/grants.js +310 -0
  293. package/src/runtime/dispatch/integrate.js +617 -0
  294. package/src/runtime/dispatch/loop.js +1835 -0
  295. package/src/runtime/dispatch/store.js +352 -0
  296. package/src/runtime/dispatch/verify-run.js +201 -0
  297. package/src/runtime/evidence-fields.js +39 -0
  298. package/src/runtime/evidence-ledger.js +41 -7
  299. package/src/runtime/failure/capture.js +3 -1
  300. package/src/runtime/failure/cli.js +25 -9
  301. package/src/runtime/failure/home.js +57 -30
  302. package/src/runtime/failure/store.js +7 -2
  303. package/src/runtime/feature-pointer.js +174 -0
  304. package/src/runtime/feature-resolve.js +13 -2
  305. package/src/runtime/fleet/command.js +77 -0
  306. package/src/runtime/fleet/projects.js +178 -0
  307. package/src/runtime/fleet/tree.js +383 -0
  308. package/src/runtime/freshness.js +77 -10
  309. package/src/runtime/git-memo.js +46 -0
  310. package/src/runtime/guidance/ablation.js +427 -0
  311. package/src/runtime/health.js +565 -17
  312. package/src/runtime/history-compactor.js +13 -3
  313. package/src/runtime/implementation-gate.js +277 -22
  314. package/src/runtime/inventory/coverage.js +1 -1
  315. package/src/runtime/inventory/index.js +1 -1
  316. package/src/runtime/inventory/precedence.js +2 -2
  317. package/src/runtime/inventory/siblings.js +6 -4
  318. package/src/runtime/knowledge/code-corpus.js +277 -0
  319. package/src/runtime/knowledge/code-lexical.js +130 -0
  320. package/src/runtime/knowledge/code-retrieval.js +307 -0
  321. package/src/runtime/knowledge/code-validation.js +106 -0
  322. package/src/runtime/knowledge/gp3-gate.js +74 -0
  323. package/src/runtime/knowledge/graph-adapter.js +288 -0
  324. package/src/runtime/knowledge/graph-fallback.js +394 -0
  325. package/src/runtime/knowledge/hybrid.js +136 -8
  326. package/src/runtime/knowledge/retrieval.js +34 -1
  327. package/src/runtime/knowledge/rtk-compress.js +77 -0
  328. package/src/runtime/knowledge/semble-bridge.py +106 -0
  329. package/src/runtime/knowledge/semble-lifecycle.js +114 -0
  330. package/src/runtime/knowledge/semble-provider.js +365 -0
  331. package/src/runtime/lifecycle/cli.js +16 -6
  332. package/src/runtime/lifecycle/event-store.js +8 -6
  333. package/src/runtime/lifecycle/followup.js +6 -1
  334. package/src/runtime/lifecycle/overview.js +24 -1
  335. package/src/runtime/lifecycle/report-store.js +8 -10
  336. package/src/runtime/lifecycle/retention.js +95 -31
  337. package/src/runtime/lifecycle/root.js +9 -1
  338. package/src/runtime/lifecycle/status.js +34 -17
  339. package/src/runtime/lifecycle/store-upkeep.js +56 -7
  340. package/src/runtime/mask.js +134 -7
  341. package/src/runtime/mcp-consultations.js +40 -6
  342. package/src/runtime/model-router.js +79 -7
  343. package/src/runtime/models/catalogue.js +191 -0
  344. package/src/runtime/models/command.js +153 -0
  345. package/src/runtime/off-words.js +12 -0
  346. package/src/runtime/outcome.js +3 -3
  347. package/src/runtime/packages/command.js +1009 -0
  348. package/src/runtime/packages/contributions.js +116 -0
  349. package/src/runtime/packages/digest.js +132 -0
  350. package/src/runtime/packages/fetch.js +182 -0
  351. package/src/runtime/packages/grants.js +192 -0
  352. package/src/runtime/packages/index-file.js +134 -0
  353. package/src/runtime/packages/instruction.js +90 -0
  354. package/src/runtime/packages/manifest.js +331 -0
  355. package/src/runtime/packages/points.js +477 -0
  356. package/src/runtime/packages/programs.js +216 -0
  357. package/src/runtime/packages/scaffold.js +277 -0
  358. package/src/runtime/packages/source.js +90 -0
  359. package/src/runtime/packages/state.js +164 -0
  360. package/src/runtime/packages/store.js +449 -0
  361. package/src/runtime/packages/tar.js +106 -0
  362. package/src/runtime/packages/view.js +406 -0
  363. package/src/runtime/plan-check.js +59 -0
  364. package/src/runtime/plan-content.js +324 -0
  365. package/src/runtime/policy-init.js +118 -0
  366. package/src/runtime/profiles/doctor.js +96 -0
  367. package/src/runtime/profiles/resolve.js +244 -0
  368. package/src/runtime/profiles/rollback.js +254 -0
  369. package/src/runtime/profiles/sampler.js +41 -0
  370. package/src/runtime/readiness-record.js +16 -11
  371. package/src/runtime/readiness.js +127 -16
  372. package/src/runtime/research-request.js +50 -25
  373. package/src/runtime/retrieval-plan.js +402 -73
  374. package/src/runtime/retrieval-record.js +293 -0
  375. package/src/runtime/review/command.js +246 -0
  376. package/src/runtime/review/dominance.js +68 -0
  377. package/src/runtime/review/findings.js +434 -0
  378. package/src/runtime/review/identity.js +255 -0
  379. package/src/runtime/review/protocol-command.js +109 -0
  380. package/src/runtime/review/protocols.js +405 -0
  381. package/src/runtime/review/resolve-protocol.js +302 -0
  382. package/src/runtime/review/start.js +530 -0
  383. package/src/runtime/roadmap/facts.js +479 -0
  384. package/src/runtime/roadmap/gates.js +270 -0
  385. package/src/runtime/roadmap/loop.js +1636 -0
  386. package/src/runtime/roadmap/merge.js +381 -0
  387. package/src/runtime/roadmap/rows.js +1113 -0
  388. package/src/runtime/roadmap/seed.js +951 -0
  389. package/src/runtime/rules-report.js +336 -0
  390. package/src/runtime/scaffold/artifacts.js +63 -9
  391. package/src/runtime/scaffold/generate.js +21 -9
  392. package/src/runtime/settings/autopilot.js +106 -0
  393. package/src/runtime/settings/cli.js +280 -0
  394. package/src/runtime/settings/config-write.js +314 -0
  395. package/src/runtime/settings/files.js +271 -0
  396. package/src/runtime/settings/legacy.js +154 -0
  397. package/src/runtime/settings/lexical.js +56 -0
  398. package/src/runtime/settings/prepared-run.js +269 -0
  399. package/src/runtime/settings/project-layers.js +118 -0
  400. package/src/runtime/settings/refs.js +288 -0
  401. package/src/runtime/settings/registry.js +553 -0
  402. package/src/runtime/settings/resolve.js +713 -0
  403. package/src/runtime/settings/shared.js +37 -0
  404. package/src/runtime/settings/worker-billing.js +107 -0
  405. package/src/runtime/settings/write.js +269 -0
  406. package/src/runtime/slot-command.js +78 -0
  407. package/src/runtime/slots.js +671 -0
  408. package/src/runtime/source-version.js +290 -0
  409. package/src/runtime/state-root.js +217 -0
  410. package/src/runtime/storage/cli.js +12 -5
  411. package/src/runtime/storage/engine.js +9 -2
  412. package/src/runtime/storage/registry.js +14 -1
  413. package/src/runtime/storage/roots.js +66 -16
  414. package/src/runtime/storage/rules.js +82 -10
  415. package/src/runtime/storage/upkeep.js +10 -2
  416. package/src/runtime/storage/work-status.js +245 -26
  417. package/src/runtime/task-attempts.js +589 -69
  418. package/src/runtime/task-classifier.js +47 -11
  419. package/src/runtime/task-graph.js +373 -0
  420. package/src/runtime/task-run.js +778 -0
  421. package/src/runtime/task-scope.js +202 -56
  422. package/src/runtime/task-sources.js +147 -0
  423. package/src/runtime/task-state.js +440 -65
  424. package/src/runtime/team/admission.js +301 -0
  425. package/src/runtime/team/envelope.js +324 -0
  426. package/src/runtime/team/review-guard.js +156 -0
  427. package/src/runtime/trace/analyze.js +427 -0
  428. package/src/runtime/trace/baseline.js +770 -0
  429. package/src/runtime/trace/ledger.js +63 -140
  430. package/src/runtime/trace/otlp-export.js +568 -0
  431. package/src/runtime/trace/otlp-map.js +481 -0
  432. package/src/runtime/trace/spans.js +745 -0
  433. package/src/runtime/trace/telemetry.js +225 -0
  434. package/src/runtime/trace/views.js +1 -0
  435. package/src/runtime/transcripts/command.js +98 -0
  436. package/src/runtime/transcripts/cursor.js +326 -0
  437. package/src/runtime/transcripts/read.js +126 -0
  438. package/src/runtime/transcripts/readers/claude-jsonl.js +74 -0
  439. package/src/runtime/transcripts/readers/codex-rollout.js +70 -0
  440. package/src/runtime/transcripts/readers/copilot-events.js +90 -0
  441. package/src/runtime/transcripts/readers/kiro-jsonl.js +77 -0
  442. package/src/runtime/transcripts/readers/pi-jsonl.js +59 -0
  443. package/src/runtime/transcripts/registry.js +161 -0
  444. package/src/runtime/transcripts/stats.js +161 -0
  445. package/src/runtime/verification/check-key.js +628 -0
  446. package/src/runtime/verification/contract-runner.js +546 -11
  447. package/src/runtime/verification/engine.js +499 -9
  448. package/src/runtime/verification/impact.js +617 -0
  449. package/src/runtime/verification/inflight.js +205 -0
  450. package/src/runtime/verification/registry.js +176 -0
  451. package/src/runtime/verification/reuse.js +184 -0
  452. package/src/runtime/verification/telemetry-emit.js +254 -0
  453. package/src/runtime/verification/test-selection.js +67 -7
  454. package/src/runtime/worker/active.js +90 -0
  455. package/src/runtime/worker/cancel.js +222 -0
  456. package/src/runtime/worker/catalogue.js +122 -0
  457. package/src/runtime/worker/command.js +677 -0
  458. package/src/runtime/worker/evidence.js +288 -0
  459. package/src/runtime/worker/launch.js +288 -0
  460. package/src/runtime/worker/models.js +137 -0
  461. package/src/runtime/worker/parsers.js +218 -0
  462. package/src/runtime/worker/probes/index.js +706 -0
  463. package/src/runtime/worker/process-tree.js +415 -0
  464. package/src/runtime/worker/quota.js +43 -0
  465. package/src/runtime/worker/readiness.js +713 -0
  466. package/src/runtime/worker/run-store.js +166 -0
  467. package/src/runtime/worker/supervisor.js +541 -0
  468. package/src/runtime/worker/worktree-check.js +252 -0
  469. package/src/runtime/workflow-engine.js +5 -1
  470. package/src/runtime/workflow-orchestrator.js +578 -63
  471. package/src/runtime/worktree.js +149 -22
  472. package/src/state/index.js +1 -1
  473. package/src/state/lockfile.js +64 -10
  474. package/src/state/run-lock.js +1 -1
  475. package/types/node-commonjs.d.ts +106 -7
  476. package/core/.antigravity-plugin/hooks.json +0 -39
  477. package/core/harnesses/gemini/hooks/hooks.json +0 -77
  478. package/core/harnesses/gemini/hooks/lib.sh +0 -302
  479. package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +0 -21
  480. package/core/harnesses/gemini/hooks/post-edit-lint.sh +0 -39
  481. package/core/harnesses/gemini/hooks/pre-bash-guard.sh +0 -21
  482. package/core/harnesses/gemini/hooks/pre-compact.sh +0 -38
  483. package/core/harnesses/gemini/hooks/pre-implement-gate.sh +0 -22
  484. package/core/harnesses/gemini/hooks/session-end.impl.sh +0 -89
  485. package/core/harnesses/gemini/hooks/session-end.sh +0 -5
  486. package/core/harnesses/gemini/hooks/session-start.sh +0 -5
  487. package/core/harnesses/gemini/settings/adapter-defaults.json +0 -4
  488. package/core/harnesses/shared/hooks/adapters/arg-fields.js +0 -19
  489. package/core/harnesses/shared/hooks/adapters/gemini.js +0 -114
  490. package/core/harnesses/shared/hooks/hooks.json +0 -47
  491. package/core/shared/guidance/FLAGS.md +0 -25
  492. package/core/shared/guidance/rules/RULE_01_SAFETY.md +0 -25
  493. package/core/shared/guidance/rules/RULE_02_WORKFLOW.md +0 -23
  494. package/core/shared/guidance/rules/RULE_03_QUALITY.md +0 -14
  495. package/core/shared/guidance/rules/RULE_04_QUESTIONS.md +0 -46
  496. package/src/adapters/gemini/hooks.js +0 -210
  497. package/src/adapters/gemini/index.js +0 -390
@@ -2,27 +2,21 @@
2
2
  'use strict';
3
3
 
4
4
  /**
5
- * DoFlow Cross-Harness Hook Runner (design.md C2) — front door for every in-scope lifecycle
6
- * event (SessionStart, PreToolUse, PostToolUse, Stop, PreInvocation) for the two harnesses whose
7
- * native hook contract speaks JSON stdin/stdout rather than a bare exit code: Gemini CLI and
8
- * Antigravity. It owns event dispatch and per-harness payload/decision translation (delegated to
9
- * adapters/{gemini,antigravity}.js, D2) and delegates every policy decision to the Canonical
10
- * Policy Library (core/harnesses/shared/hooks/policies/*.sh, Phase A) — it implements no guard
11
- * policy logic itself.
5
+ * DoFlow Cross-Harness Hook Runner — front door for every in-scope lifecycle
6
+ * event (SessionStart, PreToolUse, PostToolUse, Stop, PreInvocation) for Antigravity. It owns
7
+ * event dispatch and native payload/decision
8
+ * translation (delegated to adapters/antigravity.js) and delegates every policy decision
9
+ * to the shared lifecycle bridge — it implements no guard policy logic itself.
12
10
  *
13
11
  * Invocation: `node stream-hook-runner.js [EventName]`, JSON payload on stdin, JSON decision on
14
- * stdout. EventName is the preferred way to select which canonical policy applies; when omitted
15
- * (older hooks.json wiring that doesn't yet pass it), the event is inferred from the payload's
16
- * own shape as a fallback, matching this runner's behavior before event names were threaded
17
- * through argv.
12
+ * stdout. EventName selects which canonical policy applies.
18
13
  */
19
14
 
20
- const { execFileSync } = require('node:child_process');
15
+ const { spawnSync } = require('node:child_process');
21
16
  const fs = require('node:fs');
22
17
  const os = require('node:os');
23
18
  const path = require('node:path');
24
19
 
25
- const geminiAdapter = require('./adapters/gemini');
26
20
  const antigravityAdapter = require('./adapters/antigravity');
27
21
 
28
22
  // Tool-name classification for PreToolUse, generalized to the union every Phase A canonical
@@ -76,19 +70,58 @@ function isProgrammingError(error) {
76
70
  }
77
71
  }
78
72
 
79
- /** IC-011: `$XDG_CONFIG_HOME/doflow/failures` when absolute, else `$HOME/.config/doflow/failures` when HOME is absolute, else null. */
80
- function failureHome(env) {
73
+ // The config home and the lexical failure.capture rule, copied from src/runtime/config-home.js and
74
+ // src/runtime/settings/lexical.js (086 IC-003, IC-004); the marked text is the same in every reader.
75
+ // BEGIN doflow-config-home v1 (rule: src/runtime/config-home.js; checked by test/guards/settings.test.js)
76
+ function doflowConfigHome(env) {
81
77
  const xdg = env.XDG_CONFIG_HOME;
82
- if (typeof xdg === 'string' && xdg !== '') return path.isAbsolute(xdg) ? path.join(xdg, 'doflow', 'failures') : null;
78
+ if (typeof xdg === 'string' && xdg !== '' && path.isAbsolute(xdg)) return path.join(xdg, 'doflow');
83
79
  const home = env.HOME;
84
- return typeof home === 'string' && path.isAbsolute(home) ? path.join(home, '.config', 'doflow', 'failures') : null;
80
+ if (typeof home === 'string' && home !== '' && path.isAbsolute(home)) return path.join(home, '.config', 'doflow');
81
+ return null;
82
+ }
83
+ // END doflow-config-home v1
84
+
85
+ // BEGIN doflow-settings-lexical v1 (rule: src/runtime/settings/lexical.js; checked by test/guards/settings.test.js)
86
+ const WS = '[ \\t\\n\\v\\f\\r]';
87
+ const CAPTURE_RE = new RegExp(`"failure\\.capture"${WS}*:${WS}*("[^"]*"|[^,}" \\t\\n\\v\\f\\r]*)`, 'g');
88
+ function lexicalCapture(text) {
89
+ let out = null;
90
+ for (const m of text.split('\0', 1)[0].matchAll(CAPTURE_RE)) out = m[1] === '"on"' ? (out ?? 'on') : 'off';
91
+ return out;
92
+ }
93
+ function readLexicalCapture(file) {
94
+ try {
95
+ if (!fs.statSync(file).isFile()) return 'off';
96
+ } catch (error) {
97
+ const code = error && error.code;
98
+ if (code === 'ENOENT' || code === 'ELOOP' || code === 'ENOTDIR') return null;
99
+ if (code === 'EACCES') {
100
+ try {
101
+ const parent = path.dirname(file);
102
+ if (!fs.statSync(parent).isDirectory()) return null;
103
+ try { fs.accessSync(parent, fs.constants.X_OK); return null; }
104
+ catch (accessError) { return accessError && accessError.code === 'EACCES' ? 'off' : null; }
105
+ } catch { return null; }
106
+ }
107
+ return 'off';
108
+ }
109
+ try { return lexicalCapture(fs.readFileSync(file, 'latin1')); } catch { return 'off'; }
110
+ }
111
+ // END doflow-settings-lexical v1
112
+
113
+ /** IC-011: `<config home>/failures`, or null with no config home. */
114
+ function failureHome(env) {
115
+ const dir = doflowConfigHome(env);
116
+ return dir === null ? null : path.join(dir, 'failures');
85
117
  }
86
118
 
87
- /** IC-014: the environment first, then one stat of the sentinel file. */
119
+ /** IC-014, IC-005: the environment first, then one stat of the sentinel file, then settings.json beside the failure home. */
88
120
  function captureIsOff(home, env) {
89
121
  const setting = env.DOFLOW_FAILURE_CAPTURE;
90
122
  if (typeof setting === 'string' && CAPTURE_OFF_VALUES.includes(setting.trim().toLowerCase())) return true;
91
- try { return fs.statSync(path.join(home, 'off')).isFile(); } catch { return false; }
123
+ try { if (fs.statSync(path.join(home, 'off')).isFile()) return true; } catch { /* no sentinel */ }
124
+ return readLexicalCapture(path.join(path.dirname(home), 'settings.json')) === 'off';
92
125
  }
93
126
 
94
127
  /** The first stack frame inside this hooks folder as `<path relative to it>:<function>`, no line number. */
@@ -249,15 +282,6 @@ function captureHookFailure({ command, kind, frame = null }, env = process.env)
249
282
  }
250
283
  }
251
284
 
252
- // Canonical script name -> pre-normalization per-harness file name, for the fallback search only.
253
- const LEGACY_SCRIPT_NAMES = {
254
- 'session-context.sh': 'session-start.sh',
255
- 'pre-implementation-gate.sh': 'pre-implement-gate.sh',
256
- 'mcp-tool-guard.sh': 'mcp-tool-guard.sh',
257
- 'stop-check.sh': 'stop-check.sh',
258
- 'pre-bash-guard.sh': 'pre-bash-guard.sh',
259
- };
260
-
261
285
  // A hook payload is one tool call's JSON — a few KB in the overwhelming majority of cases, a few
262
286
  // hundred KB for a large file edit at most. These bounds exist only to stop a misbehaving harness
263
287
  // process (stdin that never closes, or streams unboundedly) from hanging this front door forever;
@@ -334,75 +358,58 @@ function resolveProjectRoot(workspacePaths) {
334
358
  }
335
359
 
336
360
  /**
337
- * Resolve a Canonical Policy Library script's absolute path. Primary location is this runner's
338
- * own `policies/` sibling directory (core/harnesses/shared/hooks/policies/) — the canonical
339
- * source of truth (design.md C1) that ships alongside this file, so the lookup needs no
340
- * project-root guessing and works identically in-repo and once installed, as long as the
341
- * `shared/hooks/` tree is projected together. The per-harness candidate search below is kept only
342
- * as a fallback for an install that hasn't picked up the canonical policies/ directory yet.
343
- */
344
- function resolvePolicyScript(projectRoot, scriptName) {
345
- const primary = path.join(__dirname, 'policies', scriptName);
346
- if (fs.existsSync(primary)) return primary;
347
-
348
- const legacyName = LEGACY_SCRIPT_NAMES[scriptName] || scriptName;
349
- const candidates = [
350
- path.join(projectRoot, '.gemini/hooks', legacyName),
351
- path.join(projectRoot, '.claude/hooks', legacyName),
352
- path.join(projectRoot, '.codex/hooks', legacyName),
353
- path.join(projectRoot, '.doflow/scripts', legacyName),
354
- ];
355
- for (const candidate of candidates) {
356
- if (fs.existsSync(candidate)) return candidate;
357
- }
358
- return null;
359
- }
360
-
361
- /**
362
- * Delegate one canonical-decision evaluation to a Phase A policy script (design.md's Canonical
363
- * Policy Script Contract): the canonical payload goes in on stdin, DOFLOW_PROJECT_DIR/DOFLOW_AGENT
364
- * are set, and the exit code decides allow/deny — exit 0 = allow, non-zero = deny with the reason
365
- * read from stderr (falling back to stdout if a script has none). Returns the CANONICAL decision
366
- * shape ({decision:'allow'} | {decision:'deny', reason}); harness-native translation happens one
367
- * layer up, in the adapter's toNative, not here — this function never speaks a harness-specific
368
- * decision vocabulary.
361
+ * Delegate the native payload to the shared lifecycle bridge. The bridge owns encoding,
362
+ * classification, effects and diagnostics; this runner only applies Antigravity's native render.
369
363
  */
370
- function delegateToPolicy(projectRoot, agent, scriptName, canonicalPayload) {
371
- const scriptPath = resolvePolicyScript(projectRoot, scriptName);
372
- if (!scriptPath) return { decision: 'allow' };
373
-
374
- try {
375
- execFileSync('bash', [scriptPath], {
376
- cwd: projectRoot,
377
- input: JSON.stringify(canonicalPayload || {}),
378
- stdio: ['pipe', 'pipe', 'pipe'],
379
- env: { ...process.env, DOFLOW_PROJECT_DIR: projectRoot, DOFLOW_AGENT: agent },
380
- });
381
- return { decision: 'allow' };
382
- } catch (err) {
383
- // A real policy deny has a numeric exit status — the script ran and its own canonical exit
384
- // code (1 = deny) is the contract this delegates to. `err.status` is null/undefined when the
385
- // process never produced an exit code at all (bash missing from PATH, EACCES, etc.) — that is
386
- // an execution fault, not a policy decision, and every sourced .sh policy in this library
387
- // fails open on its own uncertainty (`command -v jq || exit 0`); this delegator matches that
388
- // posture instead of turning an environment fault into a silent deny.
389
- if (typeof err.status !== 'number') {
390
- // A policy killed by a signal is a fault in DoFlow's own install worth recording (IC-018); a
391
- // missing `bash` or a permission error is the user's environment and is not. Either way the
392
- // decision is the same as it always was.
393
- // SIGTERM, SIGINT and SIGPIPE are the user or the harness stopping the process (DEC-031), not
394
- // a fault. Any other signal is recorded under its own kind, so a SEGV and a KILL do not share a fingerprint.
395
- if (typeof err.signal === 'string' && err.signal && !['SIGTERM', 'SIGINT', 'SIGPIPE'].includes(err.signal)) {
396
- captureHookFailure({ command: scriptName.replace(/\.sh$/, ''), kind: `policy-exec-fault:${err.signal}` });
397
- }
398
- return { decision: 'allow' };
364
+ function delegateToPolicy(projectRoot, agent, event, policyId, nativeRaw) {
365
+ const bridgeSh = path.join(__dirname, 'bridge', 'bridge.sh');
366
+ if (!fs.existsSync(bridgeSh)) {
367
+ captureHookFailure({ command: policyId, kind: 'bridge-missing' });
368
+ if (policyId === 'stop-check') {
369
+ return { v: 1, harness: agent, event, policy: policyId, policyVersion: 0, outcome: 'unsupported', code: 'bridge-missing', effect: 'proceed' };
399
370
  }
400
- const reason = err.stderr ? err.stderr.toString().trim() : (err.stdout ? err.stdout.toString().trim() : '');
401
371
  return {
402
- decision: 'deny',
403
- reason: reason || `[${scriptName}] blocked by DoFlow guard policy`,
372
+ v: 1, harness: agent, event, policy: policyId, policyVersion: 0,
373
+ outcome: 'deny', code: 'bridge-missing', reason: '[doflow] shared hooks lack the bridge; run: doflow update -t antigravity', effect: 'block',
404
374
  };
405
375
  }
376
+ const profile = process.env.DOFLOW_FAULT_PROFILE || 'compat-1';
377
+ const effectiveProfile = profile === 'compat-1' || profile === 'strict-1' ? profile : 'compat-1';
378
+ if (profile !== effectiveProfile) captureHookFailure({ command: policyId, kind: 'fault-profile-unknown' });
379
+ const blockingPolicy = ['pre-implementation-gate', 'pre-bash-guard', 'mcp-tool-guard', 'stop-check'].includes(policyId);
380
+ const faultEffect = effectiveProfile === 'strict-1' && blockingPolicy ? 'block' : 'proceed';
381
+ const faultDecision = (code) => ({
382
+ v: 1, harness: agent, event, policy: policyId, policyVersion: 0,
383
+ outcome: 'error', code, reason: code, faultProfile: effectiveProfile, effect: faultEffect,
384
+ });
385
+ const result = spawnSync('bash', [bridgeSh, agent, event, policyId, '--emit', 'decision'], {
386
+ cwd: projectRoot,
387
+ input: nativeRaw,
388
+ encoding: 'utf8',
389
+ timeout: 5000,
390
+ maxBuffer: 1024 * 1024,
391
+ env: { ...process.env, DOFLOW_PROJECT_DIR: projectRoot, DOFLOW_AGENT: agent },
392
+ });
393
+
394
+ if (result.error && result.error.code === 'ETIMEDOUT') {
395
+ captureHookFailure({ command: policyId, kind: 'bridge-timeout' });
396
+ return faultDecision('bridge-timeout');
397
+ }
398
+ // A bridge that exits before spawnSync finishes writing its stdin reports EPIPE (EOF on Windows) although it ran to
399
+ // completion; its exit status and answer are judged below, like any other run.
400
+ const completed = result.error && (result.error.code === 'EPIPE' || result.error.code === 'EOF') && result.status !== null;
401
+ if ((result.error && !completed) || result.status === null) {
402
+ if (result.signal && !['SIGTERM', 'SIGINT', 'SIGPIPE'].includes(result.signal)) {
403
+ captureHookFailure({ command: policyId, kind: `bridge-exec-fault:${result.signal}` });
404
+ }
405
+ return faultDecision('bridge-spawn');
406
+ }
407
+ try {
408
+ const decision = JSON.parse(result.stdout.trim());
409
+ if (decision && typeof decision === 'object' && typeof decision.effect === 'string') return decision;
410
+ } catch { /* malformed bridge output is a bridge fault */ }
411
+ captureHookFailure({ command: policyId, kind: 'bridge-answer-invalid' });
412
+ return faultDecision('bridge-answer-invalid');
406
413
  }
407
414
 
408
415
  function classifyPreToolUsePolicy(toolName) {
@@ -412,11 +419,11 @@ function classifyPreToolUsePolicy(toolName) {
412
419
  return null;
413
420
  }
414
421
 
415
- function evaluatePreToolUsePolicy(canonicalPayload, projectRoot, agent) {
416
- const toolName = (canonicalPayload && canonicalPayload.tool_name) || '';
422
+ function evaluatePreToolUsePolicy(payload, nativeRaw, projectRoot, agent) {
423
+ const toolName = payload && payload.toolCall && payload.toolCall.name || payload && payload.tool_name || '';
417
424
  const scriptName = classifyPreToolUsePolicy(toolName);
418
425
  if (!scriptName) return { decision: 'allow' };
419
- return delegateToPolicy(projectRoot, agent, scriptName, canonicalPayload);
426
+ return delegateToPolicy(projectRoot, agent, 'PreToolUse', scriptName.replace(/\.sh$/, ''), nativeRaw);
420
427
  }
421
428
 
422
429
  /**
@@ -431,17 +438,17 @@ function evaluatePreToolUsePolicy(canonicalPayload, projectRoot, agent) {
431
438
  * role is out of FR-001's four-policy scope) — ack only; the adapter's toNative
432
439
  * decides the harness-native shape regardless of this placeholder decision.
433
440
  */
434
- function evaluateEvent(event, canonicalPayload, projectRoot, agent) {
441
+ function evaluateEvent(event, payload, nativeRaw, projectRoot, agent) {
435
442
  switch (event) {
436
443
  case 'SessionStart':
437
- delegateToPolicy(projectRoot, agent, 'session-context.sh', canonicalPayload);
444
+ delegateToPolicy(projectRoot, agent, event, 'session-context', nativeRaw);
438
445
  return { decision: 'allow' };
439
446
 
440
447
  case 'PreToolUse':
441
- return evaluatePreToolUsePolicy(canonicalPayload, projectRoot, agent);
448
+ return evaluatePreToolUsePolicy(payload, nativeRaw, projectRoot, agent);
442
449
 
443
450
  case 'Stop':
444
- return delegateToPolicy(projectRoot, agent, 'stop-check.sh', canonicalPayload);
451
+ return delegateToPolicy(projectRoot, agent, event, 'stop-check', nativeRaw);
445
452
 
446
453
  case 'PostToolUse':
447
454
  case 'PreInvocation':
@@ -450,82 +457,7 @@ function evaluateEvent(event, canonicalPayload, projectRoot, agent) {
450
457
  }
451
458
  }
452
459
 
453
- // Falls back to 'antigravity' (this runner's legacy default) for any value other than
454
- // 'gemini', including unset/empty. An unrecognized non-empty value is likely a typo, so it
455
- // gets a stderr warning even though the fallback still applies.
456
- function resolveAgent() {
457
- const raw = process.env.DOFLOW_AGENT || '';
458
- const agent = raw.toLowerCase();
459
- if (agent === 'gemini') return 'gemini';
460
- if (raw && agent !== 'antigravity') {
461
- process.stderr.write(`stream-hook-runner: unrecognized DOFLOW_AGENT="${raw}", falling back to antigravity\n`);
462
- }
463
- return 'antigravity';
464
- }
465
-
466
- function resolveAdapter(agent) {
467
- return agent === 'gemini' ? geminiAdapter : antigravityAdapter;
468
- }
469
-
470
- function sniffEventFromPayload(payload) {
471
- if (!payload || typeof payload !== 'object') return null;
472
- // 'toolCall' in payload (key presence), not payload.toolCall (truthiness): a real Antigravity
473
- // PreToolUse payload can carry a null/empty toolCall alongside stepIdx (also present on
474
- // PostToolUse payloads) — truthiness alone let such a payload fall through to the stepIdx check
475
- // below and get misclassified as PostToolUse, silently skipping the gate entirely
476
- // (022-code-review finding). Checked before Stop/PostToolUse since a missed PreToolUse
477
- // classification fails the gate open, the worse failure mode of the two.
478
- if ('toolCall' in payload || payload.tool_name !== undefined) return 'PreToolUse';
479
- if (payload.invocationNum !== undefined) return 'PreInvocation';
480
- if (payload.terminationReason !== undefined || payload.executionNum !== undefined) return 'Stop';
481
- if (payload.stepIdx !== undefined || payload.terminationBehavior !== undefined) return 'PostToolUse';
482
- if (payload.session_id !== undefined && payload.cwd !== undefined) return 'SessionStart';
483
- return null;
484
- }
485
-
486
- // ── Back-compat helpers ──────────────────────────────────────────────────────
487
- //
488
- // evaluateToolCall/evaluatePayload predate the event-dispatcher/adapter split and are kept for
489
- // callers (including test/hooks/stream-hook-runner.test.js) that evaluate a single Antigravity-
490
- // shaped payload directly without going through main()'s argv/env-driven dispatch. Both return the
491
- // CANONICAL decision shape (never harness-native-translated) exactly as they always have.
492
-
493
- function evaluateToolCall(toolCall, projectRoot) {
494
- if (!toolCall || typeof toolCall !== 'object') {
495
- return { decision: 'allow' };
496
- }
497
- const canonicalPayload = antigravityAdapter.toCanonical('PreToolUse', { toolCall });
498
- return evaluatePreToolUsePolicy(canonicalPayload, projectRoot, 'antigravity');
499
- }
500
-
501
- function evaluatePayload(payload, projectRoot) {
502
- if (!payload || typeof payload !== 'object') {
503
- return { decision: 'allow' };
504
- }
505
-
506
- // PreToolUse: toolCall object present
507
- if (payload.toolCall) {
508
- return evaluateToolCall(payload.toolCall, projectRoot);
509
- }
510
-
511
- // PreInvocation: injection hook
512
- if (payload.invocationNum !== undefined) {
513
- return { injectSteps: [] };
514
- }
515
-
516
- // Stop hook: delegate to the canonical stop-check policy
517
- if (payload.terminationReason !== undefined) {
518
- const canonicalPayload = antigravityAdapter.toCanonical('Stop', payload);
519
- return delegateToPolicy(projectRoot, 'antigravity', 'stop-check.sh', canonicalPayload);
520
- }
521
-
522
- // PostToolUse / PostInvocation: empty object response
523
- if (payload.stepIdx !== undefined || payload.terminationBehavior !== undefined) {
524
- return {};
525
- }
526
-
527
- return { decision: 'allow' };
528
- }
460
+ const RUNNER_EVENTS = new Set(['SessionStart', 'PreToolUse', 'PostToolUse', 'Stop', 'PreInvocation']);
529
461
 
530
462
  async function main() {
531
463
  try {
@@ -542,17 +474,17 @@ async function main() {
542
474
  }
543
475
 
544
476
  const projectRoot = resolveProjectRoot(payload.workspacePaths);
545
- const agent = resolveAgent();
546
- const adapter = resolveAdapter(agent);
547
- const event = explicitEvent || sniffEventFromPayload(payload);
477
+ const agent = 'antigravity';
478
+ const adapter = antigravityAdapter;
479
+ const event = explicitEvent;
548
480
 
549
- if (!event) {
481
+ if (!event || !RUNNER_EVENTS.has(event)) {
482
+ captureHookFailure({ command: 'stream-hook-runner', kind: 'runner-event-missing' });
550
483
  process.stdout.write(JSON.stringify({ decision: 'allow' }) + '\n');
551
484
  return;
552
485
  }
553
486
 
554
- const canonicalPayload = adapter.toCanonical(event, payload);
555
- const decision = evaluateEvent(event, canonicalPayload, projectRoot, agent);
487
+ const decision = evaluateEvent(event, payload, rawInput, projectRoot, agent);
556
488
  const native = adapter.toNative(event, decision);
557
489
 
558
490
  // An empty object is a harness's documented "say nothing" answer (e.g. Antigravity's Stop
@@ -576,15 +508,10 @@ if (require.main === module) {
576
508
  }
577
509
 
578
510
  module.exports = {
579
- evaluateToolCall,
580
- evaluatePayload,
581
511
  resolveProjectRoot,
512
+ delegateToPolicy,
582
513
  evaluateEvent,
583
- resolveAgent,
584
- resolveAdapter,
585
- resolvePolicyScript,
586
514
  classifyPreToolUsePolicy,
587
- sniffEventFromPayload,
588
515
  isProgrammingError,
589
516
  captureHookFailure,
590
517
  };
@@ -1,5 +1,5 @@
1
1
  #!/bin/sh
2
- # DoFlow locator shim — projected to all eight harnesses by the `locator.doflow` asset in
2
+ # DoFlow locator shim — projected to every harness by the `locator.doflow` asset in
3
3
  # core/registry/assets.json (design.md §3 C2, §4.1).
4
4
  #
5
5
  # Its ONLY job is to find the single dispatcher (at $REL below, under the config dir) and exec it
@@ -40,8 +40,7 @@
40
40
 
41
41
  # The dispatcher ships inside the `scripts.doflow` asset (`core/shared/scripts`), so it sits at
42
42
  # `scripts/doflow/bin/doflow-run` under the shared tree. Every harness projects that tree to its
43
- # scope root (`<project>/.doflow` or `$HOME/.doflow`), so this one path holds for all eight,
44
- # Antigravity at global scope excepted (it projects no runtime there).
43
+ # scope root (`<project>/.doflow` or `$HOME/.doflow`), so this one path holds for every harness.
45
44
  REL='scripts/doflow/bin/doflow-run'
46
45
  dispatcher=''
47
46
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 1,
3
- "timeoutMs": 5000,
3
+ "timeoutMs": 15000,
4
4
  "probeTimeoutMs": 1500,
5
5
  "doctorBudgetMs": 6000,
6
6
  "limits": {
@@ -72,8 +72,8 @@
72
72
  "single": "One frontier reviewer, different from the author",
73
73
  "deep": "Two independent frontier reviewers with different lenses"
74
74
  },
75
- "staticFrom": "single",
76
- "askedBy": []
75
+ "staticFrom": "the IC-002 rule: single only for a light-path change at a singleRisks risk, else deep; the gate-b floor can raise seats",
76
+ "askedBy": ["review"]
77
77
  },
78
78
  {
79
79
  "id": "mcp-need",