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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (407) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +132 -2
  3. package/bin/doflow.js +44 -0
  4. package/core/.antigravity-plugin/hooks.json +39 -0
  5. package/core/.antigravity-plugin/mcp_config.json +18 -0
  6. package/core/.antigravity-plugin/plugin.json +31 -0
  7. package/core/.claude-plugin/marketplace.json +20 -0
  8. package/core/.claude-plugin/plugin.json +21 -0
  9. package/core/.codex-plugin/marketplace.json +20 -0
  10. package/core/.codex-plugin/plugin.json +35 -0
  11. package/core/.plugin/plugin.json +19 -0
  12. package/core/harnesses/antigravity/hooks/pre-implementation-gate.sh +9 -0
  13. package/core/harnesses/antigravity/hooks/stop-check.sh +10 -0
  14. package/core/harnesses/claude/hooks/lib.sh +304 -0
  15. package/core/harnesses/claude/hooks/mcp-tool-guard.sh +20 -0
  16. package/core/harnesses/claude/hooks/permission-audit.sh +47 -0
  17. package/core/harnesses/claude/hooks/post-compact.sh +74 -0
  18. package/core/harnesses/claude/hooks/post-edit-lint.sh +36 -0
  19. package/core/harnesses/claude/hooks/post-tool-failure.sh +47 -0
  20. package/core/harnesses/claude/hooks/pre-bash-guard.sh +20 -0
  21. package/core/harnesses/claude/hooks/pre-compact.sh +43 -0
  22. package/core/harnesses/claude/hooks/pre-implement-gate.sh +21 -0
  23. package/core/harnesses/claude/hooks/session-end.sh +89 -0
  24. package/core/harnesses/claude/hooks/session-start.sh +5 -0
  25. package/core/harnesses/claude/hooks/skill-config-audit.sh +39 -0
  26. package/core/harnesses/claude/hooks/stop-check.sh +5 -0
  27. package/core/harnesses/claude/hooks/subagent-audit.sh +7 -0
  28. package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -0
  29. package/core/harnesses/claude/settings/keybindings.json +20 -0
  30. package/core/harnesses/claude/settings/settings.json +201 -0
  31. package/core/harnesses/claude/statusline/doflow-statusline.sh +49 -0
  32. package/core/harnesses/codex/agents/core-implementer.toml +7 -0
  33. package/core/harnesses/codex/agents/quality-guardian.toml +8 -0
  34. package/core/harnesses/codex/agents/research-writer.toml +8 -0
  35. package/core/harnesses/codex/agents/spec-analyst.toml +8 -0
  36. package/core/harnesses/codex/agents/system-architect.toml +9 -0
  37. package/core/harnesses/codex/config/config.toml +10 -0
  38. package/core/harnesses/codex/hooks/hooks.json +122 -0
  39. package/core/harnesses/codex/hooks/lib.sh +335 -0
  40. package/core/harnesses/codex/hooks/mcp-tool-guard.sh +18 -0
  41. package/core/harnesses/codex/hooks/post-edit-lint.impl.sh +52 -0
  42. package/core/harnesses/codex/hooks/post-edit-lint.sh +6 -0
  43. package/core/harnesses/codex/hooks/pre-bash-guard.sh +18 -0
  44. package/core/harnesses/codex/hooks/pre-compact.impl.sh +46 -0
  45. package/core/harnesses/codex/hooks/pre-compact.sh +9 -0
  46. package/core/harnesses/codex/hooks/pre-implement-gate.sh +19 -0
  47. package/core/harnesses/codex/hooks/session-end.impl.sh +92 -0
  48. package/core/harnesses/codex/hooks/session-end.sh +5 -0
  49. package/core/harnesses/codex/hooks/session-start.sh +5 -0
  50. package/core/harnesses/codex/hooks/stop-check.sh +8 -0
  51. package/core/harnesses/codex/hooks/subagent-audit.sh +8 -0
  52. package/core/harnesses/codex/hooks/user-prompt-submit.sh +6 -0
  53. package/core/harnesses/gemini/hooks/hooks.json +77 -0
  54. package/core/harnesses/gemini/hooks/lib.sh +302 -0
  55. package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +21 -0
  56. package/core/harnesses/gemini/hooks/post-edit-lint.sh +39 -0
  57. package/core/harnesses/gemini/hooks/pre-bash-guard.sh +21 -0
  58. package/core/harnesses/gemini/hooks/pre-compact.sh +38 -0
  59. package/core/harnesses/gemini/hooks/pre-implement-gate.sh +22 -0
  60. package/core/harnesses/gemini/hooks/session-end.impl.sh +89 -0
  61. package/core/harnesses/gemini/hooks/session-end.sh +5 -0
  62. package/core/harnesses/gemini/hooks/session-start.sh +5 -0
  63. package/core/harnesses/gemini/settings/adapter-defaults.json +4 -0
  64. package/core/harnesses/kiro/agents/doflow.json +58 -0
  65. package/core/harnesses/kiro/hooks/doflow.json +53 -0
  66. package/core/harnesses/kiro/hooks/lib.sh +324 -0
  67. package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +9 -0
  68. package/core/harnesses/kiro/hooks/pre-bash-guard.sh +9 -0
  69. package/core/harnesses/kiro/hooks/pre-implement-gate.sh +9 -0
  70. package/core/harnesses/kiro/hooks/session-start.sh +9 -0
  71. package/core/harnesses/kiro/hooks/stop-check.sh +43 -0
  72. package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +39 -0
  73. package/core/harnesses/shared/hooks/adapters/antigravity.js +111 -0
  74. package/core/harnesses/shared/hooks/adapters/arg-fields.js +19 -0
  75. package/core/harnesses/shared/hooks/adapters/gemini.js +114 -0
  76. package/core/harnesses/shared/hooks/hooks.json +47 -0
  77. package/core/harnesses/shared/hooks/policies/blocked-patterns.conf +91 -0
  78. package/core/harnesses/shared/hooks/policies/capture-failure.sh +97 -0
  79. package/core/harnesses/shared/hooks/policies/deny-json.sh +29 -0
  80. package/core/harnesses/shared/hooks/policies/lib.sh +501 -0
  81. package/core/harnesses/shared/hooks/policies/mcp-policy.conf +21 -0
  82. package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +91 -0
  83. package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +328 -0
  84. package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +496 -0
  85. package/core/harnesses/shared/hooks/policies/prompt-nudge.jq +131 -0
  86. package/core/harnesses/shared/hooks/policies/session-context.sh +141 -0
  87. package/core/harnesses/shared/hooks/policies/stop-check.sh +264 -0
  88. package/core/harnesses/shared/hooks/policies/subagent-audit.sh +46 -0
  89. package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +235 -0
  90. package/core/harnesses/shared/hooks/stream-hook-runner.js +590 -0
  91. package/core/harnesses/shared/locator/doflow-run +87 -0
  92. package/core/registry/advice.json +101 -0
  93. package/core/registry/assets.json +792 -0
  94. package/core/registry/capabilities.json +120 -0
  95. package/core/registry/contracts.json +189 -0
  96. package/core/registry/external-tools.json +191 -0
  97. package/core/registry/harnesses.json +2062 -0
  98. package/core/registry/lifecycle.json +231 -0
  99. package/core/registry/mcp.json +18 -0
  100. package/core/registry/models.json +79 -0
  101. package/core/registry/readiness-templates.json +118 -0
  102. package/core/registry/routes.json +47 -0
  103. package/core/registry/storage.json +1057 -0
  104. package/core/registry/verification.json +258 -0
  105. package/core/registry/workflows.json +790 -0
  106. package/core/shared/agent-specs/core-implementer.md +73 -0
  107. package/core/shared/agent-specs/quality-guardian.md +28 -0
  108. package/core/shared/agent-specs/research-writer.md +31 -0
  109. package/core/shared/agent-specs/spec-analyst.md +33 -0
  110. package/core/shared/agent-specs/system-architect.md +29 -0
  111. package/core/shared/guidance/DOFLOW_CORE.md +8 -0
  112. package/core/shared/guidance/FLAGS.md +25 -0
  113. package/core/shared/guidance/PRINCIPLES.md +61 -0
  114. package/core/shared/guidance/VERSION +1 -0
  115. package/core/shared/guidance/mcp/MCP_Context7.md +18 -0
  116. package/core/shared/guidance/mcp/MCP_Sequential.md +17 -0
  117. package/core/shared/guidance/modes/MODE_Brainstorming.md +46 -0
  118. package/core/shared/guidance/modes/MODE_DeepResearch.md +69 -0
  119. package/core/shared/guidance/modes/MODE_Introspection.md +33 -0
  120. package/core/shared/guidance/modes/MODE_Orchestration.md +57 -0
  121. package/core/shared/guidance/modes/MODE_Task_Management.md +74 -0
  122. package/core/shared/guidance/pointers/claude-gemini.md +2 -0
  123. package/core/shared/guidance/pointers/codex.md +6 -0
  124. package/core/shared/guidance/references/ARTIFACT_FORMAT.md +373 -0
  125. package/core/shared/guidance/references/ARTIFACT_VOICE.md +104 -0
  126. package/core/shared/guidance/references/CONSTITUTION_BASE.md +47 -0
  127. package/core/shared/guidance/references/DIAGRAM_GUIDE.md +161 -0
  128. package/core/shared/guidance/references/DOFLOW_CHAIN.md +87 -0
  129. package/core/shared/guidance/references/EVIDENCE_LEDGER.md +93 -0
  130. package/core/shared/guidance/references/MODEL_SELECTION.md +74 -0
  131. package/core/shared/guidance/references/ORCHESTRATION.md +36 -0
  132. package/core/shared/guidance/references/RESEARCH_CONFIG.md +21 -0
  133. package/core/shared/guidance/references/WORKFLOW_HANDOFF.md +81 -0
  134. package/core/shared/guidance/rules/RULE_01_SAFETY.md +25 -0
  135. package/core/shared/guidance/rules/RULE_02_WORKFLOW.md +23 -0
  136. package/core/shared/guidance/rules/RULE_03_QUALITY.md +14 -0
  137. package/core/shared/guidance/rules/RULE_04_QUESTIONS.md +46 -0
  138. package/core/shared/scripts/doflow/assets/mermaid-theme.json +46 -0
  139. package/core/shared/scripts/doflow/bash/do-exec-paths.sh +167 -0
  140. package/core/shared/scripts/doflow/bash/do-git-state.sh +546 -0
  141. package/core/shared/scripts/doflow/bash/do-parallel-check.sh +208 -0
  142. package/core/shared/scripts/doflow/bash/do-paths.sh +347 -0
  143. package/core/shared/scripts/doflow/bash/do-prereqs.sh +66 -0
  144. package/core/shared/scripts/doflow/bash/do-review-package.sh +127 -0
  145. package/core/shared/scripts/doflow/bash/do-task-brief.sh +698 -0
  146. package/core/shared/scripts/doflow/bash/render-audit.sh +224 -0
  147. package/core/shared/scripts/doflow/bash/render-diagrams.sh +177 -0
  148. package/core/shared/scripts/doflow/bash/render-puml.sh +223 -0
  149. package/core/shared/scripts/doflow/bash/sync-context.sh +66 -0
  150. package/core/shared/scripts/doflow/bash/validate-artifacts.sh +526 -0
  151. package/core/shared/scripts/doflow/bin/doflow-run +592 -0
  152. package/core/shared/skills/do/SKILL.md +128 -0
  153. package/core/shared/skills/do/references/estimation.md +13 -0
  154. package/core/shared/skills/do/references/pm_routing.md +25 -0
  155. package/core/shared/skills/do/references/tool_matrix.md +52 -0
  156. package/core/shared/skills/do-brainstorm/SKILL.md +252 -0
  157. package/core/shared/skills/do-code-review/README.md +49 -0
  158. package/core/shared/skills/do-code-review/SKILL.md +333 -0
  159. package/core/shared/skills/do-code-review/assets/sample_c_clean.c +71 -0
  160. package/core/shared/skills/do-code-review/assets/sample_c_smells.c +66 -0
  161. package/core/shared/skills/do-code-review/assets/sample_cpp_shift.cpp +19 -0
  162. package/core/shared/skills/do-code-review/assets/sample_csharp_clean.cs +100 -0
  163. package/core/shared/skills/do-code-review/assets/sample_csharp_smells.cs +78 -0
  164. package/core/shared/skills/do-code-review/assets/sample_java_clean.java +55 -0
  165. package/core/shared/skills/do-code-review/assets/sample_java_smells.java +56 -0
  166. package/core/shared/skills/do-code-review/assets/sample_json_clean.json +7 -0
  167. package/core/shared/skills/do-code-review/assets/sample_markdown_clean.md +30 -0
  168. package/core/shared/skills/do-code-review/assets/sample_markdown_smells.md +29 -0
  169. package/core/shared/skills/do-code-review/assets/sample_shell_heredoc.sh +38 -0
  170. package/core/shared/skills/do-code-review/assets/sample_shell_smells.sh +15 -0
  171. package/core/shared/skills/do-code-review/assets/sample_typescript_strings.ts +36 -0
  172. package/core/shared/skills/do-code-review/assets/sample_yaml_smells.yaml +6 -0
  173. package/core/shared/skills/do-code-review/content-types/config.md +83 -0
  174. package/core/shared/skills/do-code-review/content-types/markdown.md +132 -0
  175. package/core/shared/skills/do-code-review/expected_outputs/sample_c_clean_quality.json +79 -0
  176. package/core/shared/skills/do-code-review/expected_outputs/sample_c_smells_quality.json +169 -0
  177. package/core/shared/skills/do-code-review/expected_outputs/sample_cpp_shift_quality.json +49 -0
  178. package/core/shared/skills/do-code-review/expected_outputs/sample_csharp_clean_quality.json +149 -0
  179. package/core/shared/skills/do-code-review/expected_outputs/sample_csharp_smells_quality.json +157 -0
  180. package/core/shared/skills/do-code-review/expected_outputs/sample_java_clean_quality.json +67 -0
  181. package/core/shared/skills/do-code-review/expected_outputs/sample_java_smells_quality.json +97 -0
  182. package/core/shared/skills/do-code-review/expected_outputs/sample_json_clean_quality.json +33 -0
  183. package/core/shared/skills/do-code-review/expected_outputs/sample_markdown_clean_quality.json +1 -0
  184. package/core/shared/skills/do-code-review/expected_outputs/sample_markdown_smells_quality.json +16 -0
  185. package/core/shared/skills/do-code-review/expected_outputs/sample_shell_heredoc_quality.json +54 -0
  186. package/core/shared/skills/do-code-review/expected_outputs/sample_shell_smells_quality.json +91 -0
  187. package/core/shared/skills/do-code-review/expected_outputs/sample_typescript_strings_quality.json +60 -0
  188. package/core/shared/skills/do-code-review/expected_outputs/sample_yaml_smells_quality.json +46 -0
  189. package/core/shared/skills/do-code-review/languages/c.md +103 -0
  190. package/core/shared/skills/do-code-review/languages/cpp.md +103 -0
  191. package/core/shared/skills/do-code-review/languages/csharp.md +97 -0
  192. package/core/shared/skills/do-code-review/languages/dart.md +108 -0
  193. package/core/shared/skills/do-code-review/languages/go.md +92 -0
  194. package/core/shared/skills/do-code-review/languages/java.md +103 -0
  195. package/core/shared/skills/do-code-review/languages/kotlin.md +88 -0
  196. package/core/shared/skills/do-code-review/languages/php.md +109 -0
  197. package/core/shared/skills/do-code-review/languages/python.md +94 -0
  198. package/core/shared/skills/do-code-review/languages/ruby.md +105 -0
  199. package/core/shared/skills/do-code-review/languages/rust.md +99 -0
  200. package/core/shared/skills/do-code-review/languages/shell.md +90 -0
  201. package/core/shared/skills/do-code-review/languages/swift.md +88 -0
  202. package/core/shared/skills/do-code-review/languages/typescript.md +97 -0
  203. package/core/shared/skills/do-code-review/review-policy.json +47 -0
  204. package/core/shared/skills/do-code-review/rules/universal.md +49 -0
  205. package/core/shared/skills/do-code-review/scripts/code_quality_checker.py +1696 -0
  206. package/core/shared/skills/do-code-review/scripts/doc_quality_checker.py +532 -0
  207. package/core/shared/skills/do-code-review/scripts/pr_analyzer.py +620 -0
  208. package/core/shared/skills/do-code-review/scripts/review_report_generator.py +505 -0
  209. package/core/shared/skills/do-constitution/SKILL.md +72 -0
  210. package/core/shared/skills/do-design/SKILL.md +212 -0
  211. package/core/shared/skills/do-diagnose/SKILL.md +156 -0
  212. package/core/shared/skills/do-diagnose/references/code_audit.md +15 -0
  213. package/core/shared/skills/do-diagnose/references/refactoring.md +12 -0
  214. package/core/shared/skills/do-diagnose/references/root_cause.md +17 -0
  215. package/core/shared/skills/do-document/SKILL.md +81 -0
  216. package/core/shared/skills/do-document/references/api-reference.md +42 -0
  217. package/core/shared/skills/do-document/references/deep_research.md +18 -0
  218. package/core/shared/skills/do-document/references/embedded-research.md +11 -0
  219. package/core/shared/skills/do-document/references/implementation-flow.md +105 -0
  220. package/core/shared/skills/do-document/references/index_generator.md +9 -0
  221. package/core/shared/skills/do-document/references/user-guide.md +22 -0
  222. package/core/shared/skills/do-execute-plan/SKILL.md +261 -0
  223. package/core/shared/skills/do-execute-plan/references/handoff_record.md +57 -0
  224. package/core/shared/skills/do-execute-plan/references/parallel_dispatch.md +92 -0
  225. package/core/shared/skills/do-execute-plan/references/readiness_gate.md +155 -0
  226. package/core/shared/skills/do-execute-plan/references/run_position.md +63 -0
  227. package/core/shared/skills/do-execute-plan/references/scaffold.md +441 -0
  228. package/core/shared/skills/do-execute-plan/references/task_attempts.md +41 -0
  229. package/core/shared/skills/do-flow/SKILL.md +186 -0
  230. package/core/shared/skills/do-flow/references/task_classes.md +134 -0
  231. package/core/shared/skills/do-git/SKILL.md +115 -0
  232. package/core/shared/skills/do-git/references/hotfix-ritual.md +44 -0
  233. package/core/shared/skills/do-git/references/lifecycle-policy.md +54 -0
  234. package/core/shared/skills/do-git/references/release-ritual.md +64 -0
  235. package/core/shared/skills/do-implement/SKILL.md +222 -0
  236. package/core/shared/skills/do-plan/SKILL.md +219 -0
  237. package/core/shared/skills/do-test/SKILL.md +113 -0
  238. package/core/shared/templates/doflow/constitution-template.md +28 -0
  239. package/core/shared/templates/doflow/data-model-template.md +169 -0
  240. package/core/shared/templates/doflow/design-template.md +193 -0
  241. package/core/shared/templates/doflow/external-contract-template.md +35 -0
  242. package/core/shared/templates/doflow/intent-template.md +45 -0
  243. package/core/shared/templates/doflow/plan-template.md +151 -0
  244. package/core/shared/templates/doflow/question-log-template.md +51 -0
  245. package/core/shared/templates/doflow/requirement-template.md +126 -0
  246. package/core/shared/templates/doflow/specs-template.md +55 -0
  247. package/core/shared/templates/doflow/state-template.md +59 -0
  248. package/core/shared/workflows/do-flow-chain.md +17 -0
  249. package/package.json +46 -4
  250. package/src/adapters/antigravity/index.ts +631 -0
  251. package/src/adapters/claude/index.ts +548 -0
  252. package/src/adapters/claude/mcp.ts +94 -0
  253. package/src/adapters/codex/agents.ts +208 -0
  254. package/src/adapters/codex/config.ts +272 -0
  255. package/src/adapters/codex/hooks.ts +203 -0
  256. package/src/adapters/codex/index.ts +707 -0
  257. package/src/adapters/codex/mcp.ts +271 -0
  258. package/src/adapters/codex/native-projection.ts +34 -0
  259. package/src/adapters/copilot/index.ts +413 -0
  260. package/src/adapters/copy-tree.ts +620 -0
  261. package/src/adapters/gemini/hooks.ts +210 -0
  262. package/src/adapters/gemini/index.ts +390 -0
  263. package/src/adapters/hook-commands.ts +60 -0
  264. package/src/adapters/index.ts +106 -0
  265. package/src/adapters/kiro/index.ts +310 -0
  266. package/src/adapters/mcp-entries.ts +331 -0
  267. package/src/adapters/opencode/index.ts +466 -0
  268. package/src/adapters/pi/index.ts +279 -0
  269. package/src/adapters/pi/json-members.ts +185 -0
  270. package/src/adapters/pi/mcp.ts +373 -0
  271. package/src/adapters/resolve-source.ts +19 -0
  272. package/src/cli/commands/install.ts +218 -0
  273. package/src/cli/commands/list-backups.ts +21 -0
  274. package/src/cli/commands/reconcile.ts +120 -0
  275. package/src/cli/commands/remove.ts +82 -0
  276. package/src/cli/commands/rollback.ts +172 -0
  277. package/src/cli/commands/self-update.ts +33 -0
  278. package/src/cli/commands/status.ts +138 -0
  279. package/src/cli/commands/tools.ts +92 -0
  280. package/src/cli/commands/update.ts +162 -0
  281. package/src/cli/index.ts +568 -0
  282. package/src/cli/runtime-commands.ts +281 -0
  283. package/src/cli/shared.ts +218 -0
  284. package/src/helper/bash-helper.ts +34 -0
  285. package/src/helper/git.ts +24 -0
  286. package/src/helper/guardrails.ts +49 -0
  287. package/src/helper/harness-paths.ts +140 -0
  288. package/src/helper/marker-merge.ts +116 -0
  289. package/src/helper/prompt.ts +61 -0
  290. package/src/helper/repo-root.ts +29 -0
  291. package/src/helper/settings-merge.ts +151 -0
  292. package/src/helper/settings-scope.ts +33 -0
  293. package/src/helper/toml.ts +244 -0
  294. package/src/install/backup-set.ts +149 -0
  295. package/src/install/backup.ts +724 -0
  296. package/src/install/context.ts +58 -0
  297. package/src/install/manifest.ts +145 -0
  298. package/src/install/mcp.ts +254 -0
  299. package/src/install/paths.ts +84 -0
  300. package/src/install/targets.ts +90 -0
  301. package/src/install/tool-lifecycle.ts +151 -0
  302. package/src/lifecycle/bash-availability.ts +25 -0
  303. package/src/lifecycle/index.ts +812 -0
  304. package/src/lifecycle/mcp-index.ts +28 -0
  305. package/src/lifecycle/policies.ts +73 -0
  306. package/src/lifecycle/view.ts +175 -0
  307. package/src/registry/index.ts +611 -0
  308. package/src/release/sync-plugin-versions.ts +66 -0
  309. package/src/runtime/advice/cli.ts +283 -0
  310. package/src/runtime/advice/client.ts +324 -0
  311. package/src/runtime/advice/config.ts +189 -0
  312. package/src/runtime/advice/doctor.ts +169 -0
  313. package/src/runtime/advice/endpoint-guard.ts +134 -0
  314. package/src/runtime/advice/kinds.ts +154 -0
  315. package/src/runtime/advice/providers/ollama-systemone.ts +209 -0
  316. package/src/runtime/advice/record.ts +166 -0
  317. package/src/runtime/advice/registry.ts +170 -0
  318. package/src/runtime/advice/strength.ts +66 -0
  319. package/src/runtime/brief-tools.ts +342 -0
  320. package/src/runtime/c4-project.ts +371 -0
  321. package/src/runtime/capability-router.ts +484 -0
  322. package/src/runtime/checkouts.ts +170 -0
  323. package/src/runtime/claims.ts +468 -0
  324. package/src/runtime/cli-result.ts +55 -0
  325. package/src/runtime/cli.ts +678 -0
  326. package/src/runtime/command-detect.ts +516 -0
  327. package/src/runtime/context-pack.ts +492 -0
  328. package/src/runtime/decision-register.ts +493 -0
  329. package/src/runtime/evidence-ledger.ts +338 -0
  330. package/src/runtime/failure/capture.ts +272 -0
  331. package/src/runtime/failure/classifier.ts +68 -0
  332. package/src/runtime/failure/cli.ts +178 -0
  333. package/src/runtime/failure/home.ts +64 -0
  334. package/src/runtime/failure/store.ts +226 -0
  335. package/src/runtime/feature-resolve.ts +79 -0
  336. package/src/runtime/freshness.ts +177 -0
  337. package/src/runtime/health.ts +863 -0
  338. package/src/runtime/history-compactor.ts +237 -0
  339. package/src/runtime/implementation-gate.ts +321 -0
  340. package/src/runtime/inventory/coverage.ts +218 -0
  341. package/src/runtime/inventory/identity.ts +65 -0
  342. package/src/runtime/inventory/index.ts +705 -0
  343. package/src/runtime/inventory/precedence.ts +134 -0
  344. package/src/runtime/inventory/read-scopes.ts +131 -0
  345. package/src/runtime/inventory/siblings.ts +192 -0
  346. package/src/runtime/knowledge/chunker.ts +124 -0
  347. package/src/runtime/knowledge/hybrid.ts +149 -0
  348. package/src/runtime/knowledge/index-store.ts +145 -0
  349. package/src/runtime/knowledge/retrieval.ts +194 -0
  350. package/src/runtime/leak-scan.ts +185 -0
  351. package/src/runtime/lifecycle/cli.ts +276 -0
  352. package/src/runtime/lifecycle/event-store.ts +340 -0
  353. package/src/runtime/lifecycle/fold.ts +353 -0
  354. package/src/runtime/lifecycle/followup.ts +432 -0
  355. package/src/runtime/lifecycle/goal.ts +249 -0
  356. package/src/runtime/lifecycle/intent-writer.ts +86 -0
  357. package/src/runtime/lifecycle/overview.ts +292 -0
  358. package/src/runtime/lifecycle/release.ts +241 -0
  359. package/src/runtime/lifecycle/report-store.ts +221 -0
  360. package/src/runtime/lifecycle/retention.ts +212 -0
  361. package/src/runtime/lifecycle/root.ts +71 -0
  362. package/src/runtime/lifecycle/status.ts +353 -0
  363. package/src/runtime/lifecycle/store-upkeep.ts +393 -0
  364. package/src/runtime/locator-resolve.ts +158 -0
  365. package/src/runtime/mask.ts +210 -0
  366. package/src/runtime/mcp-consultations.ts +412 -0
  367. package/src/runtime/mcp-reach.ts +157 -0
  368. package/src/runtime/model-router.ts +153 -0
  369. package/src/runtime/outcome.ts +467 -0
  370. package/src/runtime/reach.ts +148 -0
  371. package/src/runtime/readiness-record.ts +150 -0
  372. package/src/runtime/readiness.ts +435 -0
  373. package/src/runtime/recovery.ts +282 -0
  374. package/src/runtime/research-request.ts +231 -0
  375. package/src/runtime/retrieval-plan.ts +578 -0
  376. package/src/runtime/scaffold/artifacts.ts +217 -0
  377. package/src/runtime/scaffold/fingerprint.ts +56 -0
  378. package/src/runtime/scaffold/generate.ts +911 -0
  379. package/src/runtime/scaffold/languages.ts +245 -0
  380. package/src/runtime/storage/cli.ts +64 -0
  381. package/src/runtime/storage/engine.ts +249 -0
  382. package/src/runtime/storage/registry.ts +130 -0
  383. package/src/runtime/storage/roots.ts +63 -0
  384. package/src/runtime/storage/rules.ts +282 -0
  385. package/src/runtime/storage/upkeep.ts +243 -0
  386. package/src/runtime/storage/work-status.ts +326 -0
  387. package/src/runtime/task-attempts.ts +415 -0
  388. package/src/runtime/task-classifier.ts +550 -0
  389. package/src/runtime/task-scope.ts +130 -0
  390. package/src/runtime/task-state.ts +176 -0
  391. package/src/runtime/trace/indicators.ts +235 -0
  392. package/src/runtime/trace/ledger.ts +626 -0
  393. package/src/runtime/trace/render.ts +76 -0
  394. package/src/runtime/trace/views.ts +459 -0
  395. package/src/runtime/verification/contract-runner.ts +341 -0
  396. package/src/runtime/verification/engine.ts +1461 -0
  397. package/src/runtime/verification/registry.ts +130 -0
  398. package/src/runtime/verification/scope-bound.ts +418 -0
  399. package/src/runtime/verification/test-selection.ts +172 -0
  400. package/src/runtime/workflow-engine.ts +588 -0
  401. package/src/runtime/workflow-orchestrator.ts +953 -0
  402. package/src/runtime/worktree.ts +340 -0
  403. package/src/state/index.ts +193 -0
  404. package/src/state/lockfile.ts +136 -0
  405. package/src/state/run-lock.ts +408 -0
  406. package/types/node-commonjs.d.ts +68 -0
  407. package/types/runtime.d.ts +91 -0
@@ -0,0 +1,60 @@
1
+ 'use strict';
2
+
3
+ // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
+
5
+ // Shared hook-command verification — the one piece of codex/hooks.ts and gemini/hooks.ts that
6
+ // proved byte-identical on inspection (unlike SUPPORTED_EVENTS, validateHooksConfig, and
7
+ // classifyClaudeGuardrails, which encode genuine per-harness differences and stay in each
8
+ // adapter). verifyHookCommands and the two private helpers it calls, commandScriptNames and
9
+ // hookHandlers, check that a hook config's command handlers resolve to a real, executable script
10
+ // in the harness's own hooks directory — that check does not vary by harness, so it lives once.
11
+ const fs = require('node:fs');
12
+ const path = require('node:path');
13
+
14
+ function commandScriptNames(command: string): string[] {
15
+ // DoFlow's wrappers are shell scripts selected from a project or CODEX_HOME hooks directory.
16
+ // Extracting the basename works for both literal and command-substitution based paths.
17
+ return [...new Set((command.match(/[A-Za-z0-9][A-Za-z0-9_-]*\.sh\b/g) || []))];
18
+ }
19
+
20
+ function hookHandlers(config: any): { event: string, handler: any }[] {
21
+ return Object.entries(config.hooks || {}).flatMap(([event, groups]: [string, any]) =>
22
+ (Array.isArray(groups) ? groups : []).flatMap((group: any) =>
23
+ (Array.isArray(group?.hooks) ? group.hooks : []).map((handler: any) => ({ event, handler }))));
24
+ }
25
+
26
+ // On `trusted`: both harnesses gate hook execution behind their own trust prompt — Codex through
27
+ // its config, Gemini by fingerprinting a hook's name and command and warning before running one
28
+ // that changed (geminicli.com/docs/hooks/). DoFlow verifies neither gate live; doing so would need
29
+ // a running CLI session. It reports trust as a prerequisite whose shape it observed, not one it
30
+ // bypassed or assumed satisfied. That reading is identical for both harnesses, which is part of
31
+ // why this function is shared.
32
+ // Windows carries no executable permission bits — statSync().mode always reports 0666/0444 and
33
+ // chmodSync can only toggle the read-only flag — so the POSIX "not executable" failure mode
34
+ // cannot exist there. Requiring the bit would refuse every hooks install on win32 (the scripts
35
+ // are invoked through an explicit `bash <script>` command string, which needs no +x), so the
36
+ // exec-bit half of the check is POSIX-only; existence is checked everywhere.
37
+ const EXEC_BITS_EXIST = process.platform !== 'win32';
38
+
39
+ function verifyHookCommands(config: any, { scriptsDir, trusted = false, fsImpl = fs }: { scriptsDir?: string, trusted?: boolean, fsImpl?: any } = {}): any {
40
+ const checks: any[] = [];
41
+ for (const { event, handler } of hookHandlers(config)) {
42
+ if (!handler || handler.type !== 'command' || typeof handler.command !== 'string' || !handler.command.trim()) continue;
43
+ const names = commandScriptNames(handler.command);
44
+ if (names.length === 0) {
45
+ checks.push({ event, command: handler.command, ok: false, reason: 'Command does not identify a hook script', requiresTrust: true, trusted });
46
+ continue;
47
+ }
48
+ for (const name of names) {
49
+ const file = scriptsDir ? path.join(scriptsDir, name) : null;
50
+ const exists = Boolean(file && fsImpl.existsSync(file));
51
+ const executable = exists && (!EXEC_BITS_EXIST || Boolean(fsImpl.statSync(file).mode & 0o111));
52
+ checks.push({ event, command: handler.command, script: name, file, exists, executable,
53
+ ok: exists && executable, reason: !exists ? 'Hook script is missing' : (!executable ? 'Hook script is not executable' : null),
54
+ requiresTrust: true, trusted });
55
+ }
56
+ }
57
+ return { ok: checks.every((check: any) => check.ok), checks, trust: { required: checks.length > 0, trusted: Boolean(trusted), status: trusted ? 'trusted' : 'review-required' } };
58
+ }
59
+
60
+ module.exports = { commandScriptNames, hookHandlers, verifyHookCommands };
@@ -0,0 +1,106 @@
1
+ 'use strict';
2
+
3
+ // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
+
5
+ // Harness adapters own native formats and paths. This module intentionally only
6
+ // validates and resolves that boundary; it never reads or writes harness files.
7
+ const { resolveRegistrySource } = require('./resolve-source.ts');
8
+
9
+ const ADAPTER_METHODS = Object.freeze(['discover', 'render', 'plan', 'apply', 'remove', 'verify']);
10
+
11
+ /** Per-adapter native-projection normalizers. Each lives in its adapter's own directory (review
12
+ * A3: the Codex shape used to be inlined here, putting per-harness knowledge on the shared side of
13
+ * the boundary); this module only dispatches by adapter name. An adapter gaining a
14
+ * nativeProjection declaration registers its normalizer here. */
15
+ const NATIVE_PROJECTION_NORMALIZERS: Record<string, () => any> = Object.freeze({
16
+ codex: () => require('./codex/native-projection.ts').normalizeNativeProjection,
17
+ });
18
+
19
+ /** Dispatch a harness's nativeProjection declaration to its adapter's own normalizer. */
20
+ function nativeProjectionFor(registry: any, harness: any, mcp: any, context: any) {
21
+ if (!harness.nativeProjection) return {};
22
+ const load = NATIVE_PROJECTION_NORMALIZERS[harness.adapter];
23
+ if (!load) {
24
+ throw new Error(`No native projection normalizer is registered for '${harness.adapter}'. `
25
+ + `Registered: ${Object.keys(NATIVE_PROJECTION_NORMALIZERS).join(', ')}`);
26
+ }
27
+ return load()(registry, harness, mcp, context);
28
+ }
29
+
30
+ /**
31
+ * Convert validated registry declarations into the only generic payload an
32
+ * adapter receives. Native serializers may add adapter-specific fields, but
33
+ * cannot infer applicability from a missing projection.
34
+ */
35
+ function projectAdapterInput({ registry, harness, scope, scopeRoot, assets = [], mcp = [], mcpAdoptable = [], policies = [], context = {} }: any) {
36
+ if (!registry || !harness) throw new Error('registry and harness are required for adapter projection');
37
+ const projectAsset = (asset: any) => {
38
+ const projection = asset?.projection?.[harness.id];
39
+ if (!projection || typeof projection.renderer !== 'string' || typeof projection.capability !== 'string') {
40
+ throw new Error(`Asset '${asset?.id ?? '?'}' lacks a projection for '${harness.id}'`);
41
+ }
42
+ const capability = harness.capabilities?.[projection.capability];
43
+ if (!capability || capability.status === 'unavailable') {
44
+ throw new Error(`Asset '${asset.id}' cannot project unavailable '${harness.id}' capability '${projection.capability}'`);
45
+ }
46
+ return Object.freeze({
47
+ id: asset.id, kind: asset.kind, source: asset.source, ownership: asset.ownership,
48
+ renderer: projection.renderer, capability: projection.capability,
49
+ capabilityStatus: capability.status, nativeTarget: harness.nativeTargets?.[projection.capability] ?? null,
50
+ nativeDir: asset.nativeDir?.[harness.id] ?? null,
51
+ // Optional destination shape for copy-tree assets. Null for every projection that mirrors
52
+ // source paths, which is all of them except Antigravity's directory-per-agent requirement.
53
+ layout: projection.layout ?? null,
54
+ transform: projection.transform ?? null,
55
+ prerequisites: [...(capability.prerequisites || [])],
56
+ });
57
+ };
58
+ if (mcp.length && (!harness.capabilities?.mcp || harness.capabilities.mcp.status === 'unavailable')) {
59
+ throw new Error(`Selected MCP servers cannot project to unavailable '${harness.id}' MCP capability`);
60
+ }
61
+ const projection = nativeProjectionFor(registry, harness, mcp, context);
62
+ return Object.freeze({
63
+ harness, scope, scopeRoot, context,
64
+ assets: Object.freeze(assets.map(projectAsset)),
65
+ mcp: Object.freeze(mcp.map((server: any) => Object.freeze({ ...server }))),
66
+ // Servers whose existing entries the adapter may take as its own while it holds no MCP row.
67
+ mcpAdoptable: Object.freeze(mcpAdoptable.map((server: any) => Object.freeze({ ...server }))),
68
+ policies: Object.freeze(policies.map((policy: any) => Object.freeze({ ...policy }))),
69
+ nativeTargets: Object.freeze({ ...harness.nativeTargets }),
70
+ projection: Object.freeze({ ...projection }),
71
+ });
72
+ }
73
+
74
+ function assertAdapter(adapter: any, name = 'adapter') {
75
+ if (!adapter || typeof adapter !== 'object') throw new Error(`${name} must be an object`);
76
+ for (const method of ADAPTER_METHODS) {
77
+ if (typeof adapter[method] !== 'function') throw new Error(`${name} must implement ${method}()`);
78
+ }
79
+ return adapter;
80
+ }
81
+
82
+ function createAdapterRegistry(adapters = {}) {
83
+ const entries = adapters instanceof Map ? [...adapters.entries()] : Object.entries(adapters);
84
+ const resolved = new Map();
85
+ for (const [name, adapter] of entries) {
86
+ if (typeof name !== 'string' || !name.trim()) throw new Error('Adapter names must be non-empty strings');
87
+ resolved.set(name, assertAdapter(adapter, `Adapter '${name}'`));
88
+ }
89
+ return Object.freeze({
90
+ names: () => [...resolved.keys()],
91
+ has: (name: any) => resolved.has(name),
92
+ get(name: any) {
93
+ const adapter = resolved.get(name);
94
+ if (!adapter) throw new Error(`No registered adapter '${name}'`);
95
+ return adapter;
96
+ },
97
+ });
98
+ }
99
+
100
+ function resolveAdapter(adapterRegistry: any, harness: any) {
101
+ if (!adapterRegistry || typeof adapterRegistry.get !== 'function') throw new Error('adapterRegistry must expose get(name)');
102
+ if (!harness || typeof harness.adapter !== 'string') throw new Error('Harness must declare an adapter');
103
+ return adapterRegistry.get(harness.adapter);
104
+ }
105
+
106
+ module.exports = { ADAPTER_METHODS, assertAdapter, createAdapterRegistry, resolveAdapter, resolveRegistrySource, nativeProjectionFor, projectAdapterInput };
@@ -0,0 +1,310 @@
1
+ 'use strict';
2
+
3
+ // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
+
5
+ // Kiro adapter.
6
+ //
7
+ // Kiro's native root is symmetric across scopes — `.kiro/` (project) / `~/.kiro/` (global) is the
8
+ // one directory that holds everything Kiro reads: steering, agents, hooks, and settings/mcp.json
9
+ // (see src/targets.js's toolDirs() for the same convention this adapter's own nativePaths()
10
+ // mirrors). Unlike every other harness in this codebase, Kiro receives DoFlow's *full* guidance
11
+ // tree as steering files rather than a single marker-wrapped pointer file plus a separately-copied
12
+ // tree (design.md §4's "research decision D3"): there is no single-file instruction surface here
13
+ // at all, so — unlike src/adapters/gemini or src/adapters/opencode — this adapter never renders a
14
+ // marker-wrapped instruction file.
15
+ //
16
+ // Evidence: https://kiro.dev/docs/steering/, https://kiro.dev/docs/mcp/configuration/,
17
+ // https://kiro.dev/docs/hooks/
18
+ const fs = require('node:fs');
19
+ const path = require('node:path');
20
+ const { planTree, applyTree, removeTree, verifyTree, resolveTransform, copyTreeAssets, copyTreeDestDir, ledgerFileResources, ledgerSiblingFingerprints, siblingReplacedNotices, sourceDirFor } = require('../copy-tree.ts');
21
+ const { readMcpFiles, planMcpEntries, verifyMcpEntries, ownedMcpIds, writeMcpEntries } = require('../mcp-entries.ts');
22
+ const { declaredHarnessPaths, resolveHarnessPaths } = require('../../helper/harness-paths.ts');
23
+
24
+ const HARNESS = 'kiro';
25
+ const MCP_CONTAINER = 'mcpServers';
26
+ const MCP_RENDERER = 'kiro-mcp';
27
+ // Releases up to 1.18.0 recorded one `kiro:mcp:<id>` row per server (and never a row for the old
28
+ // `kiro:mcp:registration` change); they are read as owned rows until a run replaces them.
29
+ const LEGACY_MCP_PREFIX = `${HARNESS}:mcp:`;
30
+ const LEGACY_MCP_REGISTRATION = `${HARNESS}:mcp:registration`;
31
+
32
+ /**
33
+ * Native path facts live in core/registry/harnesses.json under this harness's "paths" section and
34
+ * resolve through the shared harness-paths resolver; `.kiro` (project) / `~/.kiro` (global) is the
35
+ * whole native root and every other path here is a fixed subpath under it.
36
+ * createKiroAdapter({ declaredPaths }) is the injection point buildAdapterRegistry() uses;
37
+ * module-level exports delegate to a default-configured instance so direct callers keep their
38
+ * historical shape.
39
+ */
40
+ function createKiroAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS] } = {}) {
41
+ // Parity note: Kiro's historical nativePaths() derived even its user-scope root from scopeRoot
42
+ // (the CLI passes $HOME there for -g installs), never from a separate homeDir argument — so the
43
+ // resolver is fed no homeDir and "root" keeps resolving exactly as before.
44
+ function nativePaths({ scope, scopeRoot }: any = {}) {
45
+ return resolveHarnessPaths(declaredPaths, { scope, scopeRoot });
46
+ }
47
+
48
+ /** Discovery keeps the MCP files as plan read them (`mcpSnapshot`), which verify compares against,
49
+ * and reports the servers DoFlow owns in Kiro's mcp.json now (`mcpOwned`). */
50
+ function discover({ scope, scopeRoot, mcp = [], mcpAdoptable = [], ledger, fsImpl = fs }: any) {
51
+ const paths = nativePaths({ scope, scopeRoot });
52
+ const entries = mcpEntriesInput({ paths, mcp, mcpAdoptable, ledger });
53
+ const mcpSnapshot = readMcpFiles({ file: entries.file, ownRows: entries.ownRows, container: MCP_CONTAINER, fsImpl });
54
+ const read = mcpSnapshot[entries.file];
55
+ // `null` while the file is absent, unreadable or has no server map; every name in it otherwise, whoever wrote it.
56
+ const mcpConfigured = read?.ok && read.servers ? Object.keys(read.servers).sort() : null;
57
+ return { paths, mcpSnapshot, mcpOwned: ownedMcpIds({ ...entries, files: mcpSnapshot }), mcpConfigured };
58
+ }
59
+
60
+ /**
61
+ * Kiro has no single-file, marker-managed instruction surface for this adapter to render into —
62
+ * the guidance tree is projected file-for-file by the copy-tree engine below, once as steering
63
+ * (guidance.context-layer) and once into the shared `.doflow/guidance` (kiro.guidance-tree). Every
64
+ * asset routed to 'kiro' in core/registry/assets.json uses `renderer: copy-tree` or
65
+ * `kiro-agents`, so nothing reaches this function. It is kept as a pure passthrough only to
66
+ * satisfy the six-function adapter contract every harness must implement identically.
67
+ */
68
+ function render({ content = '' }: any = {}) {
69
+ return String(content);
70
+ }
71
+
72
+ // ---- copy-tree assets (steering tree, agents) ----
73
+
74
+ /**
75
+ * Kiro has a dedicated skills system (https://kiro.dev/docs/skills/): a folder containing
76
+ * `SKILL.md` with YAML frontmatter, optionally alongside scripts/references/assets — the same open
77
+ * Agent Skills standard DoFlow already authors, scanned from `.kiro/skills/` (workspace) and
78
+ * `~/.kiro/skills/` (global). `skills.doflow` therefore materialises like every other harness's
79
+ * skills tree, no exclusion needed.
80
+ *
81
+ * `agents.shared` is included alongside the generic `copy-tree` renderer even though its own
82
+ * projection declares `renderer: 'kiro-agents'` — a distinct name chosen so the registry can tell
83
+ * the two apart. Both materialise through the same engine, but `kiro-agents` declares the
84
+ * `kiro-agent-json` layout and `kiro-agents` transform: kiro-cli discovers agents as
85
+ * `.kiro/agents/<name>.json`, so each shared `<name>.md` spec is rendered, not mirrored.
86
+ */
87
+ function kiroTreeAssets(assets: any) {
88
+ return [...copyTreeAssets(assets), ...(assets || []).filter((asset: any) => asset.renderer === 'kiro-agents')];
89
+ }
90
+
91
+ function planCopyTreeAssets({ assets, scope, scopeRoot, context, ledger, removing, fsImpl = fs }: any) {
92
+ const paths = nativePaths({ scope, scopeRoot });
93
+ const changes = [];
94
+ const conflicts = [];
95
+ const treeResults = [];
96
+ const notices = [];
97
+ for (const asset of kiroTreeAssets(assets)) {
98
+ const destDir = copyTreeDestDir(paths.configDir, asset);
99
+ const sourceDir = sourceDirFor(asset, context, fsImpl, 'Kiro');
100
+ const previousResources = ledgerFileResources(ledger?.resources, HARNESS, asset.id);
101
+ const result = planTree({ sourceDir, destDir, previousResources, siblingFingerprints: ledgerSiblingFingerprints(ledger?.resources, HARNESS), operation: removing ? 'remove' : 'apply', fsImpl, layout: asset.layout, transform: asset.transform, keepModified: !removing,
102
+ // Forwarded so the CLI's --force reaches planTree's conflict check; omitting it let
103
+ // planTree's own `force = false` default stand in silently. Gated on `!removing` for the
104
+ // reason codex/index.ts states in full: force heals drift on apply, but a hand-edited file
105
+ // is never deleted on removal, forced or not.
106
+ force: !removing && context?.force === true, });
107
+ treeResults.push(result);
108
+ conflicts.push(...result.conflicts.map((reason: any) => `${asset.id}: ${reason}`));
109
+ // A hand-edited file at a path DoFlow no longer writes is the user's: it stays, only its
110
+ // ownership row is released.
111
+ notices.push(...result.kept.map((item: any) => `kept hand-edited ${path.relative(paths.root, item.target)}; DoFlow no longer manages it`));
112
+ for (const change of result.changes) {
113
+ changes.push({
114
+ assetId: asset.id, target: change.target, source: change.source, operation: change.operation,
115
+ ownershipIdentity: `doflow:${HARNESS}:copy-tree:${asset.id}:${change.relPath}`,
116
+ kind: 'copy-tree-file', identity: change.relPath,
117
+ afterFingerprint: change.fingerprint, fingerprint: change.fingerprint, sourceVersion: 'registry-v1',
118
+ transformName: asset.transform || null,
119
+ ...(change.kept ? { retained: true, retainedFor: [] } : {}),
120
+ projection: { renderer: asset.renderer },
121
+ });
122
+ }
123
+ }
124
+ return { changes, conflicts, notices: [...siblingReplacedNotices(treeResults), ...notices] };
125
+ }
126
+
127
+ function applyCopyTreeAssets(changes: any, { fsImpl = fs }: any = {}) {
128
+ let applied = 0;
129
+ const grouped = new Map();
130
+ for (const change of changes) {
131
+ if (change.kind !== 'copy-tree-file' || change.operation === 'remove') continue;
132
+ const key = change.transformName || null;
133
+ if (!grouped.has(key)) grouped.set(key, []);
134
+ grouped.get(key).push({ relPath: change.identity, target: change.target, source: change.source, operation: change.operation, fingerprint: change.fingerprint });
135
+ }
136
+ for (const [transformName, treeChanges] of grouped) {
137
+ applied += applyTree({ changes: treeChanges, fsImpl, transform: resolveTransform(transformName) }).applied;
138
+ }
139
+ return applied;
140
+ }
141
+
142
+ function removeCopyTreeAssets(changes: any, { fsImpl = fs }: any = {}) {
143
+ const treeChanges = changes.filter((change: any) => change.kind === 'copy-tree-file' && change.operation === 'remove' && !change.retained)
144
+ .map((change: any) => ({ relPath: change.identity, target: change.target, operation: 'remove', fingerprint: change.fingerprint, pruneGuard: change.pruneGuard }));
145
+ return removeTree({ changes: treeChanges, fsImpl }).removed;
146
+ }
147
+
148
+ function verifyCopyTreeAssets({ assets, scope, scopeRoot, context, fsImpl = fs }: any) {
149
+ const paths = nativePaths({ scope, scopeRoot });
150
+ const statuses = [];
151
+ const resources = [];
152
+ const conflicts = [];
153
+ for (const asset of kiroTreeAssets(assets)) {
154
+ const destDir = copyTreeDestDir(paths.configDir, asset);
155
+ const sourceDir = sourceDirFor(asset, context, fsImpl, 'Kiro');
156
+ const result = verifyTree({ sourceDir, destDir, fsImpl, layout: asset.layout, transform: asset.transform, plannedWrites: context?.plannedWrites });
157
+ conflicts.push(...result.conflicts.map((reason: any) => `${asset.id}: ${reason}`));
158
+ for (const resource of result.resources) {
159
+ resources.push({
160
+ assetId: asset.id, target: resource.target, ownershipIdentity: `doflow:${HARNESS}:copy-tree:${asset.id}:${resource.relPath}`,
161
+ kind: 'copy-tree-file', identity: resource.relPath,
162
+ fingerprint: resource.fingerprint, sourceVersion: 'registry-v1',
163
+ projection: { renderer: asset.renderer },
164
+ });
165
+ }
166
+ statuses.push({ assetId: asset.id, capability: asset.capability, status: result.ok ? 'managed' : 'conflict', target: destDir });
167
+ }
168
+ return { statuses, resources, conflicts };
169
+ }
170
+
171
+ // ---- MCP (.kiro/settings/mcp.json) ----
172
+
173
+ /**
174
+ * Shape one registry MCP server declaration into Kiro's own per-server schema (confirmed against
175
+ * kiro.dev/docs/mcp/configuration/): a local (stdio) server carries `command`/`args`/`env`/
176
+ * `disabled`/`autoApprove`/`disabledTools`; a remote server carries `url`/`headers` instead. The
177
+ * registry (core/registry/mcp.json) only ever declares stdio servers today, so only the fields it
178
+ * actually carries are emitted — this never invents a field the registry doesn't supply.
179
+ */
180
+ function buildServerEntry(server: any) {
181
+ if (server.url) return { url: server.url, ...(server.headers ? { headers: server.headers } : {}) };
182
+ return { command: server.command, ...(server.args?.length ? { args: server.args } : {}) };
183
+ }
184
+
185
+ function ownershipIdentity(id: any) { return `doflow:${HARNESS}:mcp-server:${id}`; }
186
+
187
+ function mcpOwnRows(ledger: any) {
188
+ return (ledger?.resources || []).filter((row: any) => row.harness === HARNESS).flatMap((row: any) => {
189
+ if (row.kind === 'mcp-server') {
190
+ return [{ identity: row.identity, target: row.target, fingerprint: row.fingerprint ?? null, ownershipIdentity: row.ownershipIdentity, legacy: false }];
191
+ }
192
+ const legacyIdentity = row.ownershipIdentity;
193
+ if (typeof legacyIdentity !== 'string' || !legacyIdentity.startsWith(LEGACY_MCP_PREFIX) || legacyIdentity === LEGACY_MCP_REGISTRATION) return [];
194
+ return [{ identity: legacyIdentity.slice(LEGACY_MCP_PREFIX.length), target: row.target, fingerprint: row.fingerprint ?? null, ownershipIdentity: legacyIdentity, legacy: true }];
195
+ });
196
+ }
197
+
198
+ /** Everything the shared entry-ownership rules (../mcp-entries.ts) need from this adapter. */
199
+ function mcpEntriesInput({ paths, mcp = [], mcpAdoptable = [], ledger, assets = [] }: any) {
200
+ const rendered = (servers: any) => servers.map((server: any) => ({ id: server.id, entry: buildServerEntry(server) }));
201
+ return {
202
+ file: paths.mcp, selected: rendered(mcp), adoptable: rendered(mcpAdoptable),
203
+ ownRows: mcpOwnRows(ledger),
204
+ foreignRows: (ledger?.resources || []).filter((row: any) => row.kind === 'mcp-server' && row.harness !== HARNESS)
205
+ .map((row: any) => ({ harness: row.harness, identity: row.identity, target: row.target })),
206
+ identityFor: ownershipIdentity, assetId: pseudoAssetId(assets), renderer: MCP_RENDERER, label: 'Kiro MCP',
207
+ };
208
+ }
209
+
210
+ /** Kiro has no hooks or mcp asset of its own in core/registry/assets.json (mcp servers come from
211
+ * core/registry/mcp.json, not an asset), so an MCP entry change piggybacks on an asset id
212
+ * this harness actually receives — the same "pseudo-component" technique
213
+ * src/adapters/gemini/index.ts#hooksAssetId already uses for its own settings-only component. */
214
+ function pseudoAssetId(assets: any) {
215
+ return assets.find((asset: any) => asset.id === 'guidance.context-layer')?.id ?? assets[0]?.id;
216
+ }
217
+
218
+ // ---- shared adapter contract ----
219
+
220
+ /**
221
+ * `.kiro/hooks/` is now a real, populated native surface: `kiro.hooks-scripts`
222
+ * (core/registry/assets.json) is a copy-tree asset like skills/agents, so `kiroTreeAssets()` above
223
+ * already plans/applies/removes it alongside them. This function only reports the
224
+ * declarative capability surface — same unconditional shape `plan()` already uses for
225
+ * instructions/skills/agents — not whether that asset happens to be present in a given call's
226
+ * `assets` array; per-file installed status for the hooks tree itself is reported through
227
+ * `copyTree.statuses`/`copyTree.resources`, exactly like it is for skills and agents.
228
+ */
229
+ function hooksSurface(paths: any) {
230
+ return { status: 'supported', target: paths.hooks };
231
+ }
232
+
233
+ function plan({ scope, scopeRoot, assets = [], mcp = [], mcpAdoptable = [], discovery, context = {}, ledger, fsImpl = fs }: any) {
234
+ const found = discovery || discover({ scope, scopeRoot, mcp, mcpAdoptable, ledger, fsImpl });
235
+ const changes = [];
236
+ const conflicts = [];
237
+ const removing = context.operation === 'remove';
238
+
239
+ const copyTree = planCopyTreeAssets({ assets, scope, scopeRoot, context, ledger, removing, fsImpl });
240
+ changes.push(...copyTree.changes);
241
+ conflicts.push(...copyTree.conflicts);
242
+
243
+ const mcpPlan = planMcpEntries({
244
+ ...mcpEntriesInput({ paths: found.paths, mcp, mcpAdoptable, ledger, assets }), files: found.mcpSnapshot, removing,
245
+ });
246
+ changes.push(...mcpPlan.changes);
247
+ conflicts.push(...mcpPlan.conflicts);
248
+
249
+ return {
250
+ changes, conflicts, prerequisites: [], notices: [...copyTree.notices, ...mcpPlan.notices],
251
+ surfaces: {
252
+ instructions: { status: 'supported', target: found.paths.steering },
253
+ skills: { status: 'supported', target: found.paths.skills },
254
+ agents: { status: 'supported', target: found.paths.agents },
255
+ hooks: hooksSurface(found.paths),
256
+ mcp: { status: found.mcpSnapshot[found.paths.mcp].ok ? 'supported' : 'blocked', target: found.paths.mcp, selected: mcp.map((item: any) => item.id) },
257
+ },
258
+ };
259
+ }
260
+
261
+ function apply({ changes = [], fsImpl = fs }: any) {
262
+ writeMcpEntries(changes, { container: MCP_CONTAINER, fsImpl });
263
+ applyCopyTreeAssets(changes, { fsImpl });
264
+ // An update that no longer ships a copy-tree file carries its rows as removals inside the
265
+ // apply batch; the lifecycle calls remove() only for `doflow remove`.
266
+ removeCopyTreeAssets(changes, { fsImpl });
267
+ }
268
+
269
+ function remove({ changes = [], fsImpl = fs }: any) {
270
+ writeMcpEntries(changes, { container: MCP_CONTAINER, fsImpl });
271
+ removeCopyTreeAssets(changes, { fsImpl });
272
+ }
273
+
274
+ function verify({ scope, scopeRoot, assets = [], mcp = [], mcpAdoptable = [], discovery, ledger, operation, context = {}, fsImpl = fs }: any) {
275
+ const paths = nativePaths({ scope, scopeRoot });
276
+ const resources = [];
277
+ const conflicts = [];
278
+
279
+ const copyTree = verifyCopyTreeAssets({ assets, scope, scopeRoot, context, fsImpl });
280
+ resources.push(...copyTree.resources);
281
+ conflicts.push(...copyTree.conflicts);
282
+
283
+ const entries = mcpEntriesInput({ paths, mcp, mcpAdoptable, ledger, assets });
284
+ const files = readMcpFiles({ file: entries.file, ownRows: entries.ownRows, container: MCP_CONTAINER, fsImpl });
285
+ const mcpResult = verifyMcpEntries({
286
+ ...entries, files, snapshot: discovery?.mcpSnapshot ?? files,
287
+ removing: (operation ?? context.operation) === 'remove', harness: HARNESS, sourceVersion: context.sourceVersion ?? 'unknown',
288
+ });
289
+ resources.push(...mcpResult.resources);
290
+ conflicts.push(...mcpResult.conflicts);
291
+
292
+ return {
293
+ ok: conflicts.length === 0,
294
+ resources,
295
+ statuses: { copyTree: copyTree.statuses, mcp: mcpResult.statuses, hooks: hooksSurface(paths) },
296
+ conflicts,
297
+ };
298
+ }
299
+
300
+ return { nativePaths, discover, render, plan, apply, remove, verify, buildServerEntry };
301
+ }
302
+
303
+ const singleton = createKiroAdapter();
304
+
305
+ module.exports = {
306
+ nativePaths: singleton.nativePaths, discover: singleton.discover, render: singleton.render,
307
+ plan: singleton.plan, apply: singleton.apply, remove: singleton.remove, verify: singleton.verify,
308
+ buildServerEntry: singleton.buildServerEntry,
309
+ createKiroAdapter,
310
+ };