@khoavu882/doflow 0.0.0-stage → 2.0.0-beta.3

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 (407) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -2
  3. package/bin/doflow.js +44 -0
  4. package/core/.antigravity-plugin/hooks.json +39 -0
  5. package/core/.antigravity-plugin/mcp_config.json +18 -0
  6. package/core/.antigravity-plugin/plugin.json +31 -0
  7. package/core/.claude-plugin/marketplace.json +20 -0
  8. package/core/.claude-plugin/plugin.json +21 -0
  9. package/core/.codex-plugin/marketplace.json +20 -0
  10. package/core/.codex-plugin/plugin.json +35 -0
  11. package/core/.plugin/plugin.json +19 -0
  12. package/core/harnesses/antigravity/hooks/pre-implementation-gate.sh +9 -0
  13. package/core/harnesses/antigravity/hooks/stop-check.sh +10 -0
  14. package/core/harnesses/claude/hooks/lib.sh +304 -0
  15. package/core/harnesses/claude/hooks/mcp-tool-guard.sh +20 -0
  16. package/core/harnesses/claude/hooks/permission-audit.sh +47 -0
  17. package/core/harnesses/claude/hooks/post-compact.sh +74 -0
  18. package/core/harnesses/claude/hooks/post-edit-lint.sh +36 -0
  19. package/core/harnesses/claude/hooks/post-tool-failure.sh +47 -0
  20. package/core/harnesses/claude/hooks/pre-bash-guard.sh +20 -0
  21. package/core/harnesses/claude/hooks/pre-compact.sh +43 -0
  22. package/core/harnesses/claude/hooks/pre-implement-gate.sh +21 -0
  23. package/core/harnesses/claude/hooks/session-end.sh +89 -0
  24. package/core/harnesses/claude/hooks/session-start.sh +5 -0
  25. package/core/harnesses/claude/hooks/skill-config-audit.sh +39 -0
  26. package/core/harnesses/claude/hooks/stop-check.sh +5 -0
  27. package/core/harnesses/claude/hooks/subagent-audit.sh +7 -0
  28. package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -0
  29. package/core/harnesses/claude/settings/keybindings.json +20 -0
  30. package/core/harnesses/claude/settings/settings.json +201 -0
  31. package/core/harnesses/claude/statusline/doflow-statusline.sh +49 -0
  32. package/core/harnesses/codex/agents/core-implementer.toml +7 -0
  33. package/core/harnesses/codex/agents/quality-guardian.toml +8 -0
  34. package/core/harnesses/codex/agents/research-writer.toml +8 -0
  35. package/core/harnesses/codex/agents/spec-analyst.toml +8 -0
  36. package/core/harnesses/codex/agents/system-architect.toml +9 -0
  37. package/core/harnesses/codex/config/config.toml +10 -0
  38. package/core/harnesses/codex/hooks/hooks.json +122 -0
  39. package/core/harnesses/codex/hooks/lib.sh +335 -0
  40. package/core/harnesses/codex/hooks/mcp-tool-guard.sh +18 -0
  41. package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +52 -0
  42. package/core/harnesses/codex/hooks/post-edit-lint.sh +6 -0
  43. package/core/harnesses/codex/hooks/pre-bash-guard.sh +18 -0
  44. package/core/harnesses/codex/hooks/pre-compact.impl.sh +46 -0
  45. package/core/harnesses/codex/hooks/pre-compact.sh +9 -0
  46. package/core/harnesses/codex/hooks/pre-implement-gate.sh +19 -0
  47. package/core/harnesses/codex/hooks/session-end.impl.sh +92 -0
  48. package/core/harnesses/codex/hooks/session-end.sh +5 -0
  49. package/core/harnesses/codex/hooks/session-start.sh +5 -0
  50. package/core/harnesses/codex/hooks/stop-check.sh +8 -0
  51. package/core/harnesses/codex/hooks/subagent-audit.sh +8 -0
  52. package/core/harnesses/codex/hooks/user-prompt-submit.sh +6 -0
  53. package/core/harnesses/gemini/hooks/hooks.json +77 -0
  54. package/core/harnesses/gemini/hooks/lib.sh +302 -0
  55. package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +21 -0
  56. package/core/harnesses/gemini/hooks/post-edit-lint.sh +39 -0
  57. package/core/harnesses/gemini/hooks/pre-bash-guard.sh +21 -0
  58. package/core/harnesses/gemini/hooks/pre-compact.sh +38 -0
  59. package/core/harnesses/gemini/hooks/pre-implement-gate.sh +22 -0
  60. package/core/harnesses/gemini/hooks/session-end.impl.sh +89 -0
  61. package/core/harnesses/gemini/hooks/session-end.sh +5 -0
  62. package/core/harnesses/gemini/hooks/session-start.sh +5 -0
  63. package/core/harnesses/gemini/settings/adapter-defaults.json +4 -0
  64. package/core/harnesses/kiro/agents/doflow.json +58 -0
  65. package/core/harnesses/kiro/hooks/doflow.json +53 -0
  66. package/core/harnesses/kiro/hooks/lib.sh +324 -0
  67. package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +9 -0
  68. package/core/harnesses/kiro/hooks/pre-bash-guard.sh +9 -0
  69. package/core/harnesses/kiro/hooks/pre-implement-gate.sh +9 -0
  70. package/core/harnesses/kiro/hooks/session-start.sh +9 -0
  71. package/core/harnesses/kiro/hooks/stop-check.sh +43 -0
  72. package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +39 -0
  73. package/core/harnesses/shared/hooks/adapters/antigravity.js +111 -0
  74. package/core/harnesses/shared/hooks/adapters/arg-fields.js +19 -0
  75. package/core/harnesses/shared/hooks/adapters/gemini.js +114 -0
  76. package/core/harnesses/shared/hooks/hooks.json +47 -0
  77. package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +91 -0
  78. package/core/harnesses/shared/hooks/policies/capture-failure.sh +97 -0
  79. package/core/harnesses/shared/hooks/policies/deny-json.sh +29 -0
  80. package/core/harnesses/shared/hooks/policies/lib.sh +501 -0
  81. package/core/harnesses/shared/hooks/policies/mcp-policy.conf +21 -0
  82. package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +91 -0
  83. package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +328 -0
  84. package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +496 -0
  85. package/core/harnesses/shared/hooks/policies/prompt-nudge.jq +131 -0
  86. package/core/harnesses/shared/hooks/policies/session-context.sh +141 -0
  87. package/core/harnesses/shared/hooks/policies/stop-check.sh +264 -0
  88. package/core/harnesses/shared/hooks/policies/subagent-audit.sh +46 -0
  89. package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +235 -0
  90. package/core/harnesses/shared/hooks/stream-hook-runner.js +590 -0
  91. package/core/harnesses/shared/locator/doflow-run +87 -0
  92. package/core/registry/advice.json +101 -0
  93. package/core/registry/assets.json +792 -0
  94. package/core/registry/capabilities.json +120 -0
  95. package/core/registry/contracts.json +189 -0
  96. package/core/registry/external-tools.json +191 -0
  97. package/core/registry/harnesses.json +2062 -0
  98. package/core/registry/lifecycle.json +231 -0
  99. package/core/registry/mcp.json +18 -0
  100. package/core/registry/models.json +79 -0
  101. package/core/registry/readiness-templates.json +118 -0
  102. package/core/registry/routes.json +47 -0
  103. package/core/registry/storage.json +1057 -0
  104. package/core/registry/verification.json +258 -0
  105. package/core/registry/workflows.json +790 -0
  106. package/core/shared/agent-specs/core-implementer.md +73 -0
  107. package/core/shared/agent-specs/quality-guardian.md +28 -0
  108. package/core/shared/agent-specs/research-writer.md +31 -0
  109. package/core/shared/agent-specs/spec-analyst.md +33 -0
  110. package/core/shared/agent-specs/system-architect.md +29 -0
  111. package/core/shared/guidance/DOFLOW_CORE.md +8 -0
  112. package/core/shared/guidance/FLAGS.md +25 -0
  113. package/core/shared/guidance/PRINCIPLES.md +61 -0
  114. package/core/shared/guidance/VERSION +1 -0
  115. package/core/shared/guidance/mcp/MCP_Context7.md +18 -0
  116. package/core/shared/guidance/mcp/MCP_Sequential.md +17 -0
  117. package/core/shared/guidance/modes/MODE_Brainstorming.md +46 -0
  118. package/core/shared/guidance/modes/MODE_DeepResearch.md +69 -0
  119. package/core/shared/guidance/modes/MODE_Introspection.md +33 -0
  120. package/core/shared/guidance/modes/MODE_Orchestration.md +57 -0
  121. package/core/shared/guidance/modes/MODE_Task_Management.md +74 -0
  122. package/core/shared/guidance/pointers/claude-gemini.md +2 -0
  123. package/core/shared/guidance/pointers/codex.md +6 -0
  124. package/core/shared/guidance/references/ARTIFACT_FORMAT.md +373 -0
  125. package/core/shared/guidance/references/ARTIFACT_VOICE.md +104 -0
  126. package/core/shared/guidance/references/CONSTITUTION_BASE.md +47 -0
  127. package/core/shared/guidance/references/DIAGRAM_GUIDE.md +161 -0
  128. package/core/shared/guidance/references/DOFLOW_CHAIN.md +87 -0
  129. package/core/shared/guidance/references/EVIDENCE_LEDGER.md +93 -0
  130. package/core/shared/guidance/references/MODEL_SELECTION.md +74 -0
  131. package/core/shared/guidance/references/ORCHESTRATION.md +36 -0
  132. package/core/shared/guidance/references/RESEARCH_CONFIG.md +21 -0
  133. package/core/shared/guidance/references/WORKFLOW_HANDOFF.md +81 -0
  134. package/core/shared/guidance/rules/RULE_01_SAFETY.md +25 -0
  135. package/core/shared/guidance/rules/RULE_02_WORKFLOW.md +23 -0
  136. package/core/shared/guidance/rules/RULE_03_QUALITY.md +14 -0
  137. package/core/shared/guidance/rules/RULE_04_QUESTIONS.md +46 -0
  138. package/core/shared/scripts/doflow/assets/mermaid-theme.json +46 -0
  139. package/core/shared/scripts/doflow/bash/do-exec-paths.sh +167 -0
  140. package/core/shared/scripts/doflow/bash/do-git-state.sh +546 -0
  141. package/core/shared/scripts/doflow/bash/do-parallel-check.sh +208 -0
  142. package/core/shared/scripts/doflow/bash/do-paths.sh +347 -0
  143. package/core/shared/scripts/doflow/bash/do-prereqs.sh +66 -0
  144. package/core/shared/scripts/doflow/bash/do-review-package.sh +127 -0
  145. package/core/shared/scripts/doflow/bash/do-task-brief.sh +698 -0
  146. package/core/shared/scripts/doflow/bash/render-audit.sh +224 -0
  147. package/core/shared/scripts/doflow/bash/render-diagrams.sh +177 -0
  148. package/core/shared/scripts/doflow/bash/render-puml.sh +223 -0
  149. package/core/shared/scripts/doflow/bash/sync-context.sh +66 -0
  150. package/core/shared/scripts/doflow/bash/validate-artifacts.sh +526 -0
  151. package/core/shared/scripts/doflow/bin/doflow-run +592 -0
  152. package/core/shared/skills/do/SKILL.md +128 -0
  153. package/core/shared/skills/do/references/estimation.md +13 -0
  154. package/core/shared/skills/do/references/pm_routing.md +25 -0
  155. package/core/shared/skills/do/references/tool_matrix.md +52 -0
  156. package/core/shared/skills/do-brainstorm/SKILL.md +252 -0
  157. package/core/shared/skills/do-code-review/README.md +49 -0
  158. package/core/shared/skills/do-code-review/SKILL.md +333 -0
  159. package/core/shared/skills/do-code-review/assets/sample_c_clean.c +71 -0
  160. package/core/shared/skills/do-code-review/assets/sample_c_smells.c +66 -0
  161. package/core/shared/skills/do-code-review/assets/sample_cpp_shift.cpp +19 -0
  162. package/core/shared/skills/do-code-review/assets/sample_csharp_clean.cs +100 -0
  163. package/core/shared/skills/do-code-review/assets/sample_csharp_smells.cs +78 -0
  164. package/core/shared/skills/do-code-review/assets/sample_java_clean.java +55 -0
  165. package/core/shared/skills/do-code-review/assets/sample_java_smells.java +56 -0
  166. package/core/shared/skills/do-code-review/assets/sample_json_clean.json +7 -0
  167. package/core/shared/skills/do-code-review/assets/sample_markdown_clean.md +30 -0
  168. package/core/shared/skills/do-code-review/assets/sample_markdown_smells.md +29 -0
  169. package/core/shared/skills/do-code-review/assets/sample_shell_heredoc.sh +38 -0
  170. package/core/shared/skills/do-code-review/assets/sample_shell_smells.sh +15 -0
  171. package/core/shared/skills/do-code-review/assets/sample_typescript_strings.ts +36 -0
  172. package/core/shared/skills/do-code-review/assets/sample_yaml_smells.yaml +6 -0
  173. package/core/shared/skills/do-code-review/content-types/config.md +83 -0
  174. package/core/shared/skills/do-code-review/content-types/markdown.md +132 -0
  175. package/core/shared/skills/do-code-review/expected_outputs/sample_c_clean_quality.json +79 -0
  176. package/core/shared/skills/do-code-review/expected_outputs/sample_c_smells_quality.json +169 -0
  177. package/core/shared/skills/do-code-review/expected_outputs/sample_cpp_shift_quality.json +49 -0
  178. package/core/shared/skills/do-code-review/expected_outputs/sample_csharp_clean_quality.json +149 -0
  179. package/core/shared/skills/do-code-review/expected_outputs/sample_csharp_smells_quality.json +157 -0
  180. package/core/shared/skills/do-code-review/expected_outputs/sample_java_clean_quality.json +67 -0
  181. package/core/shared/skills/do-code-review/expected_outputs/sample_java_smells_quality.json +97 -0
  182. package/core/shared/skills/do-code-review/expected_outputs/sample_json_clean_quality.json +33 -0
  183. package/core/shared/skills/do-code-review/expected_outputs/sample_markdown_clean_quality.json +1 -0
  184. package/core/shared/skills/do-code-review/expected_outputs/sample_markdown_smells_quality.json +16 -0
  185. package/core/shared/skills/do-code-review/expected_outputs/sample_shell_heredoc_quality.json +54 -0
  186. package/core/shared/skills/do-code-review/expected_outputs/sample_shell_smells_quality.json +91 -0
  187. package/core/shared/skills/do-code-review/expected_outputs/sample_typescript_strings_quality.json +60 -0
  188. package/core/shared/skills/do-code-review/expected_outputs/sample_yaml_smells_quality.json +46 -0
  189. package/core/shared/skills/do-code-review/languages/c.md +103 -0
  190. package/core/shared/skills/do-code-review/languages/cpp.md +103 -0
  191. package/core/shared/skills/do-code-review/languages/csharp.md +97 -0
  192. package/core/shared/skills/do-code-review/languages/dart.md +108 -0
  193. package/core/shared/skills/do-code-review/languages/go.md +92 -0
  194. package/core/shared/skills/do-code-review/languages/java.md +103 -0
  195. package/core/shared/skills/do-code-review/languages/kotlin.md +88 -0
  196. package/core/shared/skills/do-code-review/languages/php.md +109 -0
  197. package/core/shared/skills/do-code-review/languages/python.md +94 -0
  198. package/core/shared/skills/do-code-review/languages/ruby.md +105 -0
  199. package/core/shared/skills/do-code-review/languages/rust.md +99 -0
  200. package/core/shared/skills/do-code-review/languages/shell.md +90 -0
  201. package/core/shared/skills/do-code-review/languages/swift.md +88 -0
  202. package/core/shared/skills/do-code-review/languages/typescript.md +97 -0
  203. package/core/shared/skills/do-code-review/review-policy.json +47 -0
  204. package/core/shared/skills/do-code-review/rules/universal.md +49 -0
  205. package/core/shared/skills/do-code-review/scripts/code_quality_checker.py +1696 -0
  206. package/core/shared/skills/do-code-review/scripts/doc_quality_checker.py +532 -0
  207. package/core/shared/skills/do-code-review/scripts/pr_analyzer.py +620 -0
  208. package/core/shared/skills/do-code-review/scripts/review_report_generator.py +505 -0
  209. package/core/shared/skills/do-constitution/SKILL.md +72 -0
  210. package/core/shared/skills/do-design/SKILL.md +212 -0
  211. package/core/shared/skills/do-diagnose/SKILL.md +156 -0
  212. package/core/shared/skills/do-diagnose/references/code_audit.md +15 -0
  213. package/core/shared/skills/do-diagnose/references/refactoring.md +12 -0
  214. package/core/shared/skills/do-diagnose/references/root_cause.md +17 -0
  215. package/core/shared/skills/do-document/SKILL.md +81 -0
  216. package/core/shared/skills/do-document/references/api-reference.md +42 -0
  217. package/core/shared/skills/do-document/references/deep_research.md +18 -0
  218. package/core/shared/skills/do-document/references/embedded-research.md +11 -0
  219. package/core/shared/skills/do-document/references/implementation-flow.md +105 -0
  220. package/core/shared/skills/do-document/references/index_generator.md +9 -0
  221. package/core/shared/skills/do-document/references/user-guide.md +22 -0
  222. package/core/shared/skills/do-execute-plan/SKILL.md +261 -0
  223. package/core/shared/skills/do-execute-plan/references/handoff_record.md +57 -0
  224. package/core/shared/skills/do-execute-plan/references/parallel_dispatch.md +92 -0
  225. package/core/shared/skills/do-execute-plan/references/readiness_gate.md +155 -0
  226. package/core/shared/skills/do-execute-plan/references/run_position.md +63 -0
  227. package/core/shared/skills/do-execute-plan/references/scaffold.md +441 -0
  228. package/core/shared/skills/do-execute-plan/references/task_attempts.md +41 -0
  229. package/core/shared/skills/do-flow/SKILL.md +186 -0
  230. package/core/shared/skills/do-flow/references/task_classes.md +134 -0
  231. package/core/shared/skills/do-git/SKILL.md +115 -0
  232. package/core/shared/skills/do-git/references/hotfix-ritual.md +44 -0
  233. package/core/shared/skills/do-git/references/lifecycle-policy.md +54 -0
  234. package/core/shared/skills/do-git/references/release-ritual.md +64 -0
  235. package/core/shared/skills/do-implement/SKILL.md +222 -0
  236. package/core/shared/skills/do-plan/SKILL.md +219 -0
  237. package/core/shared/skills/do-test/SKILL.md +113 -0
  238. package/core/shared/templates/doflow/constitution-template.md +28 -0
  239. package/core/shared/templates/doflow/data-model-template.md +169 -0
  240. package/core/shared/templates/doflow/design-template.md +193 -0
  241. package/core/shared/templates/doflow/external-contract-template.md +35 -0
  242. package/core/shared/templates/doflow/intent-template.md +45 -0
  243. package/core/shared/templates/doflow/plan-template.md +151 -0
  244. package/core/shared/templates/doflow/question-log-template.md +51 -0
  245. package/core/shared/templates/doflow/requirement-template.md +126 -0
  246. package/core/shared/templates/doflow/specs-template.md +55 -0
  247. package/core/shared/templates/doflow/state-template.md +59 -0
  248. package/core/shared/workflows/do-flow-chain.md +17 -0
  249. package/package.json +46 -4
  250. package/src/adapters/antigravity/index.ts +631 -0
  251. package/src/adapters/claude/index.ts +548 -0
  252. package/src/adapters/claude/mcp.ts +94 -0
  253. package/src/adapters/codex/agents.ts +208 -0
  254. package/src/adapters/codex/config.ts +272 -0
  255. package/src/adapters/codex/hooks.ts +203 -0
  256. package/src/adapters/codex/index.ts +707 -0
  257. package/src/adapters/codex/mcp.ts +271 -0
  258. package/src/adapters/codex/native-projection.ts +34 -0
  259. package/src/adapters/copilot/index.ts +413 -0
  260. package/src/adapters/copy-tree.ts +620 -0
  261. package/src/adapters/gemini/hooks.ts +210 -0
  262. package/src/adapters/gemini/index.ts +390 -0
  263. package/src/adapters/hook-commands.ts +60 -0
  264. package/src/adapters/index.ts +106 -0
  265. package/src/adapters/kiro/index.ts +310 -0
  266. package/src/adapters/mcp-entries.ts +331 -0
  267. package/src/adapters/opencode/index.ts +466 -0
  268. package/src/adapters/pi/index.ts +279 -0
  269. package/src/adapters/pi/json-members.ts +185 -0
  270. package/src/adapters/pi/mcp.ts +373 -0
  271. package/src/adapters/resolve-source.ts +19 -0
  272. package/src/cli/commands/install.ts +218 -0
  273. package/src/cli/commands/list-backups.ts +21 -0
  274. package/src/cli/commands/reconcile.ts +120 -0
  275. package/src/cli/commands/remove.ts +82 -0
  276. package/src/cli/commands/rollback.ts +172 -0
  277. package/src/cli/commands/self-update.ts +33 -0
  278. package/src/cli/commands/status.ts +138 -0
  279. package/src/cli/commands/tools.ts +92 -0
  280. package/src/cli/commands/update.ts +162 -0
  281. package/src/cli/index.ts +568 -0
  282. package/src/cli/runtime-commands.ts +281 -0
  283. package/src/cli/shared.ts +218 -0
  284. package/src/helper/bash-helper.ts +34 -0
  285. package/src/helper/git.ts +24 -0
  286. package/src/helper/guardrails.ts +49 -0
  287. package/src/helper/harness-paths.ts +140 -0
  288. package/src/helper/marker-merge.ts +116 -0
  289. package/src/helper/prompt.ts +61 -0
  290. package/src/helper/repo-root.ts +29 -0
  291. package/src/helper/settings-merge.ts +151 -0
  292. package/src/helper/settings-scope.ts +33 -0
  293. package/src/helper/toml.ts +244 -0
  294. package/src/install/backup-set.ts +149 -0
  295. package/src/install/backup.ts +724 -0
  296. package/src/install/context.ts +58 -0
  297. package/src/install/manifest.ts +145 -0
  298. package/src/install/mcp.ts +254 -0
  299. package/src/install/paths.ts +84 -0
  300. package/src/install/targets.ts +90 -0
  301. package/src/install/tool-lifecycle.ts +151 -0
  302. package/src/lifecycle/bash-availability.ts +25 -0
  303. package/src/lifecycle/index.ts +812 -0
  304. package/src/lifecycle/mcp-index.ts +28 -0
  305. package/src/lifecycle/policies.ts +73 -0
  306. package/src/lifecycle/view.ts +175 -0
  307. package/src/registry/index.ts +611 -0
  308. package/src/release/sync-plugin-versions.ts +66 -0
  309. package/src/runtime/advice/cli.ts +283 -0
  310. package/src/runtime/advice/client.ts +324 -0
  311. package/src/runtime/advice/config.ts +189 -0
  312. package/src/runtime/advice/doctor.ts +169 -0
  313. package/src/runtime/advice/endpoint-guard.ts +134 -0
  314. package/src/runtime/advice/kinds.ts +154 -0
  315. package/src/runtime/advice/providers/ollama-systemone.ts +209 -0
  316. package/src/runtime/advice/record.ts +166 -0
  317. package/src/runtime/advice/registry.ts +170 -0
  318. package/src/runtime/advice/strength.ts +66 -0
  319. package/src/runtime/brief-tools.ts +342 -0
  320. package/src/runtime/c4-project.ts +371 -0
  321. package/src/runtime/capability-router.ts +484 -0
  322. package/src/runtime/checkouts.ts +170 -0
  323. package/src/runtime/claims.ts +468 -0
  324. package/src/runtime/cli-result.ts +55 -0
  325. package/src/runtime/cli.ts +678 -0
  326. package/src/runtime/command-detect.ts +516 -0
  327. package/src/runtime/context-pack.ts +492 -0
  328. package/src/runtime/decision-register.ts +493 -0
  329. package/src/runtime/evidence-ledger.ts +338 -0
  330. package/src/runtime/failure/capture.ts +272 -0
  331. package/src/runtime/failure/classifier.ts +68 -0
  332. package/src/runtime/failure/cli.ts +178 -0
  333. package/src/runtime/failure/home.ts +64 -0
  334. package/src/runtime/failure/store.ts +226 -0
  335. package/src/runtime/feature-resolve.ts +79 -0
  336. package/src/runtime/freshness.ts +177 -0
  337. package/src/runtime/health.ts +863 -0
  338. package/src/runtime/history-compactor.ts +237 -0
  339. package/src/runtime/implementation-gate.ts +321 -0
  340. package/src/runtime/inventory/coverage.ts +218 -0
  341. package/src/runtime/inventory/identity.ts +65 -0
  342. package/src/runtime/inventory/index.ts +705 -0
  343. package/src/runtime/inventory/precedence.ts +134 -0
  344. package/src/runtime/inventory/read-scopes.ts +131 -0
  345. package/src/runtime/inventory/siblings.ts +192 -0
  346. package/src/runtime/knowledge/chunker.ts +124 -0
  347. package/src/runtime/knowledge/hybrid.ts +149 -0
  348. package/src/runtime/knowledge/index-store.ts +145 -0
  349. package/src/runtime/knowledge/retrieval.ts +194 -0
  350. package/src/runtime/leak-scan.ts +185 -0
  351. package/src/runtime/lifecycle/cli.ts +276 -0
  352. package/src/runtime/lifecycle/event-store.ts +340 -0
  353. package/src/runtime/lifecycle/fold.ts +353 -0
  354. package/src/runtime/lifecycle/followup.ts +432 -0
  355. package/src/runtime/lifecycle/goal.ts +249 -0
  356. package/src/runtime/lifecycle/intent-writer.ts +86 -0
  357. package/src/runtime/lifecycle/overview.ts +292 -0
  358. package/src/runtime/lifecycle/release.ts +241 -0
  359. package/src/runtime/lifecycle/report-store.ts +221 -0
  360. package/src/runtime/lifecycle/retention.ts +212 -0
  361. package/src/runtime/lifecycle/root.ts +71 -0
  362. package/src/runtime/lifecycle/status.ts +353 -0
  363. package/src/runtime/lifecycle/store-upkeep.ts +393 -0
  364. package/src/runtime/locator-resolve.ts +158 -0
  365. package/src/runtime/mask.ts +210 -0
  366. package/src/runtime/mcp-consultations.ts +412 -0
  367. package/src/runtime/mcp-reach.ts +157 -0
  368. package/src/runtime/model-router.ts +153 -0
  369. package/src/runtime/outcome.ts +467 -0
  370. package/src/runtime/reach.ts +148 -0
  371. package/src/runtime/readiness-record.ts +150 -0
  372. package/src/runtime/readiness.ts +435 -0
  373. package/src/runtime/recovery.ts +282 -0
  374. package/src/runtime/research-request.ts +231 -0
  375. package/src/runtime/retrieval-plan.ts +578 -0
  376. package/src/runtime/scaffold/artifacts.ts +217 -0
  377. package/src/runtime/scaffold/fingerprint.ts +56 -0
  378. package/src/runtime/scaffold/generate.ts +911 -0
  379. package/src/runtime/scaffold/languages.ts +245 -0
  380. package/src/runtime/storage/cli.ts +64 -0
  381. package/src/runtime/storage/engine.ts +249 -0
  382. package/src/runtime/storage/registry.ts +130 -0
  383. package/src/runtime/storage/roots.ts +63 -0
  384. package/src/runtime/storage/rules.ts +282 -0
  385. package/src/runtime/storage/upkeep.ts +243 -0
  386. package/src/runtime/storage/work-status.ts +326 -0
  387. package/src/runtime/task-attempts.ts +415 -0
  388. package/src/runtime/task-classifier.ts +550 -0
  389. package/src/runtime/task-scope.ts +130 -0
  390. package/src/runtime/task-state.ts +176 -0
  391. package/src/runtime/trace/indicators.ts +235 -0
  392. package/src/runtime/trace/ledger.ts +626 -0
  393. package/src/runtime/trace/render.ts +76 -0
  394. package/src/runtime/trace/views.ts +459 -0
  395. package/src/runtime/verification/contract-runner.ts +341 -0
  396. package/src/runtime/verification/engine.ts +1461 -0
  397. package/src/runtime/verification/registry.ts +130 -0
  398. package/src/runtime/verification/scope-bound.ts +418 -0
  399. package/src/runtime/verification/test-selection.ts +172 -0
  400. package/src/runtime/workflow-engine.ts +588 -0
  401. package/src/runtime/workflow-orchestrator.ts +953 -0
  402. package/src/runtime/worktree.ts +340 -0
  403. package/src/state/index.ts +193 -0
  404. package/src/state/lockfile.ts +136 -0
  405. package/src/state/run-lock.ts +408 -0
  406. package/types/node-commonjs.d.ts +68 -0
  407. package/types/runtime.d.ts +91 -0
@@ -0,0 +1,111 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Antigravity payload/decision adapter for the Cross-Harness Hook Runner (design.md C2's
5
+ * Payload Adapter / Decision Adapter seam, D2).
6
+ *
7
+ * Antigravity's own native contracts — evidenced by core/harnesses/antigravity/hooks/*.sh (the
8
+ * shims src/adapters/antigravity/index.js actually projects today) and
9
+ * src/adapters/antigravity/index.js's own GATE_MATCHER/hookGroups — are NOT uniform across
10
+ * events. Only PreToolUse and Stop are wired live there today:
11
+ *
12
+ * PreToolUse : stdin { toolCall: { name, args }, conversationId, workspacePaths, stepIdx }
13
+ * stdout { decision: "allow"|"deny"|"ask"|"force_ask", reason?, overwrite? }
14
+ * Stop : stdin { executionNum, terminationReason, fullyIdle, transcriptPath }
15
+ * stdout { decision: "continue", reason } to block the stop; NO positive field at
16
+ * all (silence) to let it proceed — confirmed by
17
+ * core/harnesses/antigravity/hooks/stop-check.sh's own header ("FAIL-OPEN
18
+ * DOCTRINE... silence lets the session end"). This is a different decision
19
+ * vocabulary than PreToolUse's allow/deny/ask/force_ask, not an oversight.
20
+ *
21
+ * SessionStart and PostToolUse have no dedicated Antigravity-native shim in
22
+ * src/adapters/antigravity/index.js's live projection; core/.antigravity-plugin/hooks.json (a
23
+ * separate, read-only-to-this-task artifact) documents both routed directly to the *Gemini*
24
+ * session-start.sh / post-edit-lint.sh scripts, which read the Claude/Gemini-style
25
+ * session_id/cwd/tool_name/tool_input field names, not the toolCall envelope above — this
26
+ * adapter honors that evidence for those two events rather than guessing at a toolCall shape
27
+ * with no corroborating source. No Phase A canonical policy owns PostToolUse today (only
28
+ * session-context, pre-implementation-gate, mcp-tool-guard, stop-check, pre-bash-guard exist),
29
+ * so its native shape is an ack passthrough either way.
30
+ */
31
+
32
+ const { FILE_PATH_ARG_FIELDS, COMMAND_ARG_FIELDS, firstArgField } = require('./arg-fields');
33
+
34
+ function toCanonical(event, payload) {
35
+ const safePayload = payload && typeof payload === 'object' ? payload : {};
36
+
37
+ switch (event) {
38
+ case 'SessionStart':
39
+ return { session_id: safePayload.session_id || '', cwd: safePayload.cwd || '' };
40
+
41
+ case 'PreToolUse': {
42
+ const toolCall = safePayload.toolCall || {};
43
+ const args = toolCall.args || {};
44
+ return {
45
+ tool_name: toolCall.name || '',
46
+ tool_input: {
47
+ file_path: firstArgField(args, FILE_PATH_ARG_FIELDS),
48
+ command: firstArgField(args, COMMAND_ARG_FIELDS),
49
+ },
50
+ };
51
+ }
52
+
53
+ case 'PostToolUse':
54
+ // No Phase A policy consumes this event — canonical shape kept for symmetry only.
55
+ return {
56
+ tool_name: safePayload.tool_name || '',
57
+ session_id: safePayload.session_id || '',
58
+ tool_input: { file_path: (safePayload.tool_input && safePayload.tool_input.file_path) || '' },
59
+ };
60
+
61
+ case 'Stop':
62
+ return {
63
+ session_id: safePayload.session_id || '',
64
+ transcript_path: safePayload.transcriptPath || safePayload.transcript_path || '',
65
+ };
66
+
67
+ case 'PreInvocation':
68
+ // No Phase A policy — ack only (injectSteps handled entirely in toNative).
69
+ return {};
70
+
71
+ default:
72
+ return safePayload;
73
+ }
74
+ }
75
+
76
+ function toNative(event, decision) {
77
+ const safeDecision = decision || { decision: 'allow' };
78
+
79
+ switch (event) {
80
+ case 'PreToolUse':
81
+ if (safeDecision.decision === 'deny') {
82
+ return { decision: 'deny', reason: safeDecision.reason };
83
+ }
84
+ return { decision: 'allow' };
85
+
86
+ case 'PostToolUse':
87
+ // Preserve the existing empty-ack contract — no policy decision to report.
88
+ return {};
89
+
90
+ case 'Stop':
91
+ if (safeDecision.decision === 'deny') {
92
+ return { decision: 'continue', reason: safeDecision.reason };
93
+ }
94
+ // Silence (no positive field) lets the session stop, per Antigravity's own documented
95
+ // Stop contract — not the allow/deny vocabulary PreToolUse uses.
96
+ return {};
97
+
98
+ case 'PreInvocation':
99
+ return { injectSteps: [] };
100
+
101
+ case 'SessionStart':
102
+ // Side-effect-only event; Antigravity's own SessionStart routing writes no structured
103
+ // stdout today (routed directly to bash, which produces none).
104
+ return {};
105
+
106
+ default:
107
+ return { decision: 'allow' };
108
+ }
109
+ }
110
+
111
+ module.exports = { toCanonical, toNative };
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Shared toolCall.args field-name lookup for the toolCall/args envelope adapters
5
+ * (antigravity.js, gemini.js's fallback path) both read when mapping to canonical
6
+ * file_path/command. Extracted because both adapters carried an identical copy.
7
+ */
8
+
9
+ const FILE_PATH_ARG_FIELDS = ['AbsolutePath', 'TargetFile', 'Path', 'file_path', 'path'];
10
+ const COMMAND_ARG_FIELDS = ['CommandLine', 'command'];
11
+
12
+ function firstArgField(args, fields) {
13
+ for (const field of fields) {
14
+ if (args && args[field]) return args[field];
15
+ }
16
+ return '';
17
+ }
18
+
19
+ module.exports = { FILE_PATH_ARG_FIELDS, COMMAND_ARG_FIELDS, firstArgField };
@@ -0,0 +1,114 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Gemini CLI payload/decision adapter for the Cross-Harness Hook Runner (design.md C2's
5
+ * Payload Adapter / Decision Adapter seam, D2).
6
+ *
7
+ * Gemini's own native contract — evidenced by core/harnesses/gemini/hooks/*.sh and
8
+ * core/harnesses/gemini/hooks/hooks.json, all currently invoked directly by bash rather than
9
+ * through this runner — already speaks field names close to Claude/Codex/Kiro's, NOT
10
+ * Antigravity's toolCall/args envelope:
11
+ *
12
+ * SessionStart : stdin { session_id, cwd } (session-start.sh)
13
+ * BeforeTool (~PreToolUse): stdin { tool_name, tool_input: { file_path, command } }
14
+ * stdout { decision: "allow"|"deny", reason } — TOP-LEVEL, not
15
+ * nested under hookSpecificOutput.permissionDecision like
16
+ * Claude/Codex (confirmed in gemini/hooks/pre-bash-guard.sh's header).
17
+ * AfterTool (~PostToolUse): stdin { tool_name, tool_input: { file_path }, session_id }
18
+ * (post-edit-lint.sh) — stdout {} (ack; no Phase A policy owns this
19
+ * event, post-edit-lint.sh's collector role is out of FR-001's scope)
20
+ * Stop : NOT a documented Gemini lifecycle event — gemini/hooks/
21
+ * post-edit-lint.sh's own comment states "Gemini has no
22
+ * Stop-equivalent event," and no stop-check.sh ships under
23
+ * gemini/hooks/ today. Handled defensively below (same field-name
24
+ * union stop-check.sh itself accepts) in case a future Gemini
25
+ * version adds one, or in case core/harnesses/shared/hooks/hooks.json's
26
+ * existing (currently dangling) Stop entry is corrected to a real target.
27
+ *
28
+ * NFR-002 note: core/harnesses/shared/hooks/hooks.json has historically routed PreToolUse through
29
+ * this runner using Antigravity's { toolCall: { name, args } } envelope — inherited from this
30
+ * runner's original Antigravity-only design (see the runner's own prior header comment), not
31
+ * verified against Gemini's own documented schema above. toCanonical() below reads the
32
+ * tool_name/tool_input shape first (Gemini's own evidenced contract) and falls back to the
33
+ * toolCall envelope only if that shape isn't present, so this adapter is correct once that
34
+ * wiring is corrected without silently breaking before it is.
35
+ */
36
+
37
+ const { FILE_PATH_ARG_FIELDS, COMMAND_ARG_FIELDS, firstArgField } = require('./arg-fields');
38
+
39
+ function toCanonical(event, payload) {
40
+ const safePayload = payload && typeof payload === 'object' ? payload : {};
41
+
42
+ switch (event) {
43
+ case 'SessionStart':
44
+ return { session_id: safePayload.session_id || '', cwd: safePayload.cwd || '' };
45
+
46
+ case 'PreToolUse': {
47
+ if (safePayload.tool_name !== undefined || safePayload.tool_input !== undefined) {
48
+ const toolInput = safePayload.tool_input || {};
49
+ return {
50
+ tool_name: safePayload.tool_name || '',
51
+ tool_input: {
52
+ file_path: toolInput.file_path || '',
53
+ command: toolInput.command || '',
54
+ },
55
+ };
56
+ }
57
+ // Defensive fallback: Antigravity-shaped envelope (see header note).
58
+ const toolCall = safePayload.toolCall || {};
59
+ const args = toolCall.args || {};
60
+ return {
61
+ tool_name: toolCall.name || '',
62
+ tool_input: {
63
+ file_path: firstArgField(args, FILE_PATH_ARG_FIELDS),
64
+ command: firstArgField(args, COMMAND_ARG_FIELDS),
65
+ },
66
+ };
67
+ }
68
+
69
+ case 'PostToolUse':
70
+ return {
71
+ tool_name: safePayload.tool_name || '',
72
+ session_id: safePayload.session_id || '',
73
+ tool_input: { file_path: (safePayload.tool_input && safePayload.tool_input.file_path) || '' },
74
+ };
75
+
76
+ case 'Stop':
77
+ return {
78
+ session_id: safePayload.session_id || '',
79
+ transcript_path: safePayload.transcript_path || safePayload.transcriptPath || '',
80
+ };
81
+
82
+ default:
83
+ return safePayload;
84
+ }
85
+ }
86
+
87
+ function toNative(event, decision) {
88
+ const safeDecision = decision || { decision: 'allow' };
89
+
90
+ switch (event) {
91
+ case 'PreToolUse':
92
+ if (safeDecision.decision === 'deny') {
93
+ return { decision: 'deny', reason: safeDecision.reason };
94
+ }
95
+ return { decision: 'allow' };
96
+
97
+ case 'PostToolUse':
98
+ return {};
99
+
100
+ case 'Stop':
101
+ if (safeDecision.decision === 'deny') {
102
+ return { decision: 'deny', reason: safeDecision.reason };
103
+ }
104
+ return { decision: 'allow' };
105
+
106
+ case 'SessionStart':
107
+ return {};
108
+
109
+ default:
110
+ return { decision: 'allow' };
111
+ }
112
+ }
113
+
114
+ module.exports = { toCanonical, toNative };
@@ -0,0 +1,47 @@
1
+ {
2
+ "description": "DoFlow shared lifecycle hooks schema for Antigravity, Gemini, and Claude.",
3
+ "hooks": {
4
+ "SessionStart": [
5
+ {
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "bash \"$DOFLOW_PROJECT_DIR/.gemini/hooks/session-start.sh\""
10
+ }
11
+ ]
12
+ }
13
+ ],
14
+ "PreToolUse": [
15
+ {
16
+ "matcher": "^(run_command|run_shell_command|replace_file_content|write_to_file|multi_replace_file_content|edit_file|Edit|Write)$",
17
+ "hooks": [
18
+ {
19
+ "type": "command",
20
+ "command": "node \"$DOFLOW_PROJECT_DIR/.doflow/scripts/stream-hook-runner.js\""
21
+ }
22
+ ]
23
+ }
24
+ ],
25
+ "PostToolUse": [
26
+ {
27
+ "matcher": "^(replace_file_content|write_to_file|multi_replace_file_content|edit_file|Edit|Write)$",
28
+ "hooks": [
29
+ {
30
+ "type": "command",
31
+ "command": "bash \"$DOFLOW_PROJECT_DIR/.gemini/hooks/post-edit-lint.sh\""
32
+ }
33
+ ]
34
+ }
35
+ ],
36
+ "Stop": [
37
+ {
38
+ "hooks": [
39
+ {
40
+ "type": "command",
41
+ "command": "bash \"$DOFLOW_PROJECT_DIR/.gemini/hooks/stop-check.sh\""
42
+ }
43
+ ]
44
+ }
45
+ ]
46
+ }
47
+ }
@@ -0,0 +1,91 @@
1
+ # blocked-patterns.conf — Dangerous command patterns for pre-bash-guard.sh
2
+ #
3
+ # Format (TAB-separated):
4
+ # regex<TAB>reason shown to the harness<TAB>exclude_regex (optional)
5
+ #
6
+ # Rules:
7
+ # - Lines beginning with # are comments (skipped)
8
+ # - Empty lines are skipped
9
+ # - Regex is POSIX Extended Regular Expression (ERE, as used by `grep -E`),
10
+ # matched case-insensitively against the full command string (RM and GIT run
11
+ # on a case-insensitive filesystem such as the macOS default), which
12
+ # includes any expanded heredocs or -m "..." arguments. Git and rm
13
+ # patterns use a command-context anchor:
14
+ # (^|[[:space:]]*(&&|\|\||;)[[:space:]]*)
15
+ # so they only fire when the dangerous text is an actual invocation,
16
+ # not when it appears as text inside a commit message or other argument.
17
+ # - Anchored patterns (those beginning with "(^|") are matched against the
18
+ # command with quoted text blanked out (pre-bash-guard.sh scrub_quotes),
19
+ # so echo "x && rm -rf /" or git commit -m "git reset --hard" is not a
20
+ # command. The argument of sh -c, bash -c, zsh -c and eval is NOT blanked
21
+ # (it executes). Every other pattern is matched against the full text.
22
+ # - The rm lines use a wider command position than the others: start of a
23
+ # line or after ; & | ( or a backtick, then optional sudo/command/time/
24
+ # nohup/exec/env (with options, VAR=x and, per wrapper, the options that take
25
+ # a separate argument: sudo -u/-g/-C/-h/-p/-r/-t/-U/-D/-R and --user/--group
26
+ # root, xargs -n/-I/-L/-P/-s/-d/-E/-a, env -u/-C/-S)/xargs/eval/then/do/else, then rm,
27
+ # \rm, /bin/rm or /usr/bin/rm. "git rm" and "echo rm -rf /" are therefore
28
+ # not matched. pre-bash-guard.sh's hardcoded floor uses the same rule.
29
+ # Matching is case-insensitive, so an uppercase flag-only option that shares a
30
+ # letter with a value-taking one (sudo -H beside -h, xargs -p beside -P) is
31
+ # treated as value-taking: a false deny, the fail-safe direction.
32
+ # - The git patterns accept git's global options before the subcommand
33
+ # (git -C dir push, git -c k=v push). The force-push rules block -f (also
34
+ # inside a flag cluster such as -uf), --force and a +refspec; the
35
+ # --force-with-lease form stays allowed, as the reason text advises, but a
36
+ # +refspec still blocks next to a lease (git push --force-with-lease origin +main).
37
+ # - The find rule blocks -delete, and -exec rm, off the root, a home directory
38
+ # or a system directory (among other start paths, find or \find or
39
+ # /usr/bin/find) when only -type, -maxdepth/-mindepth N, -mount, -xdev,
40
+ # -depth, -noleaf, -follow or -ignore_readdir_race follow the path: none of
41
+ # those narrows what is deleted. Any other predicate (-name, -path, -newer,
42
+ # -mtime, -size, -user, -empty ...) counts as scoping, so
43
+ # find ~ -name '*.pyc' -delete is allowed.
44
+ # - SQL patterns are intentionally NOT anchored — DROP/DELETE/TRUNCATE
45
+ # inside heredoc-to-psql pipelines are real execution and must be caught.
46
+ # - The optional third column is an exclude_regex: when present and the
47
+ # command ALSO matches it, the pattern line is skipped (not blocked).
48
+ # This is how negative-lookahead behavior (unsupported in POSIX ERE) is
49
+ # approximated — e.g. "git push --force" blocks force pushes, but the
50
+ # exclude_regex "--force-with-lease" lets that safer variant through.
51
+ # - First matching pattern wins — order matters
52
+ # - A malformed regex on any line is skipped (guard continues safely)
53
+ #
54
+ # Add project-specific patterns at the bottom of this file.
55
+
56
+ # ── Dangerous git operations ──────────────────────────────────────────────────
57
+ (^|[[:space:]]*(&&|\|\||;)[[:space:]]*)git([[:space:]]+(-[Cc][[:space:]]+[^[:space:];&|]+|--(git-dir|work-tree|namespace|exec-path)[[:space:]]+[^[:space:];&|]+|-[^[:space:];&|]+))*[[:space:]]+push([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(--force|-[a-zA-Z]*f[a-zA-Z]*)([^-[:alnum:]]|$) Force push blocked — use --force-with-lease or confirm with user first
58
+ (^|[[:space:]]*(&&|\|\||;)[[:space:]]*)git([[:space:]]+(-[Cc][[:space:]]+[^[:space:];&|]+|--(git-dir|work-tree|namespace|exec-path)[[:space:]]+[^[:space:];&|]+|-[^[:space:];&|]+))*[[:space:]]+push([[:space:]]+[^[:space:];&|]+)*[[:space:]]+\+[^[:space:];&|]+ Force push blocked — use --force-with-lease or confirm with user first
59
+ (^|[[:space:]]*(&&|\|\||;)[[:space:]]*)git([[:space:]]+(-[Cc][[:space:]]+[^[:space:];&|]+|--(git-dir|work-tree|namespace|exec-path)[[:space:]]+[^[:space:];&|]+|-[^[:space:];&|]+))*[[:space:]]+reset --hard Destructive reset blocked — commit or stash changes before resetting
60
+ (^|[[:space:]]*(&&|\|\||;)[[:space:]]*)git([[:space:]]+(-[Cc][[:space:]]+[^[:space:];&|]+|--(git-dir|work-tree|namespace|exec-path)[[:space:]]+[^[:space:];&|]+|-[^[:space:];&|]+))*[[:space:]]+clean -fd Irreversible clean blocked — use --dry-run to preview what would be deleted
61
+
62
+ # ── Filesystem catastrophes ───────────────────────────────────────────────────
63
+ (^|[;&|(`])[[:space:]]*((sudo([[:space:]]+(-[ugChprtUDR][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|--(user|group|host|prompt|role|type|chdir)[[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|xargs([[:space:]]+(-[nILPsdEa][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|env([[:space:]]+(-[uCS][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|(command|time|nohup|exec|eval|then|do|else)([[:space:]]+(-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*)[[:space:]]+)*(\\|/(usr/)?bin/)?rm([[:space:]]+[^[:space:];&|]+)*[[:space:]]+((-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(/+\*{0,2})([[:space:];&|)`]|$)|(/+\*{0,2})([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:];&|)`]|$)) Catastrophic delete blocked — recursive rm of the root directory (/)
64
+ (^|[;&|(`])[[:space:]]*((sudo([[:space:]]+(-[ugChprtUDR][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|--(user|group|host|prompt|role|type|chdir)[[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|xargs([[:space:]]+(-[nILPsdEa][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|env([[:space:]]+(-[uCS][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|(command|time|nohup|exec|eval|then|do|else)([[:space:]]+(-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*)[[:space:]]+)*(\\|/(usr/)?bin/)?rm([[:space:]]+[^[:space:];&|]+)*[[:space:]]+((-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:]]+[^[:space:];&|]+)*[[:space:]]+((~[A-Za-z_][A-Za-z0-9_.-]*|~|\$HOME|\$\{HOME\})(/\*{0,2})?)([[:space:];&|)`]|$)|((~[A-Za-z_][A-Za-z0-9_.-]*|~|\$HOME|\$\{HOME\})(/\*{0,2})?)([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:];&|)`]|$)) Catastrophic delete blocked — recursive rm of the home directory
65
+ (^|[;&|(`])[[:space:]]*((sudo([[:space:]]+(-[ugChprtUDR][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|--(user|group|host|prompt|role|type|chdir)[[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|xargs([[:space:]]+(-[nILPsdEa][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|env([[:space:]]+(-[uCS][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|(command|time|nohup|exec|eval|then|do|else)([[:space:]]+(-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*)[[:space:]]+)*(\\|/(usr/)?bin/)?rm([[:space:]]+[^[:space:];&|]+)*[[:space:]]+((-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(/(Users|home|etc|usr|bin|sbin|var|opt|System|Library|Applications|Volumes|private|root|boot|lib|dev|proc)(/\*{0,2})?)([[:space:];&|)`]|$)|(/(Users|home|etc|usr|bin|sbin|var|opt|System|Library|Applications|Volumes|private|root|boot|lib|dev|proc)(/\*{0,2})?)([[:space:]]+[^[:space:];&|]+)*[[:space:]]+(-[a-zA-Z]*[rR][a-zA-Z]*|--recursive)([[:space:];&|)`]|$)) Catastrophic delete blocked — recursive rm of a system directory
66
+ (^|[;&|(`])[[:space:]]*((sudo([[:space:]]+(-[ugChprtUDR][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|--(user|group|host|prompt|role|type|chdir)[[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|xargs([[:space:]]+(-[nILPsdEa][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|env([[:space:]]+(-[uCS][[:space:]]+[^-[:space:];&|][^[:space:];&|]*|-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*|(command|time|nohup|exec|eval|then|do|else)([[:space:]]+(-[^[:space:];&|]*|[A-Za-z_][A-Za-z0-9_]*=[^[:space:];&|]*))*)[[:space:]]+)*(\\|/(usr/)?bin/)?find([[:space:]]+-[HLP])*([[:space:]]+[^-[:space:];&|][^[:space:];&|]*)*[[:space:]]+(/+\*{0,2}|(~[A-Za-z_][A-Za-z0-9_.-]*|~|\$HOME|\$\{HOME\})(/\*{0,2})?|/(Users|home|etc|usr|bin|sbin|var|opt|System|Library|Applications|Volumes|private|root|boot|lib|dev|proc)(/\*{0,2})?)([[:space:]]+([^-[:space:];&|][^[:space:];&|]*|-(mount|xdev|depth|noleaf|follow|ignore_readdir_race)|-(type|maxdepth|mindepth)[[:space:]]+[^[:space:];&|]+))*[[:space:]]+(-delete([[:space:];&|)`]|$)|-exec(dir)?[[:space:]]+(\\|/(usr/)?bin/)?rm([[:space:];&|)`]|$)) Catastrophic delete blocked — find -delete or -exec rm from the root, home or a system directory with no name, path or time predicate to scope it
67
+
68
+ # ── SQL destructive statements (no anchor — must catch inside psql heredocs) ──
69
+ DROP[[:space:]]+(TABLE|DATABASE|SCHEMA)[[:space:]] Destructive DDL blocked — confirm with user before dropping
70
+ DELETE[[:space:]]+FROM[[:space:]]+[[:alnum:]_]+[[:space:]]*; Unscoped DELETE blocked — this would affect all rows, add a WHERE clause
71
+ TRUNCATE[[:space:]]+TABLE Irreversible truncate blocked — confirm with user before truncating
72
+
73
+ # ── Code execution from untrusted network sources ─────────────────────────────
74
+ (^|[[:space:]]*(&&|\|\||;)[[:space:]]*)(curl|wget)[[:space:]]+[^[:space:]]+.*\|[[:space:]]*(ba)?sh Pipe-to-shell blocked — download and review the script before executing
75
+
76
+ # ── Broad permission grants ───────────────────────────────────────────────────
77
+ (^|[[:space:]]*(&&|\|\||;)[[:space:]]*)chmod[[:space:]]+-R[[:space:]]+777 chmod -R 777 blocked — grants world-write access recursively; use targeted permissions (e.g. chmod 755) instead
78
+
79
+ # ── Disk device operations ────────────────────────────────────────────────────
80
+ (^|[[:space:]]*(&&|\|\||;)[[:space:]]*)dd[[:space:]]+if=/dev/ dd from block device blocked — can wipe or clone disks; confirm with user before any raw device operation
81
+
82
+ # ── Known limitation (not a pattern — comment only) ──────────────────────────
83
+ # eval-based indirection (e.g. CMD="git push --force"; eval "$CMD") bypasses all
84
+ # static pattern matching above. This is an inherent limitation of text-based
85
+ # guards. For high-security environments, supplement with branch protection
86
+ # rules and code review rather than relying solely on this guard.
87
+ #
88
+ # Variables other than HOME ($B, "$DIR") are not blocked: an empty or unset
89
+ # variable cannot be known statically, so rm -rf "$B"/ is allowed. Only the
90
+ # literal targets in the rm rule above are judged (root, home, and the system
91
+ # directories listed; subpaths such as /tmp/x or /Users/kai/x are allowed).
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env bash
2
+ # capture-failure.sh — Canonical Policy Library: failure capture helper (feature 046, IC-018, DEC-032)
3
+ #
4
+ # Defines doflow_capture_failure <policy> <point>, which appends one IC-011 line to the machine-wide
5
+ # DoFlow failure list when a guard policy fails open because DoFlow's own install is broken (for
6
+ # example its pattern file is missing). It exists only to be sourced, in a subshell with all output
7
+ # discarded, from inside a branch where the policy already fails open:
8
+ #
9
+ # ( . "$(dirname "$0")/capture-failure.sh"; doflow_capture_failure pre-bash-guard patterns-missing ) >/dev/null 2>&1 || true
10
+ #
11
+ # The subshell keeps anything this file does away from the policy, which runs with `set -uo pipefail`,
12
+ # does not source lib.sh and would change exit codes under `set -e`. So this file:
13
+ # - sets no shell option and installs no trap (DEC-018), and is written to be safe under the
14
+ # caller's `set -u` and `pipefail`;
15
+ # - reads no stdin and writes nothing to stdout or stderr;
16
+ # - never rotates the file (rotation is done by the Node writers only, DEC-019);
17
+ # - never blocks, never changes the policy's decision, and swallows every error.
18
+ # The line holds only the policy name and the point name from DoFlow's own code, the working
19
+ # directory, the harness name and the install version: never the tool call, its arguments or stdin.
20
+ # It is a no-op when no failure home can be resolved (HOME unset, or XDG_CONFIG_HOME relative) and
21
+ # while capture is off (the `off` sentinel file wins; DOFLOW_FAILURE_CAPTURE=off|0|false|no also
22
+ # turns it off), the same rules the Node writer follows (IC-011, IC-014).
23
+
24
+ doflow_capture_failure() {
25
+ local policy="${1:-}" point="${2:-}"
26
+ local LC_ALL=C # byte-wise lengths and cuts; scoped to this function
27
+ local home="" setting="" version="" harness="" project="" cwd="" hp="" at="" line="" here="" dir=""
28
+
29
+ if [ -n "${XDG_CONFIG_HOME:-}" ]; then
30
+ case "$XDG_CONFIG_HOME" in
31
+ /*) home="$XDG_CONFIG_HOME/doflow/failures" ;;
32
+ *) return 0 ;;
33
+ esac
34
+ else
35
+ case "${HOME:-}" in
36
+ /*) home="$HOME/.config/doflow/failures" ;;
37
+ *) return 0 ;;
38
+ esac
39
+ fi
40
+
41
+ # Case-insensitive, whitespace trimmed at the ends only: the same reading the Node writer has.
42
+ setting="$(printf '%s' "${DOFLOW_FAILURE_CAPTURE:-}" | tr '[:upper:]' '[:lower:]')" || return 0
43
+ setting="${setting#"${setting%%[![:space:]]*}"}"
44
+ setting="${setting%"${setting##*[![:space:]]}"}"
45
+ case "$setting" in
46
+ off|0|false|no) return 0 ;;
47
+ esac
48
+ [ -f "$home/off" ] && return 0
49
+
50
+ [[ "$policy" =~ ^[a-z][a-z0-9-]{0,39}$ ]] || policy="unknown"
51
+ [[ "$point" =~ ^[A-Za-z][A-Za-z0-9._:-]{0,39}$ ]] || return 0
52
+
53
+ harness="${DOFLOW_AGENT:-}"
54
+ [[ "$harness" =~ ^[A-Za-z0-9._-]{1,40}$ ]] || harness="none"
55
+
56
+ # script_version of the nearest install manifest: walking up from this file, then the global one.
57
+ here="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd -P)" || here=""
58
+ dir="$here"
59
+ while [ -n "$dir" ] && [ -z "$version" ]; do
60
+ if [ -f "$dir/.doflow/.install-manifest.json" ]; then
61
+ version="$(sed -n 's/^[[:space:]]*"script_version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$dir/.doflow/.install-manifest.json" | head -n 1)" || version=""
62
+ fi
63
+ [ "$dir" = "/" ] && break
64
+ dir="$(dirname "$dir")"
65
+ done
66
+ if [ -z "$version" ] && [ -f "${HOME:-}/.doflow/.install-manifest.json" ]; then
67
+ version="$(sed -n 's/^[[:space:]]*"script_version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' "$HOME/.doflow/.install-manifest.json" | head -n 1)" || version=""
68
+ fi
69
+ [[ "$version" =~ ^[A-Za-z0-9._+-]{1,40}$ ]] || version="unknown"
70
+
71
+ # The working directory with the home prefix as `~`, cut to 200 bytes, control characters turned
72
+ # into spaces and every quote and backslash escaped, so the line stays one valid JSON string.
73
+ cwd="$(pwd 2>/dev/null)" || cwd=""
74
+ hp="${HOME:-}"
75
+ hp="${hp%/}"
76
+ if [ -n "$hp" ]; then
77
+ case "$cwd" in
78
+ "$hp") cwd="~" ;;
79
+ "$hp"/*) cwd="~${cwd#"$hp"}" ;;
80
+ esac
81
+ fi
82
+ project="$(printf '%s' "${cwd:0:200}" | tr '\001-\037\177' ' ')" || project=""
83
+ project="${project//\\/\\\\}"
84
+ project="${project//\"/\\\"}"
85
+
86
+ at="$(date -u +%Y-%m-%dT%H:%M:%S.000Z)" || return 0
87
+ line="{\"v\":1,\"at\":\"$at\",\"source\":\"hook\",\"command\":\"$policy\",\"harness\":\"$harness\",\"version\":\"$version\",\"project\":\"$project\",\"kind\":\"$point\",\"message\":\"\",\"frame\":null,\"exit\":null}"
88
+ if [ "${#line}" -gt 999 ]; then
89
+ line="{\"v\":1,\"at\":\"$at\",\"source\":\"hook\",\"command\":\"$policy\",\"harness\":\"$harness\",\"version\":\"$version\",\"project\":\"\",\"kind\":\"$point\",\"message\":\"\",\"frame\":null,\"exit\":null}"
90
+ fi
91
+
92
+ (umask 077; mkdir -p "$home") || return 0
93
+ # Only ever append to a regular file: opening a FIFO for append would block forever.
94
+ [ ! -e "$home/events.jsonl" ] || [ -f "$home/events.jsonl" ] || return 0
95
+ ( umask 077; printf '%s\n' "$line" >>"$home/events.jsonl" ) || return 0
96
+ return 0
97
+ }
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env bash
2
+ # deny-json.sh — shared PreToolUse deny-JSON emitters for front-door dispatchers.
3
+ #
4
+ # Deliberately carries no `set` directive (unlike lib.sh, which sets -euo
5
+ # pipefail on source): a front door needs `set -e` OFF while it captures a
6
+ # policy script's exit code via `REASON=$(bash "$POLICY" ...); CODE=$?` — under
7
+ # `set -e` that assignment's own nonzero exit status (the deny case) would abort
8
+ # the front door right there, before it ever reached the code below that emits
9
+ # the deny JSON. Sourcing this file must never change the caller's shell options.
10
+ #
11
+ # Usage: source "$(dirname "$0")/../../shared/hooks/policies/deny-json.sh"
12
+
13
+ # Claude/Codex shape: nested under hookSpecificOutput.permissionDecision.
14
+ emit_pretooluse_deny_nested() {
15
+ local reason="$1"
16
+ jq -n --arg reason "$reason" '{
17
+ hookSpecificOutput: {
18
+ hookEventName: "PreToolUse",
19
+ permissionDecision: "deny",
20
+ permissionDecisionReason: $reason
21
+ }
22
+ }'
23
+ }
24
+
25
+ # Gemini shape: flat {decision, reason} (packages/core/src/hooks/types.ts).
26
+ emit_pretooluse_deny_flat() {
27
+ local reason="$1"
28
+ jq -n --arg reason "$reason" '{decision: "deny", reason: $reason}'
29
+ }