@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
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env bash
2
+ case "${OSTYPE:-}" in msys*|cygwin*|win32*) if command -v jq >/dev/null 2>&1; then jq() { command jq -b "$@"; }; fi ;; esac # native jq.exe ends lines with CRLF unless -b
3
+ _DOFLOW_SRC=${0//\\//}; case $_DOFLOW_SRC in */*) _DOFLOW_POLDIR=${_DOFLOW_SRC%/*} ;; *) _DOFLOW_POLDIR=. ;; esac
2
4
  # pre-implementation-gate.sh — Canonical Policy Library: PreToolUse(Edit|Write|...)
3
5
  # backstop for the doflow implement gate. The HARD half of the one enforced
4
6
  # gate (the other half is the prompt-level do-prereqs.sh inside
@@ -21,28 +23,20 @@
21
23
  # - edit target is under agent-docs/ -> allow (editing the artifacts themselves)
22
24
  # - edit target outside the repo -> allow
23
25
  # It reads files with jq and lists checkouts with one git call; it never runs
24
- # the DoFlow runtime. Self-contained + fail-open: any uncertainty -> allow (exit 0).
26
+ # the DoFlow runtime. Missing or malformed v1 input is denied as out of step; other faults follow IC-011.
25
27
  #
26
28
  # Canonical Policy Script Contract (design.md §4):
27
29
  # env DOFLOW_PROJECT_DIR (repo root, if the front door sets it),
28
30
  # DOFLOW_AGENT (harness id, informational only here),
29
- # CLAUDE_CONFIG_DIR / CLAUDE_PROJECT_DIR / GEMINI_CONFIG_DIR / CODEX_HOME
31
+ # CLAUDE_CONFIG_DIR / CLAUDE_PROJECT_DIR / CODEX_HOME
30
32
  # (each already read by the harness-specific dispatcher this policy
31
33
  # replaces — kept so an unmodified front door still resolves its own
32
34
  # harness's do-paths.sh resolver)
33
- # stdin a PreToolUse-shaped JSON payload for an edit tool. Every harness's
34
- # own field names differ (Claude/Gemini: tool_name/tool_input.file_path;
35
- # Codex: tool_name=apply_patch with a unified diff in
36
- # tool_input.command; Kiro: field names undocumented) — this script
37
- # reads the union of known shapes rather than assuming one, since a
38
- # native front door (Claude/Codex/Kiro) execs this script directly
39
- # with no payload translation of its own.
40
- # exit 0 = allow, non-zero = deny with the reason on stderr. A front door
41
- # translates this into whatever JSON/exit-code shape its harness
42
- # natively expects — this script never speaks a harness-specific
43
- # decision shape.
35
+ # stdin a native payload encoded as envelope v1 by the lifecycle bridge.
36
+ # exit exit 2 + doflow_decide deny = deny; other faults per IC-011. A front
37
+ # door translates this into its native response shape.
44
38
  #
45
- # Reconciliation note (022-normalize-hooks, Phase A): claude/gemini/codex/kiro
39
+ # Reconciliation note (022-normalize-hooks, Phase A): claude/codex/kiro
46
40
  # each shipped a separately-adapted copy of this gate; antigravity's copy
47
41
  # additionally never depended on a do-paths.sh resolver at all — it computed
48
42
  # feature_dir itself from the current branch name and checked the three
@@ -58,74 +52,71 @@
58
52
 
59
53
  set -uo pipefail
60
54
 
61
- command -v jq >/dev/null 2>&1 || exit 0 # no jq -> cannot evaluate -> allow
62
-
63
55
  INPUT=$(cat)
64
-
65
- # ── Normalized envelope (preferred; review R7) ────────────────────────────────
66
- # A host adapter that has already decoded its native event sends
67
- # {"doflow_event": {"operation": "edit", "paths": [..], "projectRoot": "..", "taskId": ".."}}
68
- # and this policy consumes it verbatim. The union decoder below remains the
69
- # fallback for front doors that still forward raw native payloads; per-harness
70
- # knowledge belongs in those adapters, and each one that starts sending the
71
- # envelope retires its share of the union.
72
- ENVELOPE_ROOT=""
73
- ENVELOPE_TASK=""
74
- ENVELOPE_OP=$(printf '%s' "$INPUT" | jq -r '.doflow_event.operation // empty' 2>/dev/null)
75
- if [ -n "$ENVELOPE_OP" ]; then
76
- [ "$ENVELOPE_OP" = "edit" ] || exit 0 # only edits are gated
77
- FILES=$(printf '%s' "$INPUT" | jq -r '.doflow_event.paths[]? // empty' 2>/dev/null | sed '/^$/d' | sort -u)
78
- [ -n "$FILES" ] || exit 0
79
- ENVELOPE_ROOT=$(printf '%s' "$INPUT" | jq -r '.doflow_event.projectRoot // empty' 2>/dev/null)
80
- ENVELOPE_TASK=$(printf '%s' "$INPUT" | jq -r '.doflow_event.taskId // empty' 2>/dev/null)
56
+ if [ -f "$_DOFLOW_POLDIR/contract.sh" ]; then
57
+ . "$_DOFLOW_POLDIR/contract.sh"
81
58
  else
59
+ doflow_decision_init() { :; }
60
+ doflow_decide() { :; }
61
+ doflow_read_envelope() { DF_ENV_CLASS=missing; DF_ENV_CODE=contract-missing; }
62
+ ( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-implementation-gate contract-missing ) >/dev/null 2>&1 || true
63
+ if [[ "${DOFLOW_AGENT:-}" =~ ^[a-z]+$ ]]; then
64
+ printf '[pre-implementation-gate] DoFlow hooks out of step; run: doflow update -t %s\n' "$DOFLOW_AGENT" >&2
65
+ else
66
+ printf '[pre-implementation-gate] DoFlow hooks out of step; run: doflow update\n' >&2
67
+ fi
68
+ doflow_decide deny contract-missing
69
+ exit 2
70
+ fi
71
+ doflow_decision_init pre-implementation-gate 1
72
+ command -v jq >/dev/null 2>&1 || {
73
+ doflow_decide error dependency-missing:jq
74
+ ( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-implementation-gate dependency-missing:jq ) >/dev/null 2>&1 || true
75
+ exit 0
76
+ }
82
77
 
83
- # ── Tool name (union of every known field name across harnesses; LEGACY decoder) ──
84
- tool=""
85
- for field in '.tool_name' '.tool' '.toolName' '.name'; do
86
- tool=$(printf '%s' "$INPUT" | jq -r "${field} // empty" 2>/dev/null)
87
- [ -n "$tool" ] && break
88
- done
89
-
90
- is_patch_tool=false
91
- case "$tool" in
92
- Edit|Write|MultiEdit|edit_file|write_file|create_file|replace_file|replace) ;;
93
- write_to_file|replace_file_content|multi_replace_file_content) ;;
94
- apply_patch) is_patch_tool=true ;;
95
- *) exit 0 ;;
96
- esac
97
-
98
- # ── Candidate files to gate ────────────────────────────────────────────────────
99
- # Normal edit tools: one file, from the union of field names harnesses use.
100
- # apply_patch (Codex): the tool has no file_path field at all — the paths are
101
- # embedded in a unified diff under tool_input.command.
102
- FILES=""
103
- if [ "$is_patch_tool" = true ]; then
104
- PATCH=$(printf '%s' "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null)
105
- [ -n "$PATCH" ] || exit 0
106
- # "#" (not the original codex script's "|") is the sed delimiter here: BSD
107
- # sed (macOS, no GNU coreutils) misparses "s|...(Add|Update|Delete)...|...|"
108
- # because it splits on every unescaped "|", including the ones meant as ERE
109
- # alternation inside the pattern — a portability bug in the source script
110
- # this reconciliation fixes rather than ports, since it silently broke
111
- # apply_patch parsing under this exact invocation on any non-GNU-sed host.
112
- FILES=$(printf '%s\n' "$PATCH" | sed -nE \
78
+ # Parse v1 apply_patch paths using the shared parser.
79
+ parse_patch_paths() {
80
+ printf '%s\n' "$1" | sed -nE \
113
81
  -e 's#^\*\*\* (Add|Update|Delete) File: (.+)$#\2#p' \
114
82
  -e 's#^\+\+\+ (a/|b/)?(.+)$#\2#p' \
115
- | sed '/^\/dev\/null$/d' | sort -u)
116
- [ -n "$FILES" ] || exit 0
83
+ | sed '/^\/dev\/null$/d' | sort -u
84
+ }
85
+
86
+ DF_ENV_CLASS=missing DF_ENV_CODE=envelope-missing
87
+ doflow_read_envelope || true
88
+
89
+ # ── Envelope v1 ───────────────────────────────────────────────────────────────
90
+ ENVELOPE_ROOT=""
91
+ ENVELOPE_TASK=""
92
+ if [ "$DF_ENV_CLASS" = v1 ]; then
93
+ ENVELOPE_OP=$DF_ENV_OP
94
+ [ "$ENVELOPE_OP" = "edit" ] || exit 0 # only edits are gated
95
+ FILES=$DF_ENV_PATHS
96
+ ENVELOPE_ROOT=$DF_ENV_ROOT
97
+ ENVELOPE_TASK=$DF_ENV_TASK
98
+ if [ -z "$FILES" ] && [ -z "$DF_ENV_PATCH" ]; then
99
+ doflow_decide unsupported edit-without-target
100
+ ( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-implementation-gate edit-without-target ) >/dev/null 2>&1 || true
101
+ exit 0
102
+ fi
103
+ if [ -z "$FILES" ] && [ -n "$DF_ENV_PATCH" ]; then
104
+ FILES=$(parse_patch_paths "$DF_ENV_PATCH")
105
+ [ -n "$FILES" ] || exit 0
106
+ fi
107
+ elif [ "$DF_ENV_CLASS" = unsupported ]; then
108
+ doflow_decide unsupported envelope-version
109
+ ( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-implementation-gate unsupported:envelope-version ) >/dev/null 2>&1 || true
110
+ exit 0
117
111
  else
118
- file=""
119
- for field in '.tool_input.file_path' '.tool_input.path' '.tool_input.target' '.file_path' '.path'; do
120
- file=$(printf '%s' "$INPUT" | jq -r "${field} // empty" 2>/dev/null)
121
- [ -n "$file" ] && break
122
- done
123
- [ -n "$file" ] || exit 0
124
- FILES="$file"
112
+ if [ "${DF_ENV_CODE:-envelope-missing}" != contract-missing ]; then
113
+ ( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure pre-implementation-gate envelope-missing ) >/dev/null 2>&1 || true
114
+ fi
115
+ if [[ "${DOFLOW_AGENT:-}" =~ ^[a-z]+$ ]]; then printf '[pre-implementation-gate] DoFlow hooks out of step; run: doflow update -t %s\n' "$DOFLOW_AGENT" >&2; else printf '[pre-implementation-gate] DoFlow hooks out of step; run: doflow update\n' >&2; fi
116
+ doflow_decide deny "${DF_ENV_CODE:-envelope-missing}"
117
+ exit 2
125
118
  fi
126
119
 
127
- fi # end legacy union decoder
128
-
129
120
  # ── Resolve repo root ───────────────────────────────────────────────────────
130
121
  # DOFLOW_PROJECT_DIR (explicit) beats the envelope's projectRoot beats git discovery.
131
122
  ROOT="${DOFLOW_PROJECT_DIR:-$ENVELOPE_ROOT}"
@@ -149,13 +140,11 @@ RESOLVER_CANDIDATES=(
149
140
  "$ROOT/.doflow/scripts/doflow/bash/do-paths.sh"
150
141
  "$ROOT/.claude/scripts/doflow/bash/do-paths.sh"
151
142
  "$ROOT/.codex/scripts/doflow/bash/do-paths.sh"
152
- "$ROOT/.gemini/scripts/doflow/bash/do-paths.sh"
153
143
  "$ROOT/.kiro/scripts/doflow/bash/do-paths.sh"
154
144
  "$HOME/.doflow/scripts/doflow/bash/do-paths.sh"
155
145
  "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/scripts/doflow/bash/do-paths.sh"
156
146
  "${CLAUDE_PROJECT_DIR:-}/.claude/scripts/doflow/bash/do-paths.sh"
157
147
  "${CODEX_HOME:-$HOME/.codex}/scripts/doflow/bash/do-paths.sh"
158
- "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/scripts/doflow/bash/do-paths.sh"
159
148
  "$HOME/.kiro/scripts/doflow/bash/do-paths.sh"
160
149
  )
161
150
 
@@ -173,11 +162,14 @@ has_plan=""
173
162
  if [ -n "$RESOLVER" ]; then
174
163
  json=$("$RESOLVER" --json 2>/dev/null) || json=""
175
164
  if [ -n "$json" ]; then
176
- feature_dir=$(printf '%s' "$json" | jq -r '.feature_dir // empty' 2>/dev/null)
177
- repo_root=$(printf '%s' "$json" | jq -r '.repo_root // empty' 2>/dev/null)
178
- has_requirement=$(printf '%s' "$json" | jq -r '.has_requirement // false' 2>/dev/null)
179
- has_design=$(printf '%s' "$json" | jq -r '.has_design // false' 2>/dev/null)
180
- has_plan=$(printf '%s' "$json" | jq -r '.has_plan // false' 2>/dev/null)
165
+ # One jq run for all five fields, one per line (none of them can hold a newline).
166
+ {
167
+ IFS= read -r feature_dir
168
+ IFS= read -r repo_root
169
+ IFS= read -r has_requirement
170
+ IFS= read -r has_design
171
+ IFS= read -r has_plan
172
+ } < <(printf '%s' "$json" | jq -r '(.feature_dir // ""), (.repo_root // ""), (.has_requirement // false), (.has_design // false), (.has_plan // false)' 2>/dev/null) || true
181
173
  fi
182
174
  fi
183
175
 
@@ -257,18 +249,41 @@ real_path() {
257
249
  repo_real=$(cd -P "$repo_root" 2>/dev/null && pwd) || repo_real="$repo_root"
258
250
 
259
251
  # Only source files inside this repo are gated: edits to doflow artifacts are
260
- # always allowed, and an absolute path elsewhere is not this repo's.
252
+ # always allowed, an absolute path elsewhere is not this repo's, and neither is a
253
+ # path git ignores.
261
254
  GATED=false
262
255
  while IFS= read -r file; do
263
256
  [ -z "$file" ] && continue
264
- case "$file" in *"/agent-docs/"*|agent-docs/*) continue ;; esac
257
+ # A ".." segment can lead out of agent-docs (agent-docs/../src/x), so such a path is judged by
258
+ # its real path below, never by the text before the "..".
259
+ case "/$file/" in
260
+ */../*) ;;
261
+ *) case "$file" in *"/agent-docs/"*|agent-docs/*) continue ;; esac ;;
262
+ esac
263
+ check="$file"
265
264
  case "$file" in
266
265
  /*)
267
266
  real=$(real_path "$file") || real="$file"
268
- case "$real" in *"/agent-docs/"*) continue ;; esac
267
+ case "/$real/" in */../*) ;; *) case "$real" in *"/agent-docs/"*) continue ;; esac ;; esac
269
268
  case "$real" in "$repo_real"/*) ;; *) continue ;; esac
269
+ check="$real"
270
+ ;;
271
+ *)
272
+ real=$(real_path "$repo_root/$file") || real="$repo_root/$file"
273
+ # real_path folds a ".." only through directories that exist, so one left in it is not folded.
274
+ case "/$file/" in */../*) case "/$real/" in */../*) ;; *) case "${real#"$repo_real"}/" in */agent-docs/*) continue ;; esac ;; esac ;; esac
270
275
  ;;
271
276
  esac
277
+ # A path git ignores (a local config file such as .mcp.json) is not source. check-ignore
278
+ # without --no-index answers "not ignored" for a tracked file, so tracked source stays gated.
279
+ # The skip never applies to DoFlow's own state or gate artifacts: .doflow/ is gitignored, and
280
+ # skipping it would let an edit forge a readiness record. Any `.doflow` or `agent-docs/doflow`
281
+ # segment of the real path, or of the path as written (a `..` the resolver could not fold), keeps it gated.
282
+ # The same holds for the do-paths.sh resolver the gate runs (any RESOLVER_CANDIDATES path, whichever
283
+ # harness directory holds it, ignored or not): rewriting it can make the gate find no feature.
284
+ case "/$file/" in */.doflow/*|*/agent-docs/doflow/*|*/../*|*/scripts/doflow/bash/do-paths.sh/) GATED=true; break ;; esac
285
+ case "${real#"$repo_real"}/" in */.doflow/*|*/agent-docs/doflow/*|*/scripts/doflow/bash/do-paths.sh/) GATED=true; break ;; esac
286
+ git -C "$repo_root" check-ignore -q -- "$check" 2>/dev/null && continue
272
287
  GATED=true
273
288
  break
274
289
  done <<< "$FILES"
@@ -314,25 +329,71 @@ checkouts() {
314
329
  return 0
315
330
  }
316
331
 
317
- # A state file under this checkout, else under exactly one other checkout, at
318
- # the first of the given paths that exists in each; held in two or more others,
319
- # it cannot be told which is meant -> allow.
332
+ # Whether two files hold the same bytes.
333
+ same_bytes() {
334
+ if command -v cmp >/dev/null 2>&1; then cmp -s "$1" "$2"; else [ "$(cat "$1")" = "$(cat "$2")" ]; fi
335
+ }
336
+
337
+ # Whether the flat record $1 of a namespaced task may be read as feature $2's
338
+ # (115 D-3): it names that feature (featureSlug on a run, slug on a readiness
339
+ # record) or none. A file that does not parse names nobody.
340
+ flat_is_ours() {
341
+ local named
342
+ named=$(jq -r '[.featureSlug, .slug] | map(select(type == "string" and . != "")) | first // empty' "$1" 2>/dev/null) || return 1
343
+ [ -z "$named" ] || [ "$named" = "$2" ]
344
+ }
345
+
346
+ # The task's record of store $2 (readiness | orchestration) under checkout $1,
347
+ # keyed by feature $3 as the runtime keys it (115 C-1): <store>/<feature>/<id>.json
348
+ # for a task id other than the feature's slug, else the flat file; the flat file
349
+ # of a namespaced task only when it is this feature's or names none. Sets HIT.
350
+ HIT=""
351
+ record_in() {
352
+ local store="$1/.doflow/state/$2"
353
+ HIT=""
354
+ if [ -n "$3" ] && [ "$3" != "$task_id" ]; then
355
+ if [ -f "$store/$3/$task_id.json" ]; then HIT="$store/$3/$task_id.json"; return 0; fi
356
+ [ -f "$store/$task_id.json" ] && flat_is_ours "$store/$task_id.json" "$3" && HIT="$store/$task_id.json"
357
+ return 0
358
+ fi
359
+ [ -f "$store/$task_id.json" ] && HIT="$store/$task_id.json"
360
+ return 0
361
+ }
362
+
363
+ # The task's readiness record, keyed by feature $1. From a linked worktree the
364
+ # main checkout's comes first, since every record lives there (115 IC-004), and
365
+ # a copy at the same path here with other bytes refuses (C-3). Else this
366
+ # checkout's, else exactly one other checkout's; held in two or more others it
367
+ # cannot be told which is meant -> allow.
320
368
  FOUND=""
321
369
  find_state() {
322
- local rel root count=0 hit
370
+ local root count=0 copy
323
371
  FOUND=""
324
- for rel in "$@"; do
325
- if [ -f "$repo_root/$rel" ]; then FOUND="$repo_root/$rel"; return 0; fi
326
- done
372
+ if [ -f "$repo_root/.git" ]; then
373
+ checkouts
374
+ if [ -n "$MAIN" ]; then
375
+ record_in "$MAIN" readiness "$1"
376
+ if [ -n "$HIT" ]; then
377
+ copy="$repo_root${HIT#"$MAIN"}"
378
+ if [ -f "$copy" ] && ! same_bytes "$copy" "$HIT"; then
379
+ printf "doflow gate readiness-before-implementation: task '%s' has a readiness record in this worktree (%s) that differs from the main checkout's (%s). Next: keep one of the two and remove the other, then re-run. Nothing was changed.\n" "$task_id" "$copy" "$HIT" >&2
380
+ doflow_decide deny readiness-store-conflict
381
+ exit 2
382
+ fi
383
+ FOUND="$HIT"
384
+ return 0
385
+ fi
386
+ fi
387
+ fi
388
+ record_in "$repo_root" readiness "$1"
389
+ if [ -n "$HIT" ]; then FOUND="$HIT"; return 0; fi
327
390
  checkouts
328
391
  for root in ${OTHERS[@]+"${OTHERS[@]}"}; do
329
- hit=""
330
- for rel in "$@"; do
331
- [ -f "$root/$rel" ] && { hit="$root/$rel"; break; }
332
- done
333
- [ -n "$hit" ] || continue
392
+ [ "$root" = "$MAIN" ] && continue
393
+ record_in "$root" readiness "$1"
394
+ [ -n "$HIT" ] || continue
334
395
  count=$((count + 1))
335
- FOUND="$hit"
396
+ FOUND="$HIT"
336
397
  done
337
398
  [ "$count" -le 1 ] || exit 0
338
399
  }
@@ -348,18 +409,26 @@ run_feature() {
348
409
  return 0
349
410
  }
350
411
 
412
+ # The feature the task's records are keyed by, as the runtime keys them
413
+ # (featureSlugFor): a task id that names a feature folder in this checkout is
414
+ # its own feature, else the branch's.
415
+ run_key="$slug"
416
+ [ -d "$repo_root/agent-docs/doflow/$task_id" ] && run_key="$task_id"
417
+
351
418
  # The task's run: this checkout's, else the one other checkout's run of the same
352
419
  # feature. A run with the same id for another feature is a different task.
353
420
  find_run() {
354
- local rel=".doflow/state/orchestration/$task_id.json" root count=0
421
+ local root count=0
355
422
  FOUND=""
356
- if [ -f "$repo_root/$rel" ]; then FOUND="$repo_root/$rel"; return 0; fi
423
+ record_in "$repo_root" orchestration "$run_key"
424
+ if [ -n "$HIT" ]; then FOUND="$HIT"; return 0; fi
357
425
  checkouts
358
426
  for root in ${OTHERS[@]+"${OTHERS[@]}"}; do
359
- [ -f "$root/$rel" ] || continue
360
- [ "$(run_feature "$root/$rel")" = "$slug" ] || continue
427
+ record_in "$root" orchestration "$run_key"
428
+ [ -n "$HIT" ] || continue
429
+ [ "$(run_feature "$HIT")" = "$run_key" ] || continue
361
430
  count=$((count + 1))
362
- FOUND="$root/$rel"
431
+ FOUND="$HIT"
363
432
  done
364
433
  [ "$count" -le 1 ] || exit 0
365
434
  }
@@ -384,13 +453,14 @@ PLANNED=false
384
453
  # plan.md all exist. Classes that cannot be a feature skip this check.
385
454
  if [ "$exempt" = false ] && [ -n "$FEATURE_ROOT" ] && [ "$PLANNED" = false ]; then
386
455
  echo "[pre-implementation-gate] doflow gate: feature $feature_dir is missing requirement.md, design.md, or plan.md — run /do-brainstorm, /do-design, then /do-plan before editing source. (Edits under agent-docs/ are always allowed; skip the flow by removing the feature dir.)" >&2
456
+ doflow_decide deny missing-artifacts
387
457
  exit 2
388
458
  fi
389
459
 
390
460
  # ── Readiness ────────────────────────────────────────────────────────────────
391
461
  # The workflow registry the installed runtime reads: beside this policy in an
392
462
  # install, the source tree's own, the project's install, the global install.
393
- POLICY_DIR=$(cd -P "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd) || POLICY_DIR=""
463
+ POLICY_DIR=$_DOFLOW_POLDIR
394
464
  REGISTRY=""
395
465
  for candidate in \
396
466
  "${POLICY_DIR:+$POLICY_DIR/../../../runtime/core/registry/workflows.json}" \
@@ -452,13 +522,10 @@ if [ -n "$RUN" ]; then
452
522
  fi
453
523
 
454
524
  # The record, where the runtime looks: under the feature's namespace (the run's
455
- # own feature when it recorded one), then flat; this checkout first.
456
- record_slug="${run_slug:-$slug}"
457
- if [ -n "$record_slug" ] && [ "$record_slug" != "$task_id" ]; then
458
- find_state ".doflow/state/readiness/$record_slug/$task_id.json" ".doflow/state/readiness/$task_id.json"
459
- else
460
- find_state ".doflow/state/readiness/$task_id.json"
461
- fi
525
+ # own feature when it recorded one), then flat; the main checkout first from a
526
+ # linked worktree, else this checkout first.
527
+ record_slug="${run_slug:-$run_key}"
528
+ find_state "$record_slug"
462
529
  record_state=""; record_class=""; record_at=""
463
530
  if [ -n "$FOUND" ]; then
464
531
  record_info=$(jq -r '(.state // ""), (.taskClass // ""), (.evaluatedAt // "")' "$FOUND" 2>/dev/null) || exit 0
@@ -480,16 +547,19 @@ gate="doflow gate readiness-before-implementation: task '$task_id'"
480
547
  rest="Next: $next, then gather what it lists until it reports READY. Nothing was changed."
481
548
  if [ -z "$FOUND" ]; then
482
549
  printf "%s has no readiness record for the '%s' template. %s\n" "$gate" "$STAGE_TEMPLATE" "$rest" >&2
550
+ doflow_decide deny readiness-missing
483
551
  exit 2
484
552
  fi
485
553
  if [ "$record_state" != READY ]; then
486
554
  printf "%s was last evaluated %s at %s against the '%s' template, not READY. %s\n" \
487
555
  "$gate" "$record_state" "$record_at" "$STAGE_TEMPLATE" "$rest" >&2
556
+ doflow_decide deny readiness-not-ready
488
557
  exit 2
489
558
  fi
490
559
  if [ "$record_class" != "$STAGE_TEMPLATE" ]; then
491
560
  printf "%s has a READY record for the '%s' template, and this stage needs '%s'. %s\n" \
492
561
  "$gate" "$record_class" "$STAGE_TEMPLATE" "$rest" >&2
562
+ doflow_decide deny readiness-wrong-template
493
563
  exit 2
494
564
  fi
495
565
 
@@ -1,4 +1,6 @@
1
1
  #!/usr/bin/env bash
2
+ case "${OSTYPE:-}" in msys*|cygwin*|win32*) if command -v jq >/dev/null 2>&1; then jq() { command jq -b "$@"; }; fi ;; esac # native jq.exe ends lines with CRLF unless -b
3
+ _DOFLOW_SRC=${0//\\//}; case $_DOFLOW_SRC in */*) _DOFLOW_POLDIR=${_DOFLOW_SRC%/*} ;; *) _DOFLOW_POLDIR=. ;; esac
2
4
  # session-context.sh — Canonical Policy Library: SessionStart guard policy
3
5
  #
4
6
  # Fires when a harness starts a new session. Captures git state into a
@@ -11,29 +13,85 @@
11
13
  # Canonical Policy Script Contract (design.md §4):
12
14
  # env DOFLOW_PROJECT_DIR, DOFLOW_AGENT (both optional here; DOFLOW_AGENT
13
15
  # only affects the "last_agent" field recorded in meta.json)
14
- # stdin the harness's native SessionStart JSON payload — must expose at
15
- # least ".session_id" and ".cwd"
16
+ # stdin envelope v1 from the native SessionStart payload, including
17
+ # the session_id and cwd fields used by this policy.
16
18
  # exit this policy never denies — it always exits 0 (side-effect only)
17
19
  #
18
20
  # Depends on lib.sh (require_jq, json_field, ensure_session_dir,
19
21
  # ensure_project_dir, cwd_hash, run_with_timeout, $SESSIONS_LOG) being
20
22
  # discoverable next to this script when it runs — a front door invoking this
21
23
  # canonical script is responsible for making lib.sh resolvable via
22
- # "$(dirname "$0")/lib.sh", exactly as every harness's own SessionStart script
24
+ # the sibling lib.sh, exactly as every harness's own SessionStart script
23
25
  # already required before this policy moved to a shared location.
24
26
 
25
27
  set -euo pipefail
26
28
  # shellcheck source=lib.sh
27
- source "$(dirname "$0")/lib.sh"
28
- require_jq
29
-
29
+ source "$_DOFLOW_POLDIR/lib.sh"
30
30
  INPUT=$(cat)
31
- SESSION_ID=$(json_field "$INPUT" ".session_id")
31
+ POLICY_DIR=$_DOFLOW_POLDIR
32
+ if [ -f "$POLICY_DIR/contract.sh" ]; then
33
+ # shellcheck source=contract.sh
34
+ source "$POLICY_DIR/contract.sh"
35
+ doflow_decision_init session-context 1
36
+ else
37
+ doflow_decision_init() { :; }
38
+ doflow_decide() { :; }
39
+ ( . "$POLICY_DIR/capture-failure.sh"; doflow_capture_failure session-context contract-missing ) >/dev/null 2>&1 || true
40
+ exit 0
41
+ fi
42
+ if ! command -v jq >/dev/null 2>&1; then
43
+ doflow_decide error dependency-missing:jq
44
+ ( . "$POLICY_DIR/capture-failure.sh"; doflow_capture_failure session-context dependency-missing:jq ) >/dev/null 2>&1 || true
45
+ fi
46
+ require_jq
47
+ SESSION_ID="" ENVELOPE_CLASS=missing
48
+ { IFS= read -r -d '' ENVELOPE_CLASS; IFS= read -r -d '' SESSION_ID; } < <(
49
+ printf '%s' "$INPUT" | jq -j 'if ((. | type) != "object") or ((.doflow_event | type) != "object") or ((.doflow_event | has("version")) | not) then "missing" elif ((.doflow_event.version | type) == "number") and .doflow_event.version == 1 then "v1" else "unsupported" end, "\u0000", (.session_id // "" | if type == "string" then rtrimstr("\n") else tojson end), "\u0000"' 2>/dev/null
50
+ ) || true
51
+ ENVELOPE_CLASS=${ENVELOPE_CLASS:-missing}
52
+ if [ ! -f "$POLICY_DIR/contract.sh" ]; then ENVELOPE_CLASS=missing; fi
53
+ if [ "$ENVELOPE_CLASS" = unsupported ] || [ "$ENVELOPE_CLASS" = missing ]; then
54
+ code=envelope-version
55
+ [ "$ENVELOPE_CLASS" = missing ] && code=envelope-missing
56
+ [ -f "$POLICY_DIR/contract.sh" ] || code=contract-missing
57
+ doflow_decide unsupported "$code"
58
+ if [ -f "$POLICY_DIR/contract.sh" ]; then
59
+ ( . "$_DOFLOW_POLDIR/capture-failure.sh"; doflow_capture_failure session-context "$code" ) >/dev/null 2>&1 || true
60
+ fi
61
+ exit 0
62
+ fi
32
63
  CWD=$(json_field "$INPUT" ".cwd")
33
64
 
65
+ package_verify_async() {
66
+ local home="${HOME:-}" lock run config_dir detach=""
67
+ [ -n "$home" ] || return 0
68
+ lock="$home/.doflow/doflow.lock"
69
+ [ -f "$lock" ] || return 0
70
+ jq -e '(.packages // []) | length > 0' "$lock" >/dev/null 2>&1 || return 0
71
+ config_dir="${CLAUDE_CONFIG_DIR:-$home/.claude}"
72
+ command -v setsid >/dev/null 2>&1 && detach="setsid"
73
+ for run in \
74
+ "$home/.doflow/scripts/doflow/bin/doflow-run" \
75
+ "$config_dir/scripts/doflow/bin/doflow-run"
76
+ do
77
+ [ -x "$run" ] || continue
78
+ ( cd "$home/.doflow" 2>/dev/null && nohup $detach "$run" package --action verify </dev/null >/dev/null 2>&1 ) >/dev/null 2>&1 3>&- 5>&- &
79
+ return 0
80
+ done
81
+ return 0
82
+ }
83
+
34
84
  # Guard: if we can't determine the session, nothing to do
35
85
  [[ -z "$SESSION_ID" ]] && exit 0
36
86
 
87
+ # No config home (lib.sh leaves the state paths empty): no session store to write, but the
88
+ # storage upkeep still starts (086 IC-010).
89
+ if [[ -z "$SESSION_DIR" ]]; then
90
+ package_verify_async
91
+ storage_upkeep_async "$CWD"
92
+ exit 0
93
+ fi
94
+
37
95
  SESSION_PATH=$(ensure_session_dir "$SESSION_ID")
38
96
 
39
97
  # Clean up stale injected flag from a prior crashed session
@@ -137,5 +195,6 @@ fi
137
195
  mkdir -p "$(dirname "$SESSIONS_LOG")"
138
196
  echo "$TIMESTAMP START $SESSION_ID ${CWD:-unknown}" >> "$SESSIONS_LOG"
139
197
 
198
+ package_verify_async
140
199
  storage_upkeep_async "$CWD"
141
200
  exit 0