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

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 (409) 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 +1061 -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 +48 -4
  250. package/src/adapters/antigravity/index.js +631 -0
  251. package/src/adapters/claude/index.js +548 -0
  252. package/src/adapters/claude/mcp.js +94 -0
  253. package/src/adapters/codex/agents.js +208 -0
  254. package/src/adapters/codex/config.js +272 -0
  255. package/src/adapters/codex/hooks.js +203 -0
  256. package/src/adapters/codex/index.js +707 -0
  257. package/src/adapters/codex/mcp.js +271 -0
  258. package/src/adapters/codex/native-projection.js +34 -0
  259. package/src/adapters/copilot/index.js +413 -0
  260. package/src/adapters/copy-tree.js +620 -0
  261. package/src/adapters/gemini/hooks.js +210 -0
  262. package/src/adapters/gemini/index.js +390 -0
  263. package/src/adapters/hook-commands.js +60 -0
  264. package/src/adapters/index.js +106 -0
  265. package/src/adapters/kiro/index.js +310 -0
  266. package/src/adapters/mcp-entries.js +331 -0
  267. package/src/adapters/opencode/index.js +466 -0
  268. package/src/adapters/pi/index.js +279 -0
  269. package/src/adapters/pi/json-members.js +185 -0
  270. package/src/adapters/pi/mcp.js +373 -0
  271. package/src/adapters/resolve-source.js +19 -0
  272. package/src/cli/commands/install.js +218 -0
  273. package/src/cli/commands/list-backups.js +21 -0
  274. package/src/cli/commands/reconcile.js +120 -0
  275. package/src/cli/commands/remove.js +82 -0
  276. package/src/cli/commands/rollback.js +172 -0
  277. package/src/cli/commands/self-update.js +33 -0
  278. package/src/cli/commands/status.js +138 -0
  279. package/src/cli/commands/tools.js +92 -0
  280. package/src/cli/commands/update.js +162 -0
  281. package/src/cli/index.js +568 -0
  282. package/src/cli/runtime-commands.js +281 -0
  283. package/src/cli/shared.js +218 -0
  284. package/src/helper/bash-helper.js +34 -0
  285. package/src/helper/git.js +24 -0
  286. package/src/helper/guardrails.js +49 -0
  287. package/src/helper/harness-paths.js +140 -0
  288. package/src/helper/marker-merge.js +116 -0
  289. package/src/helper/prompt.js +61 -0
  290. package/src/helper/repo-root.js +29 -0
  291. package/src/helper/settings-merge.js +151 -0
  292. package/src/helper/settings-scope.js +33 -0
  293. package/src/helper/toml.js +244 -0
  294. package/src/install/backup-set.js +149 -0
  295. package/src/install/backup.js +724 -0
  296. package/src/install/context.js +58 -0
  297. package/src/install/manifest.js +145 -0
  298. package/src/install/mcp.js +254 -0
  299. package/src/install/paths.js +84 -0
  300. package/src/install/targets.js +90 -0
  301. package/src/install/tool-lifecycle.js +151 -0
  302. package/src/lifecycle/bash-availability.js +25 -0
  303. package/src/lifecycle/index.js +812 -0
  304. package/src/lifecycle/mcp-index.js +28 -0
  305. package/src/lifecycle/policies.js +73 -0
  306. package/src/lifecycle/view.js +175 -0
  307. package/src/registry/index.js +611 -0
  308. package/src/release/build-package.js +91 -0
  309. package/src/release/changelog-section.js +70 -0
  310. package/src/release/sync-plugin-versions.js +66 -0
  311. package/src/runtime/advice/cli.js +283 -0
  312. package/src/runtime/advice/client.js +324 -0
  313. package/src/runtime/advice/config.js +189 -0
  314. package/src/runtime/advice/doctor.js +169 -0
  315. package/src/runtime/advice/endpoint-guard.js +134 -0
  316. package/src/runtime/advice/kinds.js +154 -0
  317. package/src/runtime/advice/providers/ollama-systemone.js +209 -0
  318. package/src/runtime/advice/record.js +166 -0
  319. package/src/runtime/advice/registry.js +170 -0
  320. package/src/runtime/advice/strength.js +66 -0
  321. package/src/runtime/brief-tools.js +342 -0
  322. package/src/runtime/c4-project.js +371 -0
  323. package/src/runtime/capability-router.js +484 -0
  324. package/src/runtime/checkouts.js +170 -0
  325. package/src/runtime/claims.js +468 -0
  326. package/src/runtime/cli-result.js +55 -0
  327. package/src/runtime/cli.js +678 -0
  328. package/src/runtime/command-detect.js +516 -0
  329. package/src/runtime/context-pack.js +492 -0
  330. package/src/runtime/decision-register.js +493 -0
  331. package/src/runtime/evidence-ledger.js +338 -0
  332. package/src/runtime/failure/capture.js +272 -0
  333. package/src/runtime/failure/classifier.js +68 -0
  334. package/src/runtime/failure/cli.js +178 -0
  335. package/src/runtime/failure/home.js +64 -0
  336. package/src/runtime/failure/store.js +226 -0
  337. package/src/runtime/feature-resolve.js +79 -0
  338. package/src/runtime/freshness.js +177 -0
  339. package/src/runtime/health.js +863 -0
  340. package/src/runtime/history-compactor.js +237 -0
  341. package/src/runtime/implementation-gate.js +321 -0
  342. package/src/runtime/inventory/coverage.js +218 -0
  343. package/src/runtime/inventory/identity.js +65 -0
  344. package/src/runtime/inventory/index.js +705 -0
  345. package/src/runtime/inventory/precedence.js +134 -0
  346. package/src/runtime/inventory/read-scopes.js +131 -0
  347. package/src/runtime/inventory/siblings.js +192 -0
  348. package/src/runtime/knowledge/chunker.js +124 -0
  349. package/src/runtime/knowledge/hybrid.js +149 -0
  350. package/src/runtime/knowledge/index-store.js +145 -0
  351. package/src/runtime/knowledge/retrieval.js +194 -0
  352. package/src/runtime/leak-scan.js +185 -0
  353. package/src/runtime/lifecycle/cli.js +276 -0
  354. package/src/runtime/lifecycle/event-store.js +340 -0
  355. package/src/runtime/lifecycle/fold.js +353 -0
  356. package/src/runtime/lifecycle/followup.js +432 -0
  357. package/src/runtime/lifecycle/goal.js +249 -0
  358. package/src/runtime/lifecycle/intent-writer.js +86 -0
  359. package/src/runtime/lifecycle/overview.js +292 -0
  360. package/src/runtime/lifecycle/release.js +241 -0
  361. package/src/runtime/lifecycle/report-store.js +221 -0
  362. package/src/runtime/lifecycle/retention.js +212 -0
  363. package/src/runtime/lifecycle/root.js +71 -0
  364. package/src/runtime/lifecycle/status.js +353 -0
  365. package/src/runtime/lifecycle/store-upkeep.js +393 -0
  366. package/src/runtime/locator-resolve.js +158 -0
  367. package/src/runtime/mask.js +210 -0
  368. package/src/runtime/mcp-consultations.js +412 -0
  369. package/src/runtime/mcp-reach.js +157 -0
  370. package/src/runtime/model-router.js +153 -0
  371. package/src/runtime/outcome.js +467 -0
  372. package/src/runtime/reach.js +148 -0
  373. package/src/runtime/readiness-record.js +150 -0
  374. package/src/runtime/readiness.js +435 -0
  375. package/src/runtime/recovery.js +282 -0
  376. package/src/runtime/research-request.js +231 -0
  377. package/src/runtime/retrieval-plan.js +578 -0
  378. package/src/runtime/scaffold/artifacts.js +217 -0
  379. package/src/runtime/scaffold/fingerprint.js +56 -0
  380. package/src/runtime/scaffold/generate.js +911 -0
  381. package/src/runtime/scaffold/languages.js +245 -0
  382. package/src/runtime/storage/cli.js +64 -0
  383. package/src/runtime/storage/engine.js +249 -0
  384. package/src/runtime/storage/registry.js +130 -0
  385. package/src/runtime/storage/roots.js +63 -0
  386. package/src/runtime/storage/rules.js +282 -0
  387. package/src/runtime/storage/upkeep.js +243 -0
  388. package/src/runtime/storage/work-status.js +326 -0
  389. package/src/runtime/task-attempts.js +415 -0
  390. package/src/runtime/task-classifier.js +550 -0
  391. package/src/runtime/task-scope.js +130 -0
  392. package/src/runtime/task-state.js +176 -0
  393. package/src/runtime/trace/indicators.js +235 -0
  394. package/src/runtime/trace/ledger.js +626 -0
  395. package/src/runtime/trace/render.js +76 -0
  396. package/src/runtime/trace/views.js +459 -0
  397. package/src/runtime/verification/contract-runner.js +341 -0
  398. package/src/runtime/verification/engine.js +1461 -0
  399. package/src/runtime/verification/registry.js +130 -0
  400. package/src/runtime/verification/scope-bound.js +418 -0
  401. package/src/runtime/verification/test-selection.js +172 -0
  402. package/src/runtime/workflow-engine.js +588 -0
  403. package/src/runtime/workflow-orchestrator.js +953 -0
  404. package/src/runtime/worktree.js +340 -0
  405. package/src/state/index.js +193 -0
  406. package/src/state/lockfile.js +136 -0
  407. package/src/state/run-lock.js +408 -0
  408. package/types/node-commonjs.d.ts +68 -0
  409. package/types/runtime.d.ts +91 -0
@@ -0,0 +1,408 @@
1
+ 'use strict';
2
+
3
+ // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
+
5
+ // run.lock — one DoFlow run at a time per scope. install, update, remove, reconcile and rollback
6
+ // read the ledger, doflow.lock and the install manifest, decide, and write them back; two runs in
7
+ // one scope interleaving those steps lose each other's rows. The lock serialises them.
8
+ //
9
+ // Taking it: the owner record goes into a private temp file first and is then hard-linked to
10
+ // run.lock, so the lock never exists half-written and a second link fails with EEXIST. Removing
11
+ // it, whether a holder releasing its own or a run clearing a stale one, happens only under a claim
12
+ // file named for the lock instance being removed (`run.lock.claim.<instance>`, created with `wx`),
13
+ // and only after re-reading run.lock under that claim and finding the same instance. One instance
14
+ // is therefore removed at most once, and never by a run that inspected a different one.
15
+ //
16
+ // Supported on a local POSIX filesystem on one host. The CLI is synchronous, so waiting blocks
17
+ // with Atomics.wait rather than a timer.
18
+ const crypto = require('node:crypto');
19
+ const fs = require('node:fs');
20
+ const os = require('node:os');
21
+ const path = require('node:path');
22
+
23
+ const RECORD_VERSION = 1;
24
+ const LOCK_FILE = 'run.lock';
25
+ const CLAIM_PREFIX = `${LOCK_FILE}.claim.`;
26
+ const TEMP_NAME = /^\.run\.lock\.([0-9a-f]{32})\.tmp$/;
27
+
28
+ function loadVersion() {
29
+ try { return require('../../package.json').version; } catch { return '0.0.0-installed'; }
30
+ }
31
+ const DOFLOW_VERSION = loadVersion();
32
+
33
+ /** Holds of this process, by resolved scope root: a nested acquisition counts instead of waiting on itself. */
34
+ const held = new Map ();
35
+
36
+ function runLockPath(scopeRoot ) { return path.join(path.resolve(scopeRoot), '.doflow', 'state', LOCK_FILE); }
37
+
38
+ function atomicsSleep(ms ) {
39
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
40
+ }
41
+
42
+ /** Alive when signal 0 reaches it, or it exists but belongs to someone else (EPERM). */
43
+ function defaultIsAlive(pid ) {
44
+ if (!Number.isInteger(pid) || pid <= 0) return false;
45
+ try {
46
+ process.kill(pid, 0);
47
+ return true;
48
+ } catch (err ) {
49
+ return err.code === 'EPERM';
50
+ }
51
+ }
52
+
53
+ function scopeLabel({ scope, scopeRoot } ) {
54
+ return scope === 'global' ? `global scope (${scopeRoot})` : `project ${scopeRoot}`;
55
+ }
56
+
57
+ function holderLabel(holder ) {
58
+ return holder ? `pid ${holder.pid}, ${holder.command}, started ${holder.startedAt}` : 'holder unknown';
59
+ }
60
+
61
+ const STALE_REASONS = Object.freeze({ 'not-running': 'that process is not running', expired: 'it is older than 10 minutes' });
62
+
63
+ /**
64
+ * The one text of every run-lock line, so the CLI prints exactly these.
65
+ * @param {'waiting'|'cleared'|'timeout'|'lost'|'error'} kind
66
+ * @param {{scope: string, scopeRoot: string, holder?: Object|null, waitMs?: number, reason?: string,
67
+ * lockPath?: string, waitedMs?: number, code?: string}} details
68
+ */
69
+ function formatRunLockMessage(kind , details ) {
70
+ const where = scopeLabel(details);
71
+ switch (kind) {
72
+ case 'waiting':
73
+ return `[INFO] Waiting for another DoFlow run in ${where} (${holderLabel(details.holder)}); up to ${details.waitMs / 1000}s`;
74
+ case 'cleared':
75
+ return `[WARN] Cleared a stale DoFlow run lock in ${where} (${holderLabel(details.holder)}): ${STALE_REASONS[details.reason]}`;
76
+ case 'timeout':
77
+ return `[ERROR] Another DoFlow run in ${where} (${holderLabel(details.holder)}) still holds ${details.lockPath} after ${Math.round(details.waitedMs / 1000)}s. Nothing was changed. Run the command again when it finishes; a lock whose process has exited is cleared automatically.`;
78
+ case 'lost':
79
+ return `[ERROR] This run's lock in ${where} was taken over by another DoFlow run while it waited; nothing was changed. Run the command again.`;
80
+ case 'error':
81
+ return `[ERROR] Cannot take the DoFlow run lock ${details.lockPath}: ${details.code}. Nothing was changed.`;
82
+ default:
83
+ throw new Error(`Unknown run-lock message kind: '${kind}'`);
84
+ }
85
+ }
86
+
87
+ class RunLockError extends Error {
88
+ constructor(details ) {
89
+ super(formatRunLockMessage('error', details));
90
+ this.name = 'RunLockError';
91
+ Object.assign(this, { code: details.code, lockPath: details.lockPath, scopeRoot: details.scopeRoot });
92
+ }
93
+ }
94
+
95
+ class RunLockTimeoutError extends Error {
96
+ constructor(details ) {
97
+ super(formatRunLockMessage('timeout', details));
98
+ this.name = 'RunLockTimeoutError';
99
+ Object.assign(this, { holder: details.holder, lockPath: details.lockPath, scopeRoot: details.scopeRoot, waitedMs: details.waitedMs });
100
+ }
101
+ }
102
+
103
+ class RunLockLostError extends Error {
104
+ constructor(details ) {
105
+ super(formatRunLockMessage('lost', details));
106
+ this.name = 'RunLockLostError';
107
+ Object.assign(this, { lockPath: details.lockPath, scopeRoot: details.scopeRoot });
108
+ }
109
+ }
110
+
111
+ function isIdentified(record ) {
112
+ return Boolean(record) && typeof record.token === 'string' && Number.isInteger(record.pid) && typeof record.hostname === 'string';
113
+ }
114
+
115
+ /**
116
+ * The lock file as one consistent read: content and stat come from the same open file, so a lock
117
+ * replaced between the two calls can never pair one instance's record with another's age.
118
+ * @returns {{record: Object|null, stat: fs.Stats, key: string}|null} null when there is no lock
119
+ */
120
+ function readLockFile(fsImpl , lockPath ) {
121
+ let fd ;
122
+ try {
123
+ fd = fsImpl.openSync(lockPath, 'r');
124
+ } catch (err ) {
125
+ if (err.code !== 'ENOENT') throw err;
126
+ // A dangling symlink opens as ENOENT yet blocks link(); judge it by its own lstat.
127
+ let stat;
128
+ try { stat = fsImpl.lstatSync(lockPath); } catch (lstatErr ) {
129
+ if (lstatErr.code === 'ENOENT') return null;
130
+ throw lstatErr;
131
+ }
132
+ return { record: null, stat, key: instanceKey(null, stat) };
133
+ }
134
+ try {
135
+ const stat = fsImpl.fstatSync(fd);
136
+ let record = null;
137
+ try { record = JSON.parse(fsImpl.readFileSync(fd, 'utf8')); } catch { /* unidentified */ }
138
+ if (!isIdentified(record)) record = null;
139
+ return { record, stat, key: instanceKey(record, stat) };
140
+ } finally {
141
+ fsImpl.closeSync(fd);
142
+ }
143
+ }
144
+
145
+ function instanceKey(record , stat ) {
146
+ return record ? record.token : `u-${stat.dev}-${stat.ino}-${Math.floor(stat.mtimeMs)}`;
147
+ }
148
+
149
+ /** @returns {null|'not-running'|'expired'} */
150
+ function staleReason(found , { token, hostname, isAlive, now, staleMs } ) {
151
+ const { record, stat } = found;
152
+ if (record && record.token === token) return null;
153
+ if (record && record.hostname === hostname && (record.pid === process.pid || !isAlive(record.pid))) return 'not-running';
154
+ if (now() - stat.mtimeMs > staleMs) return 'expired';
155
+ return null;
156
+ }
157
+
158
+ function unlinkQuietly(fsImpl , file ) {
159
+ try { fsImpl.unlinkSync(file); } catch { /* already gone, or the stale rule clears it later */ }
160
+ }
161
+
162
+ function readRaw(fsImpl , file ) {
163
+ try { return fsImpl.readFileSync(file, 'utf8'); } catch { return null; }
164
+ }
165
+
166
+ /** A claim left by a run that died while clearing: its process is gone, or it is older than claimStaleMs. */
167
+ function isOrphanClaim(fsImpl , claimPath , { hostname, isAlive, now, claimStaleMs } ) {
168
+ let stat;
169
+ try { stat = fsImpl.statSync(claimPath); } catch { return false; }
170
+ if (now() - stat.mtimeMs > claimStaleMs) return true;
171
+ let claim = null;
172
+ try { claim = JSON.parse(fsImpl.readFileSync(claimPath, 'utf8')); } catch { return false; }
173
+ return Boolean(claim) && claim.hostname === hostname && (claim.pid === process.pid || !isAlive(claim.pid));
174
+ }
175
+
176
+ /** Creates the claim for one lock instance. @returns {boolean} true when this run now holds it */
177
+ function createClaim(fsImpl , claimPath , { token, hostname, target } ) {
178
+ const body = `${JSON.stringify({ version: RECORD_VERSION, token, pid: process.pid, hostname, at: new Date().toISOString(), target })}\n`;
179
+ try {
180
+ fsImpl.writeFileSync(claimPath, body, { flag: 'wx' });
181
+ return true;
182
+ } catch (err ) {
183
+ if (err.code === 'EEXIST') return false;
184
+ throw err;
185
+ }
186
+ }
187
+
188
+ /**
189
+ * Takes a claim for instance `key`, removing an orphan claim first. A live claimant's claim means
190
+ * another run is clearing this instance. The orphan is moved aside before it is deleted, and put
191
+ * back when what was moved is not what was judged, so a fresh claim is never deleted by mistake.
192
+ * @returns {boolean}
193
+ */
194
+ function claimInstance(fsImpl , stateDir , key , options ) {
195
+ const claimPath = path.join(stateDir, `${CLAIM_PREFIX}${key}`);
196
+ for (let attempt = 0; attempt < 2; attempt += 1) {
197
+ if (createClaim(fsImpl, claimPath, { token: options.token, hostname: options.hostname, target: key })) return true;
198
+ const judged = readRaw(fsImpl, claimPath);
199
+ if (judged === null || !isOrphanClaim(fsImpl, claimPath, options)) return false;
200
+ const aside = `${claimPath}.${options.token}.gone`;
201
+ try { fsImpl.renameSync(claimPath, aside); } catch { return false; }
202
+ if (readRaw(fsImpl, aside) !== judged) {
203
+ try { fsImpl.linkSync(aside, claimPath); } catch { /* another claim took the path; leave it */ }
204
+ unlinkQuietly(fsImpl, aside);
205
+ return false;
206
+ }
207
+ unlinkQuietly(fsImpl, aside);
208
+ }
209
+ return false;
210
+ }
211
+
212
+ /**
213
+ * Removes the stale instance `found` under its claim.
214
+ * @returns {'cleared'|'aborted'}
215
+ */
216
+ function takeOver(fsImpl , stateDir , lockPath , found , options ) {
217
+ if (!claimInstance(fsImpl, stateDir, found.key, options)) return 'aborted';
218
+ const claimPath = path.join(stateDir, `${CLAIM_PREFIX}${found.key}`);
219
+ try {
220
+ const current = readLockFile(fsImpl, lockPath);
221
+ if (!current || current.key !== found.key) return 'aborted';
222
+ // Judged again under the claim: a holder whose checkpoint renewed the lock since the first
223
+ // judgment is no longer stale, and its lock stays.
224
+ if (!staleReason(current, options)) return 'aborted';
225
+ try { fsImpl.unlinkSync(lockPath); } catch (err ) {
226
+ if (err.code !== 'ENOENT') return 'aborted';
227
+ }
228
+ return 'cleared';
229
+ } catch {
230
+ return 'aborted';
231
+ } finally {
232
+ unlinkQuietly(fsImpl, claimPath);
233
+ }
234
+ }
235
+
236
+ /** Removes owner temp files left by runs that died while they waited, judged by the stale rule as
237
+ * a lock would be: interrupting a waiting run is the one exit that never reaches its own cleanup. */
238
+ function sweepOrphanTemps(fsImpl , stateDir , judge ) {
239
+ let names;
240
+ try { names = fsImpl.readdirSync(stateDir); } catch { return; }
241
+ for (const name of names) {
242
+ const match = TEMP_NAME.exec(name);
243
+ if (!match || match[1] === judge.token) continue;
244
+ const file = path.join(stateDir, name);
245
+ let found = null;
246
+ try { found = readLockFile(fsImpl, file); } catch { /* unreadable: left for a later sweep */ }
247
+ if (found && staleReason(found, judge)) unlinkQuietly(fsImpl, file);
248
+ }
249
+ }
250
+
251
+ /** Removes, innermost first, the directories an acquisition created, stopping at the first non-empty one. */
252
+ function removeCreatedDirs(fsImpl , stateDir , firstCreated ) {
253
+ if (!firstCreated) return;
254
+ const top = path.resolve(firstCreated);
255
+ for (let dir = stateDir; ; dir = path.dirname(dir)) {
256
+ try { fsImpl.rmdirSync(dir); } catch { return; }
257
+ if (dir === top || path.dirname(dir) === dir) return;
258
+ }
259
+ }
260
+
261
+ /**
262
+ * Takes the run lock for one scope, waiting for a live holder and clearing a stale one.
263
+ * @param {{scopeRoot: string, scope: 'global'|'project', command: string}} target
264
+ * @param {Object} [options]
265
+ * @returns {{lockPath: string, token: string, scopeRoot: string, waitedMs: number,
266
+ * cleared: Array<{pid: number|null, command: string|null, startedAt: string|null, reason: string}>,
267
+ * checkpoint: () => void, release: () => void}}
268
+ * @throws {RunLockTimeoutError|RunLockError}
269
+ */
270
+ function acquireRunLock({ scopeRoot, scope, command } , {
271
+ waitMs = 60_000, pollMs = 250, staleMs = 600_000, claimStaleMs = 30_000,
272
+ now = Date.now, isAlive = defaultIsAlive, hostname = os.hostname(),
273
+ log = (line ) => process.stderr.write(`${line}\n`), fsImpl = fs, sleep = atomicsSleep,
274
+ } = {}) {
275
+ const root = path.resolve(scopeRoot);
276
+ const existing = held.get(root);
277
+ if (existing) {
278
+ existing.count += 1;
279
+ return existing.handle;
280
+ }
281
+
282
+ const lockPath = runLockPath(root);
283
+ const stateDir = path.dirname(lockPath);
284
+ const token = crypto.randomBytes(16).toString('hex');
285
+ const where = { scope, scopeRoot: root, lockPath };
286
+ const fail = (code ) => new RunLockError({ ...where, code });
287
+
288
+ const tempPath = path.join(stateDir, `.${LOCK_FILE}.${token}.tmp`);
289
+ const record = {
290
+ version: RECORD_VERSION, token, pid: process.pid, hostname, command, scope, scopeRoot: root,
291
+ startedAt: new Date(now()).toISOString(), doflowVersion: DOFLOW_VERSION,
292
+ };
293
+ // A first-ever run that gives up removes the state directory it created. Doing so between this
294
+ // run's mkdir and its temp write surfaces here as ENOENT, so both steps are tried once more.
295
+ let firstCreated ;
296
+ for (let attempt = 0; ; attempt += 1) {
297
+ try { firstCreated = fsImpl.mkdirSync(stateDir, { recursive: true }); } catch (err ) { throw fail(err.code); }
298
+ try {
299
+ fsImpl.writeFileSync(tempPath, `${JSON.stringify(record)}\n`, { flag: 'wx' });
300
+ break;
301
+ } catch (err ) {
302
+ if (err.code === 'ENOENT' && attempt === 0) continue;
303
+ unlinkQuietly(fsImpl, tempPath);
304
+ removeCreatedDirs(fsImpl, stateDir, firstCreated);
305
+ throw fail(err.code);
306
+ }
307
+ }
308
+ const giveUp = (error ) => {
309
+ unlinkQuietly(fsImpl, tempPath);
310
+ removeCreatedDirs(fsImpl, stateDir, firstCreated);
311
+ return error;
312
+ };
313
+
314
+ const judge = { token, hostname, isAlive, now, staleMs, claimStaleMs };
315
+ sweepOrphanTemps(fsImpl, stateDir, judge);
316
+ const start = now();
317
+ const cleared = [];
318
+ let lastHolder = null;
319
+ let announced = false;
320
+ while (now() - start < waitMs) {
321
+ try {
322
+ fsImpl.linkSync(tempPath, lockPath);
323
+ } catch (err ) {
324
+ if (err.code !== 'EEXIST') throw giveUp(fail(err.code));
325
+ let found;
326
+ try { found = readLockFile(fsImpl, lockPath); } catch (readErr ) { throw giveUp(fail(readErr.code)); }
327
+ if (!found) continue;
328
+ lastHolder = found.record;
329
+ const reason = staleReason(found, judge);
330
+ if (reason && takeOver(fsImpl, stateDir, lockPath, found, judge) === 'cleared') {
331
+ const holder = found.record;
332
+ cleared.push({ pid: holder?.pid ?? null, command: holder?.command ?? null, startedAt: holder?.startedAt ?? null, reason });
333
+ log(formatRunLockMessage('cleared', { ...where, holder, reason }));
334
+ continue;
335
+ }
336
+ if (!announced) {
337
+ announced = true;
338
+ log(formatRunLockMessage('waiting', { ...where, holder: found.record, waitMs }));
339
+ }
340
+ sleep(pollMs);
341
+ continue;
342
+ }
343
+ unlinkQuietly(fsImpl, tempPath);
344
+ return holdHandle({ fsImpl, root, stateDir, lockPath, token, hostname, firstCreated, where, now, waitedMs: now() - start, cleared });
345
+ }
346
+ throw giveUp(new RunLockTimeoutError({ ...where, holder: lastHolder, waitedMs: now() - start }));
347
+ }
348
+
349
+ function holdHandle({ fsImpl, root, stateDir, lockPath, token, hostname, firstCreated, where, now, waitedMs, cleared } ) {
350
+ const entry = { count: 1, handle: null };
351
+ let released = false;
352
+
353
+ const releaseNow = () => {
354
+ if (released) return;
355
+ released = true;
356
+ held.delete(root);
357
+ process.removeListener('exit', releaseNow);
358
+ const claimPath = path.join(stateDir, `${CLAIM_PREFIX}${token}`);
359
+ let claimed = false;
360
+ try { claimed = createClaim(fsImpl, claimPath, { token, hostname, target: token }); } catch { /* swallowed: the stale rule clears it */ }
361
+ if (claimed) {
362
+ try {
363
+ const found = readLockFile(fsImpl, lockPath);
364
+ if (found && found.key === token) fsImpl.unlinkSync(lockPath);
365
+ } catch { /* swallowed */ }
366
+ unlinkQuietly(fsImpl, claimPath);
367
+ }
368
+ removeCreatedDirs(fsImpl, stateDir, firstCreated);
369
+ };
370
+
371
+ entry.handle = {
372
+ lockPath,
373
+ token,
374
+ scopeRoot: root,
375
+ waitedMs,
376
+ cleared,
377
+ // Under the same claim a takeover of this lock takes, so a renewal and a removal never
378
+ // interleave: a claim already there means another run is removing this lock.
379
+ checkpoint() {
380
+ const claimPath = path.join(stateDir, `${CLAIM_PREFIX}${token}`);
381
+ let claimed = false;
382
+ try { claimed = createClaim(fsImpl, claimPath, { token, hostname, target: token }); } catch { /* no state directory: the lock is gone */ }
383
+ if (!claimed) throw new RunLockLostError(where);
384
+ try {
385
+ let found = null;
386
+ try { found = readLockFile(fsImpl, lockPath); } catch { /* unreadable counts as lost */ }
387
+ if (!found || found.key !== token) throw new RunLockLostError(where);
388
+ const seconds = now() / 1000;
389
+ try { fsImpl.utimesSync(lockPath, seconds, seconds); } catch { /* renewal is best effort */ }
390
+ } finally {
391
+ unlinkQuietly(fsImpl, claimPath);
392
+ }
393
+ },
394
+ release() {
395
+ if (released) return;
396
+ entry.count -= 1;
397
+ if (entry.count > 0) return;
398
+ releaseNow();
399
+ },
400
+ };
401
+ held.set(root, entry);
402
+ process.on('exit', releaseNow);
403
+ return entry.handle;
404
+ }
405
+
406
+ module.exports = {
407
+ acquireRunLock, RunLockTimeoutError, RunLockError, RunLockLostError, runLockPath, formatRunLockMessage,
408
+ };
@@ -0,0 +1,68 @@
1
+ // Minimal ambient declarations for the CommonJS globals DoFlow's TypeScript runtime modules use.
2
+ // DoFlow runs .ts through Node native type-stripping with ZERO dependencies (no @types/node), so
3
+ // the handful of Node globals the `.ts` bodies reference are declared here rather than pulled from
4
+ // a devDependency. Kept intentionally narrow: this is not a re-implementation of @types/node, only
5
+ // the surface the migrated modules actually touch. Extend it as more modules migrate, not ahead of
6
+ // need. See agent-docs/BRIEF_GOAL_DOFLOW.md for the migration roadmap.
7
+
8
+ declare var require: { (id: string): any; main: any };
9
+
10
+ declare var module: { exports: any };
11
+
12
+ declare var process: {
13
+ features?: { typescript?: false | 'strip' | 'transform' };
14
+ env: Record<string, string | undefined>;
15
+ platform: string;
16
+ execPath: string;
17
+ version: string;
18
+ pid: number;
19
+ argv: string[];
20
+ cwd(): string;
21
+ exit(code?: number): never;
22
+ exitCode?: number;
23
+ kill(pid: number, signal?: string | number): void;
24
+ hrtime: { (time?: [number, number]): [number, number]; bigint(): bigint };
25
+ stdin: { isTTY?: boolean; isRaw?: boolean; setRawMode(mode: boolean): void };
26
+ stdout: { write(chunk: string): boolean; isTTY?: boolean };
27
+ stderr: { write(chunk: string): boolean };
28
+ on(event: string, listener: (...args: any[]) => void): any;
29
+ removeListener(event: string, listener: (...args: any[]) => void): any;
30
+ };
31
+
32
+ declare var __dirname: string;
33
+ declare var __filename: string;
34
+
35
+ // Narrow Buffer / console surface the migrated .ts modules touch. Not a re-implementation of
36
+ // @types/node — only what the converted modules reference. Extend as more modules migrate.
37
+ declare var console: {
38
+ log(...args: any[]): void;
39
+ error(...args: any[]): void;
40
+ warn(...args: any[]): void;
41
+ };
42
+
43
+ interface Buffer extends Uint8Array {
44
+ toString(encoding?: string, start?: number, end?: number): string;
45
+ equals(other: Uint8Array): boolean;
46
+ subarray(begin?: number, end?: number): Buffer;
47
+ }
48
+ declare var Buffer: {
49
+ alloc(size: number): Buffer;
50
+ from(data: any, encoding?: string): Buffer;
51
+ byteLength(string: string, encoding?: string): number;
52
+ isBuffer(value: any): boolean;
53
+ allocUnsafe(size: number): Buffer;
54
+ concat(list: Uint8Array[], totalLength?: number): Buffer;
55
+ };
56
+
57
+ // Timers and WHATWG URL, as the migrated .ts modules use them (opaque handle; parsed URL fields only).
58
+ declare function setTimeout(callback: (...args: any[]) => void, ms?: number, ...args: any[]): any;
59
+ declare function clearTimeout(handle: any): void;
60
+ declare var URL: {
61
+ new (input: string, base?: string): { protocol: string; username: string; password: string; hostname: string; [key: string]: any };
62
+ };
63
+
64
+ // High-resolution clock (storage engine pass budget).
65
+ declare var performance: { now(): number };
66
+
67
+ // structuredClone (workflow-orchestrator previewHandoff deep-copies a run program).
68
+ declare function structuredClone<T>(value: T): T;
@@ -0,0 +1,91 @@
1
+ /**
2
+ * DoFlow Runtime Type Declarations
3
+ *
4
+ * Provides ambient type definitions for core runtime contracts and schemas:
5
+ * ContextPack, VerificationContract, CapabilityRouter, DecisionRegister, and OutcomeRecord.
6
+ */
7
+
8
+ export interface ContextPackOptions {
9
+ taskId: string;
10
+ taskClass?: string;
11
+ maxBytes?: number;
12
+ objective?: string;
13
+ mandatory?: {
14
+ acceptanceCriteria?: string[];
15
+ constraints?: string[];
16
+ verificationPlan?: string;
17
+ };
18
+ optional?: {
19
+ hypotheses?: string[];
20
+ narrative?: string[];
21
+ unverifiedClaims?: string[];
22
+ };
23
+ evidenceLedger?: unknown;
24
+ claimsManager?: unknown;
25
+ researchRequests?: unknown[];
26
+ decisions?: {
27
+ available: boolean;
28
+ live: unknown[];
29
+ liveCount: number;
30
+ reason?: string;
31
+ };
32
+ }
33
+
34
+ export interface ContextPackResult {
35
+ taskId: string;
36
+ taskClass: string;
37
+ totalBytes: number;
38
+ budgetBytes: number;
39
+ overflow: boolean;
40
+ mandatoryBytes: number;
41
+ optionalBytes: number;
42
+ omissions: Array<{ id: string; reason: string }>;
43
+ payload: string;
44
+ error?: string;
45
+ }
46
+
47
+ export interface LatencyBudget {
48
+ surface: string;
49
+ command: string[];
50
+ ceilingMs: number;
51
+ }
52
+
53
+ export interface DecisionRecord {
54
+ id: string;
55
+ topic: string;
56
+ statement: string;
57
+ decidedBy: 'user' | 'agent';
58
+ channel: 'question' | 'gate' | 'prompt' | 'default' | 'resolution';
59
+ stage: 'discovery' | 'design' | 'planning' | 'implementation' | 'verification' | 'review';
60
+ rationale: string;
61
+ status: 'live' | 'superseded';
62
+ supersedes: string[];
63
+ refs: string[];
64
+ date: string;
65
+ at: string;
66
+ }
67
+
68
+ export interface VerificationContract {
69
+ taskId: string;
70
+ featureSlug: string;
71
+ allowedPaths: string[];
72
+ mandatoryTiers: string[];
73
+ requiredSuites: string[];
74
+ baselineRef?: string;
75
+ compiledAt: string;
76
+ }
77
+
78
+ export interface VerificationReport {
79
+ taskId: string;
80
+ passed: boolean;
81
+ tiers: Record<string, { passed: boolean; message?: string }>;
82
+ evidence: unknown[];
83
+ evaluatedAt: string;
84
+ }
85
+
86
+ export interface CapabilityCandidate {
87
+ provider: string;
88
+ intent: string;
89
+ priority: number;
90
+ healthy: boolean;
91
+ }