@khoavu882/doflow 2.0.0-beta.3 → 2.0.0-beta.5

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 (236) hide show
  1. package/bin/doflow.js +2 -2
  2. package/core/.antigravity-plugin/plugin.json +0 -1
  3. package/core/.claude-plugin/plugin.json +1 -1
  4. package/core/.codex-plugin/plugin.json +1 -1
  5. package/core/.plugin/plugin.json +1 -1
  6. package/core/harnesses/claude/hooks/mcp-tool-guard.sh +7 -17
  7. package/core/harnesses/claude/hooks/pre-bash-guard.sh +7 -17
  8. package/core/harnesses/claude/hooks/pre-implement-gate.sh +7 -18
  9. package/core/harnesses/claude/hooks/session-start.sh +5 -3
  10. package/core/harnesses/claude/hooks/stop-check.sh +5 -3
  11. package/core/harnesses/claude/hooks/subagent-audit.sh +5 -5
  12. package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -3
  13. package/core/harnesses/codex/hooks/mcp-tool-guard.sh +7 -15
  14. package/core/harnesses/codex/hooks/pre-bash-guard.sh +7 -15
  15. package/core/harnesses/codex/hooks/pre-implement-gate.sh +7 -16
  16. package/core/harnesses/codex/hooks/session-start.sh +5 -3
  17. package/core/harnesses/codex/hooks/stop-check.sh +6 -5
  18. package/core/harnesses/codex/hooks/subagent-audit.sh +17 -6
  19. package/core/harnesses/codex/hooks/user-prompt-submit.sh +5 -4
  20. package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +7 -18
  21. package/core/harnesses/gemini/hooks/pre-bash-guard.sh +7 -18
  22. package/core/harnesses/gemini/hooks/pre-implement-gate.sh +7 -19
  23. package/core/harnesses/gemini/hooks/session-start.sh +5 -3
  24. package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +20 -5
  25. package/core/harnesses/kiro/hooks/pre-bash-guard.sh +20 -5
  26. package/core/harnesses/kiro/hooks/pre-implement-gate.sh +20 -5
  27. package/core/harnesses/kiro/hooks/session-start.sh +11 -5
  28. package/core/harnesses/kiro/hooks/stop-check.sh +21 -30
  29. package/core/harnesses/pi/extensions/doflow-guard.js +159 -0
  30. package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +27 -11
  31. package/core/harnesses/shared/hooks/adapters/antigravity.js +14 -57
  32. package/core/harnesses/shared/hooks/bridge/bridge.sh +184 -0
  33. package/core/harnesses/shared/hooks/bridge/envelope.jq +60 -0
  34. package/core/harnesses/shared/hooks/bridge/respond.sh +62 -0
  35. package/core/harnesses/shared/hooks/policies/capture-failure.sh +4 -2
  36. package/core/harnesses/shared/hooks/policies/contract.sh +75 -0
  37. package/core/harnesses/shared/hooks/policies/deny-json.sh +39 -4
  38. package/core/harnesses/shared/hooks/policies/lib.sh +4 -2
  39. package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +46 -34
  40. package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +75 -25
  41. package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +67 -73
  42. package/core/harnesses/shared/hooks/policies/session-context.sh +37 -7
  43. package/core/harnesses/shared/hooks/policies/stop-check.sh +42 -15
  44. package/core/harnesses/shared/hooks/policies/subagent-audit.sh +35 -5
  45. package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +40 -7
  46. package/core/harnesses/shared/hooks/stream-hook-runner.js +69 -181
  47. package/core/registry/assets.json +19 -0
  48. package/core/registry/contracts.json +2 -2
  49. package/core/registry/harnesses.json +196 -10
  50. package/core/registry/lifecycle.json +2626 -7
  51. package/core/registry/storage.json +110 -83
  52. package/core/registry/verification.json +1 -1
  53. package/core/shared/scripts/doflow/bash/render-puml.sh +2 -2
  54. package/core/shared/scripts/doflow/bin/doflow-run +10 -6
  55. package/core/shared/skills/do-design/SKILL.md +6 -6
  56. package/core/shared/skills/do-execute-plan/SKILL.md +11 -10
  57. package/core/shared/skills/do-execute-plan/references/readiness_gate.md +2 -0
  58. package/core/shared/skills/do-execute-plan/references/scaffold.md +2 -2
  59. package/core/shared/skills/do-implement/SKILL.md +3 -2
  60. package/core/shared/skills/do-plan/SKILL.md +7 -8
  61. package/package.json +4 -2
  62. package/src/adapters/antigravity/{index.ts → index.js} +141 -105
  63. package/src/adapters/claude/{index.ts → index.js} +63 -49
  64. package/src/adapters/claude/{mcp.ts → mcp.js} +16 -16
  65. package/src/adapters/codex/{agents.ts → agents.js} +24 -24
  66. package/src/adapters/codex/{config.ts → config.js} +49 -49
  67. package/src/adapters/codex/{hooks.ts → hooks.js} +62 -27
  68. package/src/adapters/codex/{index.ts → index.js} +148 -105
  69. package/src/adapters/codex/{mcp.ts → mcp.js} +38 -38
  70. package/src/adapters/codex/{native-projection.ts → native-projection.js} +5 -5
  71. package/src/adapters/copilot/{index.ts → index.js} +42 -42
  72. package/src/adapters/{copy-tree.ts → copy-tree.js} +74 -74
  73. package/src/adapters/gemini/{hooks.ts → hooks.js} +78 -37
  74. package/src/adapters/gemini/{index.ts → index.js} +96 -57
  75. package/src/adapters/{hook-commands.ts → hook-commands.js} +8 -8
  76. package/src/adapters/{index.ts → index.js} +13 -13
  77. package/src/adapters/kiro/{index.ts → index.js} +49 -35
  78. package/src/adapters/{mcp-entries.ts → mcp-entries.js} +55 -55
  79. package/src/adapters/opencode/{index.ts → index.js} +52 -52
  80. package/src/adapters/pi/hooks.js +119 -0
  81. package/src/adapters/pi/{index.ts → index.js} +64 -39
  82. package/src/adapters/pi/{json-members.ts → json-members.js} +23 -23
  83. package/src/adapters/pi/{mcp.ts → mcp.js} +70 -70
  84. package/src/adapters/{resolve-source.ts → resolve-source.js} +1 -1
  85. package/src/cli/commands/{install.ts → install.js} +25 -25
  86. package/src/cli/commands/{list-backups.ts → list-backups.js} +4 -4
  87. package/src/cli/commands/{reconcile.ts → reconcile.js} +19 -19
  88. package/src/cli/commands/{remove.ts → remove.js} +10 -10
  89. package/src/cli/commands/{rollback.ts → rollback.js} +17 -17
  90. package/src/cli/commands/{self-update.ts → self-update.js} +3 -3
  91. package/src/cli/commands/{status.ts → status.js} +24 -24
  92. package/src/cli/commands/{tools.ts → tools.js} +16 -16
  93. package/src/cli/commands/{update.ts → update.js} +20 -20
  94. package/src/cli/{index.ts → index.js} +43 -31
  95. package/src/cli/{runtime-commands.ts → runtime-commands.js} +97 -58
  96. package/src/cli/{shared.ts → shared.js} +40 -40
  97. package/src/helper/{bash-helper.ts → bash-helper.js} +7 -7
  98. package/src/helper/{git.ts → git.js} +2 -2
  99. package/src/helper/{guardrails.ts → guardrails.js} +10 -10
  100. package/src/helper/{harness-paths.ts → harness-paths.js} +24 -24
  101. package/src/helper/{marker-merge.ts → marker-merge.js} +4 -4
  102. package/src/helper/{prompt.ts → prompt.js} +5 -5
  103. package/src/helper/{repo-root.ts → repo-root.js} +2 -2
  104. package/src/helper/{settings-merge.ts → settings-merge.js} +27 -27
  105. package/src/helper/{settings-scope.ts → settings-scope.js} +3 -3
  106. package/src/helper/{toml.ts → toml.js} +48 -48
  107. package/src/install/{backup-set.ts → backup-set.js} +16 -16
  108. package/src/install/{backup.ts → backup.js} +65 -65
  109. package/src/install/{context.ts → context.js} +15 -15
  110. package/src/install/{manifest.ts → manifest.js} +27 -27
  111. package/src/install/{mcp.ts → mcp.js} +30 -30
  112. package/src/install/{paths.ts → paths.js} +15 -15
  113. package/src/install/{targets.ts → targets.js} +10 -10
  114. package/src/install/{tool-lifecycle.ts → tool-lifecycle.js} +20 -20
  115. package/src/lifecycle/{bash-availability.ts → bash-availability.js} +1 -1
  116. package/src/lifecycle/coverage.js +57 -0
  117. package/src/lifecycle/hook-step.js +61 -0
  118. package/src/lifecycle/{index.ts → index.js} +160 -146
  119. package/src/lifecycle/{mcp-index.ts → mcp-index.js} +1 -1
  120. package/src/lifecycle/{policies.ts → policies.js} +11 -11
  121. package/src/lifecycle/{view.ts → view.js} +28 -28
  122. package/src/registry/{index.ts → index.js} +195 -66
  123. package/src/release/build-package.js +91 -0
  124. package/src/release/changelog-section.js +70 -0
  125. package/src/release/{sync-plugin-versions.ts → sync-plugin-versions.js} +4 -4
  126. package/src/runtime/advice/{cli.ts → cli.js} +31 -31
  127. package/src/runtime/advice/{client.ts → client.js} +44 -44
  128. package/src/runtime/advice/{config.ts → config.js} +16 -16
  129. package/src/runtime/advice/{doctor.ts → doctor.js} +32 -32
  130. package/src/runtime/advice/{endpoint-guard.ts → endpoint-guard.js} +20 -20
  131. package/src/runtime/advice/{kinds.ts → kinds.js} +16 -16
  132. package/src/runtime/advice/providers/{ollama-systemone.ts → ollama-systemone.js} +21 -21
  133. package/src/runtime/advice/{record.ts → record.js} +19 -19
  134. package/src/runtime/advice/{registry.ts → registry.js} +16 -16
  135. package/src/runtime/advice/{strength.ts → strength.js} +7 -7
  136. package/src/runtime/{brief-tools.ts → brief-tools.js} +50 -50
  137. package/src/runtime/{c4-project.ts → c4-project.js} +27 -27
  138. package/src/runtime/candidate.js +505 -0
  139. package/src/runtime/{capability-router.ts → capability-router.js} +39 -39
  140. package/src/runtime/{checkouts.ts → checkouts.js} +21 -21
  141. package/src/runtime/{claims.ts → claims.js} +44 -35
  142. package/src/runtime/{cli-result.ts → cli-result.js} +15 -8
  143. package/src/runtime/{cli.ts → cli.js} +59 -292
  144. package/src/runtime/{command-detect.ts → command-detect.js} +47 -47
  145. package/src/runtime/context/budget.js +203 -0
  146. package/src/runtime/context/compose.js +1367 -0
  147. package/src/runtime/context/delivery-store.js +102 -0
  148. package/src/runtime/context/mandatory.js +594 -0
  149. package/src/runtime/context/pointer.js +142 -0
  150. package/src/runtime/context-pack.js +1277 -0
  151. package/src/runtime/{decision-register.ts → decision-register.js} +67 -67
  152. package/src/runtime/evidence-fields.js +39 -0
  153. package/src/runtime/{evidence-ledger.ts → evidence-ledger.js} +32 -25
  154. package/src/runtime/failure/{capture.ts → capture.js} +29 -29
  155. package/src/runtime/failure/{classifier.ts → classifier.js} +4 -4
  156. package/src/runtime/failure/{cli.ts → cli.js} +30 -30
  157. package/src/runtime/failure/{home.ts → home.js} +6 -6
  158. package/src/runtime/failure/{store.ts → store.js} +32 -32
  159. package/src/runtime/{feature-resolve.ts → feature-resolve.js} +6 -6
  160. package/src/runtime/{freshness.ts → freshness.js} +59 -22
  161. package/src/runtime/{health.ts → health.js} +72 -72
  162. package/src/runtime/{history-compactor.ts → history-compactor.js} +25 -25
  163. package/src/runtime/{implementation-gate.ts → implementation-gate.js} +30 -30
  164. package/src/runtime/inventory/{coverage.ts → coverage.js} +10 -10
  165. package/src/runtime/inventory/{identity.ts → identity.js} +2 -2
  166. package/src/runtime/inventory/{index.ts → index.js} +36 -36
  167. package/src/runtime/inventory/{precedence.ts → precedence.js} +2 -2
  168. package/src/runtime/inventory/{read-scopes.ts → read-scopes.js} +9 -9
  169. package/src/runtime/inventory/{siblings.ts → siblings.js} +15 -15
  170. package/src/runtime/knowledge/{chunker.ts → chunker.js} +12 -12
  171. package/src/runtime/knowledge/{hybrid.ts → hybrid.js} +17 -17
  172. package/src/runtime/knowledge/{index-store.ts → index-store.js} +23 -23
  173. package/src/runtime/knowledge/{retrieval.ts → retrieval.js} +27 -27
  174. package/src/runtime/{leak-scan.ts → leak-scan.js} +12 -12
  175. package/src/runtime/lifecycle/{cli.ts → cli.js} +32 -32
  176. package/src/runtime/lifecycle/{event-store.ts → event-store.js} +48 -48
  177. package/src/runtime/lifecycle/{fold.ts → fold.js} +41 -41
  178. package/src/runtime/lifecycle/{followup.ts → followup.js} +54 -54
  179. package/src/runtime/lifecycle/{goal.ts → goal.js} +50 -50
  180. package/src/runtime/lifecycle/{intent-writer.ts → intent-writer.js} +5 -5
  181. package/src/runtime/lifecycle/{overview.ts → overview.js} +47 -47
  182. package/src/runtime/lifecycle/{release.ts → release.js} +29 -29
  183. package/src/runtime/lifecycle/{report-store.ts → report-store.js} +25 -25
  184. package/src/runtime/lifecycle/{retention.ts → retention.js} +37 -37
  185. package/src/runtime/lifecycle/{root.ts → root.js} +9 -9
  186. package/src/runtime/lifecycle/{status.ts → status.js} +64 -64
  187. package/src/runtime/lifecycle/{store-upkeep.ts → store-upkeep.js} +46 -46
  188. package/src/runtime/{locator-resolve.ts → locator-resolve.js} +7 -7
  189. package/src/runtime/{mask.ts → mask.js} +22 -22
  190. package/src/runtime/{mcp-consultations.ts → mcp-consultations.js} +54 -54
  191. package/src/runtime/{mcp-reach.ts → mcp-reach.js} +24 -24
  192. package/src/runtime/{model-router.ts → model-router.js} +20 -20
  193. package/src/runtime/{outcome.ts → outcome.js} +27 -27
  194. package/src/runtime/{reach.ts → reach.js} +21 -21
  195. package/src/runtime/{readiness-record.ts → readiness-record.js} +12 -12
  196. package/src/runtime/{readiness.ts → readiness.js} +113 -43
  197. package/src/runtime/{recovery.ts → recovery.js} +15 -15
  198. package/src/runtime/{research-request.ts → research-request.js} +34 -34
  199. package/src/runtime/{retrieval-plan.ts → retrieval-plan.js} +453 -104
  200. package/src/runtime/retrieval-record.js +223 -0
  201. package/src/runtime/scaffold/{artifacts.ts → artifacts.js} +22 -19
  202. package/src/runtime/scaffold/{fingerprint.ts → fingerprint.js} +3 -3
  203. package/src/runtime/scaffold/{generate.ts → generate.js} +109 -109
  204. package/src/runtime/scaffold/{languages.ts → languages.js} +34 -34
  205. package/src/runtime/source-version.js +289 -0
  206. package/src/runtime/storage/{cli.ts → cli.js} +9 -9
  207. package/src/runtime/storage/{engine.ts → engine.js} +37 -37
  208. package/src/runtime/storage/{registry.ts → registry.js} +19 -19
  209. package/src/runtime/storage/{roots.ts → roots.js} +8 -8
  210. package/src/runtime/storage/{rules.ts → rules.js} +26 -26
  211. package/src/runtime/storage/{upkeep.ts → upkeep.js} +35 -35
  212. package/src/runtime/storage/{work-status.ts → work-status.js} +39 -39
  213. package/src/runtime/{task-attempts.ts → task-attempts.js} +62 -62
  214. package/src/runtime/{task-classifier.ts → task-classifier.js} +34 -34
  215. package/src/runtime/{task-scope.ts → task-scope.js} +40 -15
  216. package/src/runtime/{task-state.ts → task-state.js} +86 -21
  217. package/src/runtime/trace/{indicators.ts → indicators.js} +22 -22
  218. package/src/runtime/trace/{ledger.ts → ledger.js} +42 -42
  219. package/src/runtime/trace/{render.ts → render.js} +7 -7
  220. package/src/runtime/trace/{views.ts → views.js} +40 -40
  221. package/src/runtime/verification/{contract-runner.ts → contract-runner.js} +23 -23
  222. package/src/runtime/verification/{engine.ts → engine.js} +143 -143
  223. package/src/runtime/verification/{registry.ts → registry.js} +6 -6
  224. package/src/runtime/verification/{scope-bound.ts → scope-bound.js} +50 -50
  225. package/src/runtime/verification/{test-selection.ts → test-selection.js} +28 -28
  226. package/src/runtime/{workflow-engine.ts → workflow-engine.js} +50 -50
  227. package/src/runtime/{workflow-orchestrator.ts → workflow-orchestrator.js} +91 -91
  228. package/src/runtime/{worktree.ts → worktree.js} +31 -31
  229. package/src/state/{index.ts → index.js} +26 -26
  230. package/src/state/{lockfile.ts → lockfile.js} +20 -20
  231. package/src/state/{run-lock.ts → run-lock.js} +44 -44
  232. package/core/.antigravity-plugin/hooks.json +0 -39
  233. package/core/harnesses/shared/hooks/adapters/arg-fields.js +0 -19
  234. package/core/harnesses/shared/hooks/adapters/gemini.js +0 -114
  235. package/core/harnesses/shared/hooks/hooks.json +0 -47
  236. package/src/runtime/context-pack.ts +0 -492
@@ -23,52 +23,54 @@ const os = require('node:os');
23
23
  const path = require('node:path');
24
24
  const {
25
25
  handleCapabilitiesCommand, handleReadinessCommand, handleEvidenceCommand,
26
- } = require('../runtime/cli.ts');
27
- // `doctor` comes from the health module rather than src/runtime/cli.ts: the health-probe report
26
+ } = require('../runtime/cli.js');
27
+ const { loadRegistry } = require('../registry/index.js');
28
+ const { enforcementFor, UnknownEnforcementTarget } = require('../lifecycle/coverage.js');
29
+ // `doctor` comes from the health module rather than src/runtime/cli.js: the health-probe report
28
30
  // (FR-013) supersedes the presence-check version, and one verb must have one implementation.
29
- const { handleDoctorCommand } = require('../runtime/health.ts');
30
- const { handleTraceCommand, handleStatsCommand, handleDiscoverCommand, resolveRunsLocation } = require('../runtime/trace/ledger.ts');
31
- const { handleIndicatorsCommand } = require('../runtime/trace/indicators.ts');
31
+ const { handleDoctorCommand } = require('../runtime/health.js');
32
+ const { handleTraceCommand, handleStatsCommand, handleDiscoverCommand, resolveRunsLocation } = require('../runtime/trace/ledger.js');
33
+ const { handleIndicatorsCommand } = require('../runtime/trace/indicators.js');
32
34
  // The rest of the verb surface design §4.2 declares. `classify`, `workflow`, `route`, `claim`,
33
35
  // `context-pack`, `verify`, `recover` and `scaffold` each have exactly one implementation, in the
34
36
  // engine module named on the right; this file only dispatches to them.
35
- const { ReadinessEngine } = require('../runtime/readiness.ts');
36
- const { handleClaimCommand } = require('../runtime/claims.ts');
37
- const { handleClassifyCommand } = require('../runtime/task-classifier.ts');
38
- const { handleWorkflowCommand } = require('../runtime/workflow-engine.ts');
39
- const { handleOrchestrateCommand } = require('../runtime/workflow-orchestrator.ts');
40
- const { handleResearchRequestCommand } = require('../runtime/research-request.ts');
41
- const { handleTaskAttemptCommand } = require('../runtime/task-attempts.ts');
42
- const { handleRetrieveCommand } = require('../runtime/knowledge/retrieval.ts');
43
- const { handleModelRoleCommand } = require('../runtime/model-router.ts');
44
- const { handleRouteCommand } = require('../runtime/capability-router.ts');
45
- const { handleContextPackCommand } = require('../runtime/context-pack.ts');
46
- const { handleRetrievalPlanCommand } = require('../runtime/retrieval-plan.ts');
47
- const { handleOutcomeCommand } = require('../runtime/outcome.ts');
48
- const { handleVerifyCommand } = require('../runtime/verification/engine.ts');
49
- const { handleLeakScanCommand } = require('../runtime/leak-scan.ts');
50
- const { handleRecoverCommand } = require('../runtime/recovery.ts');
51
- const { handleScaffoldCommand } = require('../runtime/scaffold/generate.ts');
52
- const { handleDecisionCommand } = require('../runtime/decision-register.ts');
53
- const { handleFollowupCommand, handleLifecycleCommand, handleGoalCommand } = require('../runtime/lifecycle/cli.ts');
54
- const { projectRoot: lifecycleProjectRoot } = require('../runtime/lifecycle/root.ts');
55
- const { upkeepAfterVerb } = require('../runtime/storage/upkeep.ts');
56
- const { handleStorageCommand } = require('../runtime/storage/cli.ts');
37
+ const { ReadinessEngine } = require('../runtime/readiness.js');
38
+ const { handleClaimCommand } = require('../runtime/claims.js');
39
+ const { handleClassifyCommand } = require('../runtime/task-classifier.js');
40
+ const { handleWorkflowCommand } = require('../runtime/workflow-engine.js');
41
+ const { handleOrchestrateCommand } = require('../runtime/workflow-orchestrator.js');
42
+ const { handleResearchRequestCommand } = require('../runtime/research-request.js');
43
+ const { handleTaskAttemptCommand } = require('../runtime/task-attempts.js');
44
+ const { handleRetrieveCommand } = require('../runtime/knowledge/retrieval.js');
45
+ const { handleModelRoleCommand } = require('../runtime/model-router.js');
46
+ const { handleRouteCommand } = require('../runtime/capability-router.js');
47
+ const { handleContextPackCommand } = require('../runtime/context-pack.js');
48
+ const { handleRetrievalPlanCommand } = require('../runtime/retrieval-plan.js');
49
+ const { handleOutcomeCommand } = require('../runtime/outcome.js');
50
+ const { handleVerifyCommand } = require('../runtime/verification/engine.js');
51
+ const { handleLeakScanCommand } = require('../runtime/leak-scan.js');
52
+ const { handleRecoverCommand } = require('../runtime/recovery.js');
53
+ const { handleScaffoldCommand } = require('../runtime/scaffold/generate.js');
54
+ const { handleDecisionCommand } = require('../runtime/decision-register.js');
55
+ const { handleFollowupCommand, handleLifecycleCommand, handleGoalCommand } = require('../runtime/lifecycle/cli.js');
56
+ const { projectRoot: lifecycleProjectRoot } = require('../runtime/lifecycle/root.js');
57
+ const { upkeepAfterVerb } = require('../runtime/storage/upkeep.js');
58
+ const { handleStorageCommand } = require('../runtime/storage/cli.js');
57
59
  // Required on first use, so a CLI whose failure modules cannot be loaded still runs every other verb.
58
- function handleFailureCommand(options: any): any { return require('../runtime/failure/cli.ts').handleFailureCommand(options); }
59
- const { handleInventoryCommand } = require('../runtime/inventory/index.ts');
60
- const { finishRuntime, usageError } = require('../runtime/cli-result.ts');
61
- const { setDefaultSlug, invalidSlugRefusal, slugNamesNoFeature } = require('../runtime/task-scope.ts');
62
- const { listCheckouts } = require('../runtime/checkouts.ts');
63
- const { featureSlugFor } = require('../runtime/implementation-gate.ts');
64
- const { handleBriefToolsCommand } = require('../runtime/brief-tools.ts');
65
- const { handleAdviseCommand } = require('../runtime/advice/cli.ts');
66
- const { REPO_ROOT, buildAdapterRegistry } = require('./shared.ts');
60
+ function handleFailureCommand(options ) { return require('../runtime/failure/cli.js').handleFailureCommand(options); }
61
+ const { handleInventoryCommand } = require('../runtime/inventory/index.js');
62
+ const { finishRuntime, usageError } = require('../runtime/cli-result.js');
63
+ const { setDefaultSlug, invalidSlugRefusal, slugNamesNoFeature, resolveFeature } = require('../runtime/task-scope.js');
64
+ const { listCheckouts } = require('../runtime/checkouts.js');
65
+ const { featureSlugFor } = require('../runtime/implementation-gate.js');
66
+ const { handleBriefToolsCommand } = require('../runtime/brief-tools.js');
67
+ const { handleAdviseCommand } = require('../runtime/advice/cli.js');
68
+ const { REPO_ROOT, buildAdapterRegistry } = require('./shared.js');
67
69
 
68
70
  /** Where `readiness`/`evidence` read and write per-task state. Mirrors scopeOf()'s rules so these
69
71
  * commands are scope-aware like the rest of the CLI, rather than defaulting to the DoFlow install
70
72
  * directory — which for an npm install is inside node_modules/. */
71
- function evidenceRoot(o: any): string {
73
+ function evidenceRoot(o ) {
72
74
  return o.global ? os.homedir() : path.resolve(o.positional[0] || '.');
73
75
  }
74
76
 
@@ -81,7 +83,7 @@ function evidenceRoot(o: any): string {
81
83
  * The valid set comes from the readiness registry rather than a list written here, so it cannot
82
84
  * drift from the templates that actually exist.
83
85
  */
84
- function requireTaskClass(o: any): string {
86
+ function requireTaskClass(o ) {
85
87
  if (typeof o.taskClass === 'string' && o.taskClass.trim() !== '') return o.taskClass;
86
88
  let valid = '';
87
89
  try {
@@ -92,7 +94,7 @@ function requireTaskClass(o: any): string {
92
94
  }
93
95
 
94
96
  /** The task id the caller named, or exit 2. Same reasoning as requireTaskClass. */
95
- function requireTaskId(o: any): string {
97
+ function requireTaskId(o ) {
96
98
  if (typeof o.taskId === 'string' && o.taskId.trim() !== '') return o.taskId;
97
99
  usageError(o.cmd, '--task-id is required — evidence and claims belong to one task, so guessing an id would report on a different one.', o.json);
98
100
  process.exit(2);
@@ -104,13 +106,16 @@ function requireTaskId(o: any): string {
104
106
  * Absent flags stay absent. Filling a gap here with 'unknown'/'general' would move the omission out
105
107
  * of the caller's error message and into the stored record, where it reads as a measurement.
106
108
  */
107
- function evidenceItemFromFlags(o: any): any {
108
- const item: any = {};
109
+ function evidenceItemFromFlags(o ) {
110
+ const item = {};
109
111
  if (o.kind !== undefined) item.kind = o.kind;
110
112
  if (o.provenance !== undefined) item.provenance = o.provenance;
111
113
  if (o.locator !== undefined) item.locator = o.locator;
112
114
  if (o.content !== undefined) item.content = o.content;
113
115
  if (o.establishes !== undefined) item.establishes = o.establishes;
116
+ if (o.need !== undefined) item.need = o.need;
117
+ if (o.result !== undefined) item.result = o.result;
118
+ if (o.absence !== undefined) item.absence = o.absence;
114
119
  // Both halves of an observation travel together; a lone half must reach the write boundary as
115
120
  // the partial object it is, so the refusal names the missing field instead of dropping the pair.
116
121
  if (o.observedCommand !== undefined || o.observedExit !== undefined) {
@@ -118,7 +123,7 @@ function evidenceItemFromFlags(o: any): any {
118
123
  if (o.observedCommand !== undefined) item.observation.command = o.observedCommand;
119
124
  if (o.observedExit !== undefined) item.observation.exitCode = o.observedExit;
120
125
  }
121
- const source: any = {};
126
+ const source = {};
122
127
  if (o.provider !== undefined) source.provider = o.provider;
123
128
  if (o.capability !== undefined) source.capability = o.capability;
124
129
  if (Object.keys(source).length > 0) item.source = source;
@@ -128,9 +133,9 @@ function evidenceItemFromFlags(o: any): any {
128
133
  /** Verbs that read or write per-task records, and so accept `--slug` (IC-002). */
129
134
  const TASK_STORE_VERBS = new Set(['evidence', 'claim', 'readiness', 'context-pack', 'research-request', 'outcome', 'retrieval-plan']);
130
135
 
131
- /** Verbs that build a task's readiness: run from a linked worktree whose feature folder lives only
132
- * in the main checkout, they keep the task's records there, beside the folder their evidence names. */
133
- const FEATURE_STORE_VERBS = new Set(['evidence', 'claim', 'readiness']);
136
+ /** Verbs whose task records live beside the feature folder when run from a linked worktree that
137
+ * does not contain it. */
138
+ const FEATURE_STORE_VERBS = new Set(['evidence', 'claim', 'readiness', 'retrieval-plan']);
134
139
 
135
140
  /**
136
141
  * The main checkout, when `o` runs one of FEATURE_STORE_VERBS in a linked worktree that lacks the
@@ -139,12 +144,17 @@ const FEATURE_STORE_VERBS = new Set(['evidence', 'claim', 'readiness']);
139
144
  * the readiness record written there is the one verify, orchestrate and the edit hook read from
140
145
  * the worktree.
141
146
  */
142
- function featureStoreRoot(o: any): { root: string; slug: string } | null {
147
+ function featureStoreRoot(o , checkouts ) {
143
148
  if (!FEATURE_STORE_VERBS.has(o.cmd) || o.global) return null;
144
- const checkouts = listCheckouts({ cwd: evidenceRoot(o) });
145
149
  if (!checkouts.isLinked) return null;
146
- const slug = featureSlugFor({ projectRoot: checkouts.current, slug: o.slug });
147
- const folder = (root: string) => path.join(root, 'agent-docs', 'doflow', slug || '');
150
+ let slug = o.slug || null;
151
+ if (!slug) {
152
+ try {
153
+ const feature = resolveFeature({ projectRoot: checkouts.current });
154
+ slug = !feature.error && feature.paths ? feature.paths.feature_slug : null;
155
+ } catch { /* a failed branch lookup cannot route state to a guessed feature */ }
156
+ }
157
+ const folder = (root ) => path.join(root, 'agent-docs', 'doflow', slug || '');
148
158
  if (!slug || fs.existsSync(folder(checkouts.current)) || !fs.existsSync(folder(checkouts.main))) return null;
149
159
  return { root: checkouts.main, slug };
150
160
  }
@@ -155,7 +165,7 @@ function featureStoreRoot(o: any): { root: string; slug: string } | null {
155
165
  * validate parsed CLI arguments, which is the CLI's job, not a library's); everything else belongs
156
166
  * to the engine module each case names.
157
167
  */
158
- function dispatchRuntimeCommandInner(o: any, moment: any): any {
168
+ function dispatchRuntimeCommandInner(o , moment ) {
159
169
  // A slug becomes a directory name and a state key, so one that could name a path is refused
160
170
  // here, once, for every verb that reads `--slug`, before any of them reads or writes state
161
171
  // (FR-013, IC-009). A well-formed slug that names no feature is the verbs' own business.
@@ -169,8 +179,11 @@ function dispatchRuntimeCommandInner(o: any, moment: any): any {
169
179
  // here so the verbs whose handlers build their own ledger (readiness, evidence) route the same
170
180
  // way as the ones that take `slug` directly. The orchestration journal is keyed by slug already.
171
181
  // Reset on every dispatch, so one invocation's slug can never carry into the next in-process call.
172
- const featureStore = featureStoreRoot(o);
182
+ const checkouts = FEATURE_STORE_VERBS.has(o.cmd) && !o.global
183
+ ? listCheckouts({ cwd: evidenceRoot(o) }) : null;
184
+ const featureStore = featureStoreRoot(o, checkouts);
173
185
  const storeRoot = featureStore ? featureStore.root : evidenceRoot(o);
186
+ const attemptRoot = checkouts?.ok && !checkouts.sandbox ? (checkouts.main || checkouts.current || null) : null;
174
187
  // Use the same root resolver as the handler: task redirection, the nearest run ledger,
175
188
  // and lifecycle's shared main-worktree store are deliberately different scopes.
176
189
  try {
@@ -197,6 +210,7 @@ function dispatchRuntimeCommandInner(o: any, moment: any): any {
197
210
  // REPO_ROOT locates the capability registry; projectRoot is the tree whose index freshness
198
211
  // and build/test commands are being reported on, which follows the usual scope rules.
199
212
  case 'capabilities': return handleCapabilitiesCommand({ json: o.json, check: o.check, repoRoot: REPO_ROOT });
213
+ case 'enforcement': return handleEnforcementCommand(o);
200
214
  case 'doctor': return handleDoctorCommand({ json: o.json, repoRoot: REPO_ROOT, projectRoot: evidenceRoot(o), adapters: buildAdapterRegistry() });
201
215
  // REPO_ROOT locates the registry (templates ship with the package); stateRoot locates the
202
216
  // caller's evidence, which follows the same scope rules as every other command: -g means
@@ -211,8 +225,8 @@ function dispatchRuntimeCommandInner(o: any, moment: any): any {
211
225
  // than from evidence, so the gate had one reachable answer for every task. Forwarding is
212
226
  // all this does: the handler names them back under `callerAsserted` so a stated input is
213
227
  // never mistaken for a measured one.
214
- case 'readiness': return handleReadinessCommand({ taskClass: requireTaskClass(o), taskId: requireTaskId(o), verificationPlan: o.verificationPlan, scopeClear: o.scope, invariants: o.invariants, userDecisionPending: o.userDecisionPending, mode: o.mode, slug: storeSlug, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot });
215
- case 'evidence': return handleEvidenceCommand({ taskId: requireTaskId(o), action: o.action, item: evidenceItemFromFlags(o), batchPath: o.batchPath, evidenceId: o.evidenceId, replacedBy: o.replacedBy, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot });
228
+ case 'readiness': return handleReadinessCommand({ taskClass: requireTaskClass(o), taskId: requireTaskId(o), verificationPlan: o.verificationPlan, scopeClear: o.scope, invariants: o.invariants, userDecisionPending: o.userDecisionPending, mode: o.mode, slug: storeSlug, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot, sourceRoot: evidenceRoot(o) });
229
+ case 'evidence': return handleEvidenceCommand({ taskId: requireTaskId(o), action: o.action, item: evidenceItemFromFlags(o), batchPath: o.batchPath, evidenceId: o.evidenceId, replacedBy: o.replacedBy, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot, slug: storeSlug, sourceRoot: evidenceRoot(o), attemptRoot });
216
230
  // Run-ledger views. They resolve their own ledger the way the dispatcher does (nearest
217
231
  // `.doflow` walking up, or the global one) rather than assuming cwd is the project root, so
218
232
  // a view invoked from a subdirectory reads the runs that were actually recorded.
@@ -253,15 +267,15 @@ function dispatchRuntimeCommandInner(o: any, moment: any): any {
253
267
  case 'research-request': return handleResearchRequestCommand({ slug: o.slug, action: o.action === 'status' ? 'list' : o.action, taskId: requireTaskId(o), stageId: o.stageId, question: o.question, reason: o.reason, blocking: o.blocking === undefined ? undefined : o.blocking === 'true' ? true : o.blocking === 'false' ? false : o.blocking, requestId: o.requestId, outcome: o.researchOutcome, claimId: o.claimId, evidenceIds: o.evidenceIds, gap: o.gap, json: o.json, projectRoot: evidenceRoot(o) });
254
268
  // The store is shared by every linked worktree of the clone (lifecycle's main-worktree root); the
255
269
  // feature is `--slug`, else the branch's, resolved the way decision and scaffold resolve it.
256
- case 'task-attempt': return handleTaskAttemptCommand({ action: o.actionGiven ? o.action : undefined, slug: o.slug, task: o.task, owner: o.owner, mode: o.mode, token: o.token, result: o.result, evidenceId: o.evidenceId, reason: o.reason, json: o.json, cwd: evidenceRoot(o), resolveSlug: (cwd: string) => featureSlugFor({ projectRoot: cwd }) });
270
+ case 'task-attempt': return handleTaskAttemptCommand({ action: o.actionGiven ? o.action : undefined, slug: o.slug, task: o.task, owner: o.owner, mode: o.mode, token: o.token, result: o.result, evidenceId: o.evidenceId, reason: o.reason, json: o.json, cwd: evidenceRoot(o), resolveSlug: (cwd ) => featureSlugFor({ projectRoot: cwd }) });
257
271
  case 'retrieve': return handleRetrieveCommand({ query: o.query, top: o.top, json: o.json });
258
272
  case 'brief-tools': return handleBriefToolsCommand({ owner: o.owner, tier: o.tier, harness: o.harness, slug: o.slug, headingLevel: o.headingLevel, tasks: o.tasks, json: o.json, repoRoot: REPO_ROOT, projectRoot: storeRoot, buildAdapters: buildAdapterRegistry });
259
273
  case 'advise': return handleAdviseCommand({ action: o.action, actionGiven: o.actionGiven, kind: o.kind, server: o.server, state: o.state, stateFile: o.stateFile, staticAnswer: o.staticAnswer, questionsFile: o.questionsFile, taskId: o.taskId, pickId: o.pickId, actual: o.actual, model: o.model, endpoint: o.endpoint, off: o.off, project: o.project, force: o.force, global: o.global, json: o.json, projectRoot: evidenceRoot(o) });
260
274
  case 'model-role': return handleModelRoleCommand({ role: o.role, exclude: o.exclude, json: o.json, repoRoot: REPO_ROOT });
261
275
  case 'route': return handleRouteCommand({ intent: o.intent, query: o.query, check: o.check, json: o.json, projectRoot: evidenceRoot(o) });
262
276
  case 'claim': return handleClaimCommand({ slug: storeSlug, taskId: requireTaskId(o), action: o.action, statement: o.statement, claimId: o.claimId, evidenceId: o.evidenceId, replacedBy: o.replacedBy, relation: o.relation, role: o.role, json: o.json, stateRoot: storeRoot });
263
- case 'context-pack': return handleContextPackCommand({ taskId: requireTaskId(o), taskClass: o.taskClass, objective: o.objective, json: o.json, stateRoot: evidenceRoot(o), slug: o.slug });
264
- case 'retrieval-plan': return handleRetrievalPlanCommand({ slug: o.slug, taskId: requireTaskId(o), action: o.action, need: o.need, stage: o.stage, json: o.json, repoRoot: REPO_ROOT, stateRoot: evidenceRoot(o) });
277
+ case 'context-pack': return handleContextPackCommand({ taskId: requireTaskId(o), taskClass: o.taskClass, objective: o.objective, json: o.json, stateRoot: evidenceRoot(o), slug: o.slug, mandatoryFile: o.mandatoryFile, harness: o.harness, maxBytes: o.maxBytes, bare: o.bare, noRecord: o.noRecord, reason: o.reason, since: o.since, expand: o.expand });
278
+ case 'retrieval-plan': return handleRetrievalPlanCommand({ slug: storeSlug, taskId: requireTaskId(o), action: o.action, need: o.need, stage: o.stage, provider: o.provider, attemptStatus: o.attemptStatus, reason: o.reason, note: o.note, json: o.json, repoRoot: REPO_ROOT, stateRoot: storeRoot, sourceRoot: evidenceRoot(o) });
265
279
  case 'outcome': return handleOutcomeCommand({ slug: o.slug, taskId: requireTaskId(o), action: o.action, state: o.state, taskClass: o.taskClass, stage: o.stage, readiness: o.readiness, verification: o.verification, json: o.json, repoRoot: REPO_ROOT, stateRoot: evidenceRoot(o) });
266
280
  case 'verify': return handleVerifyCommand({ slug: o.slug, taskId: requireTaskId(o), action: o.action, risk: o.risk, planPath: o.planPath, scope: o.scope, verificationInput: o.verificationInput, verificationPhase: o.verificationPhase, baselineRef: o.baselineRef, json: o.json, projectRoot: evidenceRoot(o) });
267
281
  case 'leak-scan': return handleLeakScanCommand({ paths: o.paths, exclude: o.exclude, json: o.json, repoRoot: evidenceRoot(o) });
@@ -271,11 +285,36 @@ function dispatchRuntimeCommandInner(o: any, moment: any): any {
271
285
  }
272
286
 
273
287
  /** Await the verb without changing its return value, output or exit code; usage exits never return. */
274
- async function dispatchRuntimeCommand(o: any): Promise<any> {
275
- const moment: any = {};
288
+ async function dispatchRuntimeCommand(o ) {
289
+ const moment = {};
276
290
  const result = await dispatchRuntimeCommandInner(o, moment);
277
291
  if (o.cmd !== 'storage') upkeepAfterVerb({ projectRoot: moment.projectRoot });
278
292
  return result;
279
293
  }
280
294
 
295
+ function handleEnforcementCommand(o ) {
296
+ const fail = (error , detail ) => {
297
+ if (o.json) console.log(JSON.stringify({ error, detail }));
298
+ else console.error(`doflow enforcement: ${detail}`);
299
+ process.exitCode = 2;
300
+ return 2;
301
+ };
302
+ if (typeof o.harness !== 'string' || !o.harness || typeof o.policy !== 'string' || !o.policy || (o.profile !== undefined && typeof o.profile !== 'string')) return fail('usage', 'requires --harness <id> --policy <id> [--profile <id>]');
303
+ try {
304
+ const registry = loadRegistry({ repoRoot: REPO_ROOT });
305
+ const answer = enforcementFor(registry.coverage, { harness: o.harness, policy: o.policy, ...(o.profile ? { profile: o.profile } : {}) });
306
+ if (o.json) console.log(JSON.stringify(answer));
307
+ else {
308
+ console.log(`${answer.harness} ${answer.policy}: ${answer.enforced ? 'enforced' : 'not enforced'} (${answer.class}, ${answer.verification})`);
309
+ for (const item of answer.doesNotCover) console.log(`does not cover: ${item}`);
310
+ for (const item of answer.prerequisites) console.log(`prerequisite: ${item}`);
311
+ }
312
+ process.exitCode = answer.enforced ? 0 : 1;
313
+ return process.exitCode;
314
+ } catch (error ) {
315
+ if (error instanceof UnknownEnforcementTarget) return fail(error.code, error.message);
316
+ return fail('usage', error.message);
317
+ }
318
+ }
319
+
281
320
  module.exports = { dispatchRuntimeCommand };
@@ -9,23 +9,23 @@
9
9
  const fs = require('node:fs');
10
10
  const os = require('node:os');
11
11
  const path = require('node:path');
12
- const { REPO_ROOT } = require('../helper/repo-root.ts');
13
- const { doflowPaths } = require('../install/paths.ts');
14
- const { readInstallManifest } = require('../install/manifest.ts');
15
- const { DEFAULT_BACKUP_RETENTION, formatBytes } = require('../install/backup.ts');
16
- const { stateRoot, readLedger } = require('../state/index.ts');
17
- const { readLock } = require('../state/lockfile.ts');
18
- const { acquireRunLock, RunLockTimeoutError, RunLockError, RunLockLostError } = require('../state/run-lock.ts');
19
- const { createAdapterRegistry } = require('../adapters/index.ts');
20
- const { declaredHarnessPaths } = require('../helper/harness-paths.ts');
21
- const claudeAdapter = require('../adapters/claude/index.ts');
22
- const codexAdapter = require('../adapters/codex/index.ts');
23
- const { createGeminiAdapter } = require('../adapters/gemini/index.ts');
24
- const { createOpenCodeAdapter } = require('../adapters/opencode/index.ts');
25
- const { createPiAdapter } = require('../adapters/pi/index.ts');
26
- const { createCopilotAdapter } = require('../adapters/copilot/index.ts');
27
- const { createKiroAdapter } = require('../adapters/kiro/index.ts');
28
- const { createAntigravityAdapter } = require('../adapters/antigravity/index.ts');
12
+ const { REPO_ROOT } = require('../helper/repo-root.js');
13
+ const { doflowPaths } = require('../install/paths.js');
14
+ const { readInstallManifest } = require('../install/manifest.js');
15
+ const { DEFAULT_BACKUP_RETENTION, formatBytes } = require('../install/backup.js');
16
+ const { stateRoot, readLedger } = require('../state/index.js');
17
+ const { readLock } = require('../state/lockfile.js');
18
+ const { acquireRunLock, RunLockTimeoutError, RunLockError, RunLockLostError } = require('../state/run-lock.js');
19
+ const { createAdapterRegistry } = require('../adapters/index.js');
20
+ const { declaredHarnessPaths } = require('../helper/harness-paths.js');
21
+ const claudeAdapter = require('../adapters/claude/index.js');
22
+ const codexAdapter = require('../adapters/codex/index.js');
23
+ const { createGeminiAdapter } = require('../adapters/gemini/index.js');
24
+ const { createOpenCodeAdapter } = require('../adapters/opencode/index.js');
25
+ const { createPiAdapter } = require('../adapters/pi/index.js');
26
+ const { createCopilotAdapter } = require('../adapters/copilot/index.js');
27
+ const { createKiroAdapter } = require('../adapters/kiro/index.js');
28
+ const { createAntigravityAdapter } = require('../adapters/antigravity/index.js');
29
29
 
30
30
  // The directory of the `doflow` entrypoint. Derived from the shared package root rather than
31
31
  // __dirname so its value survives this code physically moving between directories: manifests,
@@ -36,7 +36,7 @@ const SCRIPT_DIR = path.join(REPO_ROOT, 'bin');
36
36
  // core/registry/ but no package.json — see the `runtime.*` assets in core/registry/assets.json.
37
37
  // A hard require here would make every Node-backed verb fail in an install, which is the exact
38
38
  // defect that projection exists to fix. Only version reporting depends on this.
39
- function loadPkg(): any {
39
+ function loadPkg() {
40
40
  try { return require('../../package.json'); } catch { return { version: '0.0.0-installed', name: '@khoavu882/doflow' }; }
41
41
  }
42
42
  const pkg = loadPkg();
@@ -44,13 +44,13 @@ const pkg = loadPkg();
44
44
  /**
45
45
  * The one adapter registry construction, used by install/update/remove/reconcile. There used to
46
46
  * be three inline copies of the same construction (one per mutating command); a fourth variant
47
- * once grew in src/lifecycle/view.ts and silently fell behind (fixed in 96006da) — which is why
47
+ * once grew in src/lifecycle/view.js and silently fell behind (fixed in 96006da) — which is why
48
48
  * the registry guard pins every declared harness into each call site by parsing them.
49
49
  * Build one here rather than copying the object literal again. Stage 3: each adapter factory
50
50
  * receives its harness's declared native paths from core/registry/harnesses.json, so the CLI
51
51
  * consumes exactly what the loader validates.
52
52
  */
53
- function buildAdapterRegistry(): any {
53
+ function buildAdapterRegistry() {
54
54
  const declared = declaredHarnessPaths();
55
55
  return createAdapterRegistry({
56
56
  claude: claudeAdapter.createClaudeAdapter({ declaredPaths: declared.claude }),
@@ -65,11 +65,11 @@ function buildAdapterRegistry(): any {
65
65
  }
66
66
 
67
67
  /** Resolve {global, projectRoot} scope options for src/install/targets.js#toolDirs from parsed args. */
68
- function scopeOf(o: any): { global: boolean; projectRoot: string } {
68
+ function scopeOf(o ) {
69
69
  return { global: o.global, projectRoot: o.positional[0] || '.' };
70
70
  }
71
71
 
72
- function installPaths(scope: any): any {
72
+ function installPaths(scope ) {
73
73
  const scopeRoot = scope.global ? os.homedir() : path.resolve(scope.projectRoot);
74
74
  return doflowPaths({ scopeRoot });
75
75
  }
@@ -77,7 +77,7 @@ function installPaths(scope: any): any {
77
77
  /** Whether two paths name the same directory. Device and inode follow symlinks (macOS reaches
78
78
  * /var through /private/var) and ignore letter case on a case-insensitive volume; a file system
79
79
  * that reports inode 0 falls back to real paths, and paths that do not exist to resolved strings. */
80
- function sameDirectory(a: string, b: string, { fsImpl = fs }: any = {}): boolean {
80
+ function sameDirectory(a , b , { fsImpl = fs } = {}) {
81
81
  const ra = path.resolve(a);
82
82
  const rb = path.resolve(b);
83
83
  try {
@@ -95,7 +95,7 @@ function sameDirectory(a: string, b: string, { fsImpl = fs }: any = {}): boolean
95
95
  /** A project install, update, remove or reconcile rooted at the home directory would share the
96
96
  * global install's files and records, and its remove could delete them. Refuses that run with one
97
97
  * line and exit 1 before anything is read, locked or written; `-g` and every other root pass. */
98
- function refuseHomeRootedProject(o: any, command: string): void {
98
+ function refuseHomeRootedProject(o , command ) {
99
99
  if (o.global) return;
100
100
  const projectRoot = o.positional[0] || '.';
101
101
  if (!sameDirectory(projectRoot, os.homedir())) return;
@@ -106,40 +106,40 @@ function refuseHomeRootedProject(o: any, command: string): void {
106
106
 
107
107
  /** Takes the scope's run lock for a mutating command, or returns null under --dry-run. A run that
108
108
  * cannot take it prints the one reason line and exits 1 before it has read or changed anything. */
109
- function holdRunLock(o: any, scope: any, command: string): any {
109
+ function holdRunLock(o , scope , command ) {
110
110
  if (o.dryRun) return null;
111
111
  try {
112
112
  return acquireRunLock({ scopeRoot: installPaths(scope).scopeRoot, scope: scope.global ? 'global' : 'project', command });
113
113
  } catch (err) {
114
114
  if (!(err instanceof RunLockTimeoutError || err instanceof RunLockError)) throw err;
115
- console.error((err as any).message);
115
+ console.error((err ).message);
116
116
  process.exit(1);
117
117
  }
118
118
  }
119
119
 
120
120
  /** After the confirm prompt: renews the hold, and exits 1 before the first write if another run
121
121
  * took the lock over while the prompt waited. */
122
- function checkpointRunLock(hold: any): void {
122
+ function checkpointRunLock(hold ) {
123
123
  if (!hold) return;
124
124
  try {
125
125
  hold.checkpoint();
126
126
  } catch (err) {
127
127
  if (!(err instanceof RunLockLostError)) throw err;
128
- console.error((err as any).message);
128
+ console.error((err ).message);
129
129
  process.exit(1);
130
130
  }
131
131
  }
132
132
 
133
133
  /** Surface a reconciled-away MCP server rather than dropping it silently: the user picked it once,
134
134
  * so its disappearance from their config should be explained, not discovered. */
135
- function reportRetiredMcp(retired: string[]): void {
135
+ function reportRetiredMcp(retired ) {
136
136
  console.error(`[WARN] Dropping MCP server(s) no longer in the registry: ${retired.join(', ')}`);
137
137
  console.error(' They were removed from DoFlow; your saved selection is being reconciled.');
138
138
  }
139
139
 
140
140
  /** The scope's doflow.lock, ledger and 1.18.0 manifest MCP list, as the MCP selection functions in
141
141
  * src/install/mcp.js read them. */
142
- function scopeSelectionState(scope: any): any {
142
+ function scopeSelectionState(scope ) {
143
143
  const scopeRoot = scope.global ? os.homedir() : path.resolve(scope.projectRoot);
144
144
  return {
145
145
  lock: readLock(scope.global ? { scope: 'global', homeDir: scopeRoot } : { scope: 'project', projectRoot: scopeRoot }),
@@ -148,13 +148,13 @@ function scopeSelectionState(scope: any): any {
148
148
  };
149
149
  }
150
150
 
151
- const MCP_SOURCE_WORDS = Object.freeze({ flag: '--mcp', prompt: 'prompt', recorded: 'recorded', kept: 'kept', manifest: 'remembered', default: 'default' } as Record<string, string>);
151
+ const MCP_SOURCE_WORDS = Object.freeze({ flag: '--mcp', prompt: 'prompt', recorded: 'recorded', kept: 'kept', manifest: 'remembered', default: 'default' } );
152
152
 
153
153
  /** The one line a run names its MCP selections in, from what the plan resolved for each harness:
154
154
  * harnesses with the same servers and source share a group, groups follow target order. Prints
155
155
  * nothing when no target takes MCP servers, except that an explicit --mcp is said to do nothing. */
156
- function printMcpSelection(view: any, sources: any, { requested, prefix = '[INFO]' }: any = {}): void {
157
- const groups: any[] = [];
156
+ function printMcpSelection(view , sources , { requested, prefix = '[INFO]' } = {}) {
157
+ const groups = [];
158
158
  for (const target of view.plan.targets) {
159
159
  if (target.skipped || !Array.isArray(target.mcpSelected) || !(target.harness in sources)) continue;
160
160
  const ids = target.mcpSelected.join(', ') || 'none';
@@ -172,26 +172,26 @@ function printMcpSelection(view: any, sources: any, { requested, prefix = '[INFO
172
172
 
173
173
  /** Says which MCP entries a run with no native change recorded as DoFlow's (lifecycle
174
174
  * recordMcpOwnership), or, under --dry-run, would record. */
175
- function printRecordedMcpOwnership(recorded: any, { dryRun = false }: any = {}): void {
176
- for (const [harness, ids] of Object.entries<any>(recorded)) {
175
+ function printRecordedMcpOwnership(recorded , { dryRun = false } = {}) {
176
+ for (const [harness, ids] of Object.entries (recorded)) {
177
177
  const what = `${ids.length} MCP ${ids.length === 1 ? 'entry' : 'entries'} (${ids.join(', ')})`;
178
178
  console.log(dryRun ? `[DRY] ${harness}: would record DoFlow's ownership of ${what}` : `[INFO] ${harness}: recorded DoFlow's ownership of ${what}`);
179
179
  }
180
180
  }
181
181
 
182
182
  /** What each planned harness that takes MCP servers will hold, as doflow.lock records it. */
183
- function plannedMcpSelections(view: any): any {
184
- return Object.fromEntries(view.plan.targets.filter((target: any) => !target.skipped && Array.isArray(target.mcpSelected))
185
- .map((target: any) => [target.harness, target.mcpSelected]));
183
+ function plannedMcpSelections(view ) {
184
+ return Object.fromEntries(view.plan.targets.filter((target ) => !target.skipped && Array.isArray(target.mcpSelected))
185
+ .map((target ) => [target.harness, target.mcpSelected]));
186
186
  }
187
187
 
188
188
  /** Total size of some rows, noting when any of them could not be measured. */
189
- function rowsSize(rows: any[]): string {
189
+ function rowsSize(rows ) {
190
190
  const total = formatBytes(rows.reduce((sum, r) => sum + (r.bytes ?? 0), 0));
191
191
  return rows.some((r) => r.bytes === null) ? `${total} (some sizes unknown)` : total;
192
192
  }
193
193
 
194
- function printBackupTable(rows: any[], rootLabel: string): void {
194
+ function printBackupTable(rows , rootLabel ) {
195
195
  if (rows.length === 0) { console.log(`[INFO] No backups found in ${rootLabel}`); return; }
196
196
  const header = `${'BACKUP ID'.padEnd(42)} ${'OPERATION'.padEnd(14)} ${'TYPE'.padEnd(9)} ${'ORIGIN'.padEnd(9)} ${'SIZE'.padEnd(11)} TIMESTAMP`;
197
197
  console.log(`\n${header}`);
@@ -2,12 +2,12 @@
2
2
 
3
3
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): authored as `.ts`, run directly by Node
4
4
  // native type-stripping — no build step, no runtime dependency. Body stays CommonJS so a `.js`
5
- // caller's `require('../helper/bash-helper.ts')` keeps working while the rest of the tree is still
5
+ // caller's `require('../helper/bash-helper.js')` keeps working while the rest of the tree is still
6
6
  // `.js`. The `./repo-root` require stays bare while repo-root is still `.js`; it gains `.ts` in the
7
7
  // same slice that converts repo-root.
8
8
  const fs = require('node:fs');
9
9
  const path = require('node:path');
10
- const { REPO_ROOT } = require('./repo-root.ts');
10
+ const { REPO_ROOT } = require('./repo-root.js');
11
11
 
12
12
  /**
13
13
  * Where a bash helper (`do-paths.sh`, `do-git-state.sh`) is: inside the package (a checkout or a
@@ -20,15 +20,15 @@ const { REPO_ROOT } = require('./repo-root.ts');
20
20
  * @param repoRoot the runtime root; only a test moves it
21
21
  */
22
22
  function resolveBashHelper(
23
- name: string,
24
- repoRoot: string = REPO_ROOT,
25
- existsImpl: (file: string) => boolean = fs.existsSync,
26
- ): string | null {
23
+ name ,
24
+ repoRoot = REPO_ROOT,
25
+ existsImpl = fs.existsSync,
26
+ ) {
27
27
  const candidates = [
28
28
  path.join(repoRoot, 'core', 'shared', 'scripts', 'doflow', 'bash', name),
29
29
  path.resolve(repoRoot, '..', 'scripts', 'doflow', 'bash', name),
30
30
  ];
31
- return candidates.find((candidate: string) => existsImpl(candidate)) || null;
31
+ return candidates.find((candidate ) => existsImpl(candidate)) || null;
32
32
  }
33
33
 
34
34
  module.exports = { resolveBashHelper };
@@ -6,13 +6,13 @@
6
6
  // First module of the TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md). Authored as `.ts` and
7
7
  // run directly by Node's native type-stripping (process.features.typescript === 'strip', Node
8
8
  // ^22.18.0 || >=24.3.0), so no build step and no runtime dependency are added. The body stays CommonJS
9
- // (`module.exports`) so a `require('../helper/git.ts')` from a `.js` caller keeps working while the
9
+ // (`module.exports`) so a `require('../helper/git.js')` from a `.js` caller keeps working while the
10
10
  // rest of the tree is still `.js`; the explicit `.ts` extension on those requires is what the
11
11
  // CommonJS resolver needs to find this file.
12
12
  const { execFileSync } = require('node:child_process');
13
13
 
14
14
  /** Short HEAD commit of the repo at `repoRoot`, or 'unknown' if not a git repo / git unavailable. */
15
- function sourceCommit(repoRoot: string): string {
15
+ function sourceCommit(repoRoot ) {
16
16
  try {
17
17
  return execFileSync('git', ['-C', repoRoot, 'rev-parse', '--short', 'HEAD'], { stdio: ['ignore', 'pipe', 'ignore'] })
18
18
  .toString().trim() || 'unknown';
@@ -11,7 +11,7 @@
11
11
  //
12
12
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): authored as `.ts`, run directly by Node
13
13
  // native type-stripping (process.features.typescript === 'strip', Node ^22.18.0 || >=24.3.0) — no build step and
14
- // no runtime dependency. The body stays CommonJS so a `.js` caller's `require('../helper/guardrails.ts')`
14
+ // no runtime dependency. The body stays CommonJS so a `.js` caller's `require('../helper/guardrails.js')`
15
15
  // keeps working while the rest of the tree is still `.js`; the explicit `.ts` extension is what the
16
16
  // CommonJS resolver needs to find this file.
17
17
 
@@ -20,26 +20,26 @@ const path = require('node:path');
20
20
 
21
21
  const DENY_RULE = /^Bash\((.*):\*\)$/;
22
22
 
23
- interface FsReadFileSync {
24
- readFileSync(file: string, encoding: 'utf8'): string;
25
- }
23
+
24
+
25
+
26
26
 
27
- interface DestructiveCommandGlobsOptions {
28
- repoRoot: string;
29
- fsImpl?: FsReadFileSync;
30
- }
27
+
28
+
29
+
30
+
31
31
 
32
32
  /** Read the canonical blocklist as bare command globs, e.g. `git push --force*`. Throws when the
33
33
  * authored file is missing or malformed — a silent empty blocklist would look like success while
34
34
  * projecting no protection at all. */
35
- function destructiveCommandGlobs({ repoRoot, fsImpl = fs }: DestructiveCommandGlobsOptions = {} as DestructiveCommandGlobsOptions): string[] {
35
+ function destructiveCommandGlobs({ repoRoot, fsImpl = fs } = {} ) {
36
36
  const file = path.join(repoRoot, 'core', 'harnesses', 'claude', 'settings', 'settings.json');
37
37
  const parsed = JSON.parse(fsImpl.readFileSync(file, 'utf8'));
38
38
  const deny = parsed?.permissions?.deny;
39
39
  if (!Array.isArray(deny) || deny.length === 0) {
40
40
  throw new Error(`guardrails: no permissions.deny list in ${file}`);
41
41
  }
42
- return deny.map((rule: string) => {
42
+ return deny.map((rule ) => {
43
43
  const m = DENY_RULE.exec(rule);
44
44
  if (!m) throw new Error(`guardrails: unrecognized deny rule '${rule}' in ${file}`);
45
45
  return m[1];