@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,342 @@
1
+ 'use strict';
2
+
3
+ // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
+
5
+ /**
6
+ * The tier, tools and report-format block of a generated brief (062 CH7, IC-016 to IC-018).
7
+ *
8
+ * `renderBriefTools` is pure: the registries, the provider probe results, the MCP reach and the run's
9
+ * current stage are all injected, so the same inputs give the same bytes (NFR-001). It names no
10
+ * capability, provider, route intent or MCP server: every name in the block comes from the
11
+ * registries it is handed (NFR-008). `handleBriefToolsCommand` is the `brief-tools` verb that gathers
12
+ * those inputs and prints the block; it writes nothing.
13
+ */
14
+
15
+ const { REPO_ROOT } = require('../helper/repo-root.js');
16
+ const { loadRegistry } = require('../registry/index.js');
17
+ const { CapabilityRouter } = require('./capability-router.js');
18
+ const { probeProviders, HEALTHY, UNVERIFIED } = require('./health.js');
19
+ const { mcpReach } = require('./mcp-reach.js');
20
+ const { WorkflowOrchestrator } = require('./workflow-orchestrator.js');
21
+ const { resolveActiveFeature } = require('./feature-resolve.js');
22
+ const { finishRuntime, usageError, captureCaught } = require('./cli-result.js');
23
+ const fs = require('node:fs');
24
+ const path = require('node:path');
25
+ const { loadAdviceRegistry } = require('./advice/registry.js');
26
+ const { loadStorageRegistry } = require('./storage/registry.js');
27
+ const { resolveRoots } = require('./storage/roots.js');
28
+ const { resolveSetting } = require('./advice/config.js');
29
+ const { materializeKind } = require('./advice/kinds.js');
30
+ const { createAdviceClient } = require('./advice/client.js');
31
+ const { strengthWords } = require('./advice/strength.js');
32
+
33
+ const SCHEMA = 1;
34
+ const REACHABLE = new Set(['selected', 'configured']);
35
+
36
+ /** The state of `server` on a harness: selected or configured on any of its scopes wins; absent
37
+ * only when every scope says so from a complete view (IC-013); else unknown. */
38
+ function stateOn(reach , harnessId , server ) {
39
+ const rows = (reach?.harnesses || []).filter((row ) => row.id === harnessId);
40
+ if (rows.some((row ) => row.servers[server] === 'selected')) return 'selected';
41
+ if (rows.some((row ) => row.servers[server] === 'configured')) return 'configured';
42
+ const states = rows.map((row ) => row.servers[server] ?? 'unknown');
43
+ return states.length && !states.includes('unknown') ? states[0] : 'unknown';
44
+ }
45
+
46
+ /** Whether `server` is selected or configured on the target harness, or on any harness without one. */
47
+ function hasServer(reach , harnessId , server ) {
48
+ if (!reach) return false;
49
+ return harnessId ? REACHABLE.has(stateOn(reach, harnessId, server)) : reach.harnesses.some((row ) => REACHABLE.has(row.servers[server]));
50
+ }
51
+
52
+ /** The target harness: a registry id named by the caller, else the one harness installed at the
53
+ * project scope (the global scope when the project has none), else none. */
54
+ function chooseTarget({ registry, reach, harness, missing } ) {
55
+ if (harness) {
56
+ if (registry.harnesses.some((item ) => item.id === harness)) return harness;
57
+ missing.push(`harness '${harness}' is not a registry harness; ignored`);
58
+ }
59
+ const rows = reach?.harnesses || [];
60
+ for (const scope of ['project', 'global']) {
61
+ const ids = [...new Set(rows.filter((row ) => row.scope === scope).map((row ) => row.id))];
62
+ if (ids.length) return ids.length === 1 ? ids[0] : null;
63
+ }
64
+ return null;
65
+ }
66
+
67
+ /** Tier for a dispatch: the task line's tier when valid, else the owner's, else the default (IC-004).
68
+ * A registry without `dispatchTiers` (the key is optional) gives `standard` with a note. */
69
+ function resolveTier({ dispatchTiers, owner, tier, missing } ) {
70
+ if (!dispatchTiers) {
71
+ missing.push('models.json has no dispatchTiers; tier standard assumed');
72
+ return { tier: 'standard', source: 'default', note: 'models.json has no dispatchTiers' };
73
+ }
74
+ if (tier !== undefined && tier !== null && tier !== '') {
75
+ if (dispatchTiers.tiers.includes(tier)) return { tier, source: 'task' };
76
+ missing.push(`tier '${tier}' is not in dispatchTiers.tiers; ignored`);
77
+ }
78
+ if (Object.hasOwn(dispatchTiers.byOwner, owner)) return { tier: dispatchTiers.byOwner[owner], source: 'owner' };
79
+ missing.push(`owner '${owner}' has no tier in models.json dispatchTiers`);
80
+ return { tier: dispatchTiers.default, source: 'default' };
81
+ }
82
+
83
+ /** The first provider of a capability whose probe status is `status`, in registry order, or null. */
84
+ function firstWith(router , capabilityId , probes , status ) {
85
+ return (router.capabilities[capabilityId]?.providers || []).find((provider ) => probes[provider.id]?.status === status) || null;
86
+ }
87
+
88
+ /** What answers one route intent on this machine: a healthy provider of the primary capability,
89
+ * else of the route's fallback capabilities in order; failing those, a provider that has no probe
90
+ * (UNVERIFIED) in the same order; else nothing. An unhealthy provider is never chosen. */
91
+ function resolveRoute(router , route , probes ) {
92
+ const chain = [route.capability, ...(route.fallback || [])];
93
+ for (const status of [HEALTHY, UNVERIFIED]) {
94
+ for (const capability of chain) {
95
+ const provider = firstWith(router, capability, probes, status);
96
+ if (!provider) continue;
97
+ const via = capability === route.capability ? null : 'fallback';
98
+ return { capability, provider, status: status === UNVERIFIED ? 'UNVERIFIED' : via ? 'FALLBACK' : 'HEALTHY', via };
99
+ }
100
+ }
101
+ return { capability: route.capability, provider: null, status: 'NONE', via: null };
102
+ }
103
+
104
+ const cell = (text ) => String(text).replace(/\|/g, '\\|').replace(/\s+/g, ' ');
105
+ const trigger = (server ) => server.trigger.replace(/\.$/, '');
106
+
107
+ /**
108
+ * @param {Object} input
109
+ * @param {Object} input.registry loaded registry (mcp, harnesses, dispatchTiers)
110
+ * @param {CapabilityRouter} input.router carries the capabilities and routes
111
+ * @param {Object} input.probes provider id -> probe result (`status`)
112
+ * @param {Object|null} input.reach `mcpReach()` result, or null when install facts are unavailable
113
+ * @param {string} input.owner
114
+ * @param {string} [input.tier] the task line's tier
115
+ * @param {string} [input.harness] target harness id
116
+ * @param {2|3} [input.headingLevel]
117
+ * @param {{feature:?string, runTaskId:?string, stageId:?string, skill:?string}|null} [input.stage]
118
+ * @returns {{markdown: string, record: Object}} the record is IC-018 without `tasks`
119
+ */
120
+ function renderBriefTools({ registry, router, probes, reach, owner, tier, harness, headingLevel = 2, stage = null } ) {
121
+ const missing = [];
122
+ const hashes = '#'.repeat(Number(headingLevel) === 3 ? 3 : 2);
123
+ const target = chooseTarget({ registry, reach, harness, missing });
124
+ const targetHarness = target ? registry.harnesses.find((item ) => item.id === target) : null;
125
+ const resolved = resolveTier({ dispatchTiers: registry.dispatchTiers, owner, tier, missing });
126
+ const sourceText = resolved.source === 'owner' ? `owner ${owner}`
127
+ : resolved.source === 'task' ? 'task line' : `default; ${resolved.note || `owner ${owner} has no tier`}`;
128
+
129
+ const tools = [];
130
+ const rows = [];
131
+ for (const [intent, route] of Object.entries (router.routes)) {
132
+ const found = resolveRoute(router, route, probes);
133
+ if (!found.provider) {
134
+ rows.push(`| ${cell(intent)} | no healthy provider and no fallback | - |`);
135
+ tools.push({ intent, capability: found.capability, provider: null, status: 'NONE', form: 'none' });
136
+ continue;
137
+ }
138
+ const { provider } = found;
139
+ const execution = router.formatExecution(intent, provider, { query: '<query>', path: '.', command: '<command>' });
140
+ const cli = execution?.cliCommand || null;
141
+ const mcp = provider.mcp || null;
142
+ const template = targetHarness?.capabilities?.mcp?.toolName;
143
+ let form;
144
+ let how;
145
+ if (mcp && template && hasServer(reach, target, mcp.server)) {
146
+ form = 'mcp';
147
+ how = template.replace('{server}', () => mcp.server).replace('{tool}', () => mcp.tool);
148
+ } else if (!cli) {
149
+ form = 'none';
150
+ how = execution?.reason || 'no command form is available';
151
+ } else if (mcp && !target) {
152
+ form = 'neutral';
153
+ how = `${cli}; MCP server ${mcp.server}, tool ${mcp.tool}, where your harness registers it`;
154
+ } else {
155
+ form = 'cli';
156
+ how = cli;
157
+ }
158
+ const named = found.status === 'UNVERIFIED' ? `${provider.id} (unverified: no probe)` : provider.id;
159
+ const use = found.via === 'fallback' ? `no healthy ${route.capability} provider; fallback ${named}` : named;
160
+ rows.push(`| ${cell(intent)} | ${cell(use)} | ${cell(how)} |`);
161
+ tools.push({ intent, capability: found.capability, provider: provider.id, status: found.status, form });
162
+ }
163
+
164
+ const skill = stage?.skill || null;
165
+ const expectedServers = skill
166
+ ? registry.mcp.filter((server ) => (server.steps || []).some((step ) => step.skill === skill && !step.expectedWhen)) : [];
167
+ const expectedIds = new Set(expectedServers.map((server ) => server.id));
168
+ const expected = expectedServers.map((server ) => {
169
+ let state;
170
+ if (target) state = stateOn(reach, target, server.id);
171
+ else state = reach ? reach.anyHarnessHas(server.id) ?? 'unknown' : 'unknown';
172
+ const reachState = target ? (REACHABLE.has(state) ? 'reachable' : state === 'unknown' ? 'unknown' : 'unreachable')
173
+ : (state === true ? 'reachable' : state === false ? 'unreachable' : 'unknown');
174
+ return { server: server.id, reach: reachState, detail: target ? state : `any-harness:${state}` };
175
+ });
176
+ const also = registry.mcp.filter((server ) => !expectedIds.has(server.id) && hasServer(reach, target, server.id));
177
+ const list = (servers ) => (servers.length ? servers.map((server ) => `\`${server.id}\` (${trigger(server)})`).join('; ') : 'none');
178
+ const targetName = targetHarness ? targetHarness.displayName || targetHarness.id : 'any installed harness';
179
+
180
+ const lines = [
181
+ `${hashes} Tier and tools`,
182
+ '',
183
+ `Tier: \`${resolved.tier}\` (${sourceText}), per`,
184
+ '`references/MODEL_SELECTION.md`.',
185
+ '',
186
+ 'Tools this machine answers with, per information need. Searching with them before reading whole',
187
+ 'files is recommended where it saves reading; it is not required.',
188
+ '',
189
+ '| Need | Use | How |',
190
+ '|---|---|---|',
191
+ ...rows,
192
+ '',
193
+ `MCP servers. Expected for ${skill || 'the running stage (none found)'}: ${list(expectedServers)}. Also selected here:`,
194
+ `${list(also)}.`,
195
+ ];
196
+ // `unreachable` is written only where every config the harness merges was read (IC-013), so it is
197
+ // stated; a server DoFlow cannot confirm either way is hedged.
198
+ for (const item of expected) {
199
+ if (item.reach === 'unreachable') lines.push(`\`${item.server}\` is not reachable on ${targetName}; report it as \`${item.server}=unavailable\`.`);
200
+ else if (item.reach === 'unknown') lines.push(`\`${item.server}\` may not be reachable on ${targetName}; if no tool answers, report \`${item.server}=unavailable\`.`);
201
+ }
202
+ lines.push(
203
+ '',
204
+ `${hashes} Report format`,
205
+ '',
206
+ `End ${Number(headingLevel) === 3 ? "each task's report" : 'your report'} with one line naming every tool and MCP server you used:`,
207
+ '`Tools used: <name>[=used|nothing-usable|unavailable|skipped:<reason>], ...`',
208
+ );
209
+
210
+ const record = {
211
+ schema: SCHEMA,
212
+ feature: stage?.feature ?? null,
213
+ runTaskId: stage?.runTaskId ?? null,
214
+ stage: stage?.stageId ?? null,
215
+ stageSkill: skill,
216
+ owner,
217
+ tier: resolved.tier,
218
+ tierSource: resolved.source,
219
+ harness: target,
220
+ expected,
221
+ optional: also.map((server ) => server.id),
222
+ tools,
223
+ missing,
224
+ };
225
+ return { markdown: `${lines.join('\n')}\n`, record };
226
+ }
227
+
228
+ /** The stage a feature's run is at, or null when there is no readable run or it is not at a stage. */
229
+ function currentStageOf({ repoRoot = REPO_ROOT, projectRoot, taskId } ) {
230
+ try {
231
+ const run = new WorkflowOrchestrator({ repoRoot, projectRoot }).readRun(taskId);
232
+ const node = run && run.cursor < run.program.length ? run.program[run.cursor] : null;
233
+ return node && node.type === 'stage' ? { stageId: node.id, skill: node.skill } : null;
234
+ } catch { return null; }
235
+ }
236
+
237
+ /** The feature (`--slug`, else the resolved one) and its current stage, with a note for what is missing. */
238
+ function stageFor({ repoRoot, projectRoot, slug, missing } ) {
239
+ let feature = slug || null;
240
+ if (!feature) {
241
+ const resolved = resolveActiveFeature({ projectRoot });
242
+ if (resolved.error) { missing.push(`feature: ${resolved.error}`); return null; }
243
+ feature = resolved.paths.feature_slug || null;
244
+ if (!feature) { missing.push('feature: no feature slug resolved'); return null; }
245
+ }
246
+ const current = currentStageOf({ repoRoot, projectRoot, taskId: feature });
247
+ if (!current) {
248
+ missing.push(`run: no run at a stage for feature '${feature}'`);
249
+ return { feature, runTaskId: null, stageId: null, skill: null };
250
+ }
251
+ return { feature, runTaskId: feature, ...current };
252
+ }
253
+
254
+ /**
255
+ * The `brief-tools` verb (IC-016). Exit 0 on every outcome except a usage error (2); an unexpected
256
+ * failure exits 1, and the brief generator fails open on any non-zero status.
257
+ * @param {Object} options
258
+ * @param {Function} [options.buildAdapters] builds the adapter registry `mcpReach` reads installs through
259
+ * @param {Function} [options.probe] injection seam for `probeProviders`
260
+ */
261
+ function taskLinesForAdvice({ projectRoot, feature, tasks } ) {
262
+ if (!feature || !Array.isArray(tasks) || tasks.length === 0) throw new Error('feature or task ids are unavailable');
263
+ const planPath = path.join(projectRoot, 'agent-docs', 'doflow', feature, 'plan.md');
264
+ const plan = fs.readFileSync(planPath, 'utf8');
265
+ return tasks.map((id) => {
266
+ const line = plan.split(/\r?\n/).find((candidate ) => candidate.match(/^- \[[ x]\] (\S+)/)?.[1] === id);
267
+ if (!line) throw new Error(`task '${id}' was not found in ${planPath}`);
268
+ return line;
269
+ });
270
+ }
271
+
272
+ function adviceRecord(result ) {
273
+ if (result?.status === 'answered' && result.answers?.[0]) {
274
+ const answer = result.answers[0];
275
+ return {
276
+ kind: 'tier', status: 'answered', pickId: answer.pickId, pick: answer.pick,
277
+ strength: answer.strength?.word || 'leaning', between: answer.strength?.between ?? null,
278
+ agrees: answer.agrees,
279
+ };
280
+ }
281
+ if (result?.status === 'unavailable') return { kind: 'tier', status: 'unavailable', reason: result.reason || 'config-invalid' };
282
+ return null;
283
+ }
284
+
285
+ /**
286
+ * The tier renderer remains synchronous/pure; optional local advice is requested afterward.
287
+ */
288
+ async function handleBriefToolsCommand({ owner, tier, harness, slug, headingLevel, tasks, json = false, repoRoot = REPO_ROOT, projectRoot = process.cwd(), buildAdapters = null, probe = probeProviders, adviceClient = null } = {}) {
289
+ if (!owner) return usageError('brief-tools', '--owner is required (the agent type the brief is for)', json);
290
+ const level = headingLevel === undefined ? 2 : Number(headingLevel);
291
+ if (level !== 2 && level !== 3) return usageError('brief-tools', `--heading-level must be 2 or 3, got '${headingLevel}'`, json);
292
+ try {
293
+ const registry = loadRegistry({ repoRoot });
294
+ const router = new CapabilityRouter({ repoRoot, projectRoot });
295
+ const probes = probe({ repoRoot, projectRoot, router });
296
+ const notes = [];
297
+ let reach = null;
298
+ try { reach = mcpReach({ registry, projectRoot, adapters: buildAdapters ? buildAdapters() : undefined }); } catch { notes.push('install facts unavailable; MCP reach unknown'); }
299
+ const stage = stageFor({ repoRoot, projectRoot, slug, missing: notes });
300
+ const rendered = renderBriefTools({ registry, router, probes, reach, owner, tier, harness, headingLevel: level, stage });
301
+ let markdown = rendered.markdown;
302
+ const record = rendered.record;
303
+ record.missing.push(...notes);
304
+
305
+ const taskIds = Array.isArray(tasks) ? tasks : typeof tasks === 'string' ? tasks.split(',').filter(Boolean) : [];
306
+ if (taskIds.length) {
307
+ try {
308
+ const adviceRegistry = loadAdviceRegistry({ repoRoot });
309
+ const storageRegistry = loadStorageRegistry({ repoRoot });
310
+ const roots = resolveRoots({ registry: storageRegistry, projectRoot: path.resolve(projectRoot) });
311
+ if (adviceRegistry.ok && (adviceClient || resolveSetting({ adviceRegistry: adviceRegistry.registry, roots }).state === 'on')) {
312
+ const lines = taskLinesForAdvice({ projectRoot, feature: stage?.feature || slug, tasks: taskIds });
313
+ const built = materializeKind('tier', { adviceRegistry: adviceRegistry.registry });
314
+ const client = adviceClient || createAdviceClient({ adviceRegistry: adviceRegistry.registry, roots });
315
+ const result = built.ok ? await client.ask({
316
+ questionSet: { state: `${owner}\n${lines.join('\n')}`, questions: [built.question] },
317
+ kind: 'tier', staticAnswer: record.tier, caller: 'brief-tools', taskId: stage?.feature || slug,
318
+ }) : { status: 'unavailable', reason: built.reason || 'config-invalid' };
319
+ const added = adviceRecord(result);
320
+ if (added) {
321
+ record.advice = added;
322
+ if (added.status === 'answered') {
323
+ const line = `Decision model: \`${added.pick}\` (${strengthWords({ word: added.strength, between: added.between })}), advisory. The tier above stands unless you change it.`;
324
+ markdown = markdown.replace(/(Tier: `[^`]+`[^\n]*\n`references\/MODEL_SELECTION\.md`\.)\n\n/, `$1\n${line}\n\n`);
325
+ }
326
+ }
327
+ }
328
+ } catch (error ) {
329
+ record.advice = { kind: 'tier', status: 'unavailable', reason: error?.reason || 'config-invalid' };
330
+ }
331
+ }
332
+ if (json) console.log(JSON.stringify({ markdown, record }, null, 2));
333
+ else process.stdout.write(markdown);
334
+ return finishRuntime(0);
335
+ } catch (error ) {
336
+ captureCaught(error, 'brief-tools', 1);
337
+ console.error(`[ERROR] brief-tools: ${error.message}`);
338
+ return finishRuntime(1);
339
+ }
340
+ }
341
+
342
+ module.exports = { renderBriefTools, currentStageOf, handleBriefToolsCommand };