@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
@@ -7,13 +7,13 @@
7
7
  const crypto = require('node:crypto');
8
8
  const fs = require('node:fs');
9
9
  const path = require('node:path');
10
- const { mergeMarkedSection, removeMarkedSection, MARKER_START, MARKER_END } = require('../../helper/marker-merge.ts');
11
- const { selectMcpServers } = require('../../registry/index.ts');
12
- const { GLOBAL_HOOK_PREFIX, PROJECT_HOOK_PREFIX } = require('../../helper/settings-scope.ts');
13
- const { mergeSettings, settingsContains, settingsContainsAny, stripManagedSettings } = require('../../helper/settings-merge.ts');
14
- const { planTree, applyTree, removeTree, verifyTree, copyTreeAssets, copyTreeDestDir, ledgerFileResources, ledgerSiblingFingerprints, siblingReplacedNotices, resolveTransform } = require('../copy-tree.ts');
15
- const { declaredHarnessPaths, resolveHarnessPaths } = require('../../helper/harness-paths.ts');
16
- const { discoverMcp, planMcp, writeMcp, verifyMcp } = require('./mcp.ts');
10
+ const { mergeMarkedSection, removeMarkedSection, MARKER_START, MARKER_END } = require('../../helper/marker-merge.js');
11
+ const { selectMcpServers } = require('../../registry/index.js');
12
+ const { GLOBAL_HOOK_PREFIX, PROJECT_HOOK_PREFIX } = require('../../helper/settings-scope.js');
13
+ const { mergeSettings, settingsContains, settingsContainsAny, stripManagedSettings } = require('../../helper/settings-merge.js');
14
+ const { planTree, applyTree, removeTree, verifyTree, copyTreeAssets, copyTreeDestDir, ledgerFileResources, ledgerSiblingFingerprints, siblingReplacedNotices, resolveTransform } = require('../copy-tree.js');
15
+ const { declaredHarnessPaths, resolveHarnessPaths } = require('../../helper/harness-paths.js');
16
+ const { discoverMcp, planMcp, writeMcp, verifyMcp } = require('./mcp.js');
17
17
 
18
18
  const INSTRUCTION_RENDERER = 'claude-instructions';
19
19
  const SETTINGS_RENDERER = 'claude-settings';
@@ -30,11 +30,11 @@ const SETTINGS_RENDERER = 'claude-settings';
30
30
  */
31
31
  const SETTINGS_FILES = ['settings.json', 'keybindings.json'];
32
32
 
33
- function sha256(value: any) {
33
+ function sha256(value ) {
34
34
  return crypto.createHash('sha256').update(value).digest('hex');
35
35
  }
36
36
 
37
- function sourcePath(asset: any, context: any = {}) {
37
+ function sourcePath(asset , context = {}) {
38
38
  if (!asset || typeof asset.source !== 'string') throw new Error('Claude asset requires a source path');
39
39
  const repoRoot = context.repoRoot ? path.resolve(context.repoRoot) : process.cwd();
40
40
  const source = path.resolve(repoRoot, asset.source);
@@ -44,7 +44,7 @@ function sourcePath(asset: any, context: any = {}) {
44
44
  return source;
45
45
  }
46
46
 
47
- function markerState(file: any) {
47
+ function markerState(file ) {
48
48
  if (!fs.existsSync(file)) return { exists: false, managed: false, malformed: false };
49
49
  const text = fs.readFileSync(file, 'utf8');
50
50
  const starts = text.split(MARKER_START).length - 1;
@@ -53,8 +53,8 @@ function markerState(file: any) {
53
53
  }
54
54
 
55
55
  /** Single serialization form for every settings write, so repeated runs are byte-stable. */
56
- const serializeSettings = (value: any) => `${JSON.stringify(value, null, 2)}\n`;
57
- const settingsChangeExtras = (fileName: any) => ({ kind: 'settings-file', identity: fileName });
56
+ const serializeSettings = (value ) => `${JSON.stringify(value, null, 2)}\n`;
57
+ const settingsChangeExtras = (fileName ) => ({ kind: 'settings-file', identity: fileName });
58
58
 
59
59
  /**
60
60
  * Native path facts live in core/registry/harnesses.json under this harness's "paths" section and
@@ -67,18 +67,18 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
67
67
  // Parity note: Claude's historical nativePaths() resolved BOTH scopes' root from scopeRoot (the
68
68
  // CLI passes $HOME there for -g installs) and never consulted homeDir — so the resolver is fed
69
69
  // no homeDir and "root" keeps resolving exactly as before.
70
- function nativePaths({ scope, scopeRoot }: any = {}) {
70
+ function nativePaths({ scope, scopeRoot } = {}) {
71
71
  return resolveHarnessPaths(declaredPaths, { scope, scopeRoot });
72
72
  }
73
73
 
74
- function discover({ scope, scopeRoot, mcp = [], mcpAdoptable = [], ledger, registry, homeDir, context = {} }: any) {
74
+ function discover({ scope, scopeRoot, mcp = [], mcpAdoptable = [], ledger, registry, homeDir, context = {} } ) {
75
75
  const paths = nativePaths({ scope, scopeRoot });
76
76
  return {
77
77
  paths,
78
78
  instructions: markerState(paths.instructions),
79
79
  settingsExists: fs.existsSync(paths.settings),
80
80
  mcpExists: fs.existsSync(paths.mcp),
81
- knownMcpServers: registry ? selectMcpServers(registry).map((server: any) => server.id) : [],
81
+ knownMcpServers: registry ? selectMcpServers(registry).map((server ) => server.id) : [],
82
82
  ...discoverMcp({ paths, mcp, mcpAdoptable, ledger, scope, scopeRoot, homeDir: context.homeDir || homeDir || undefined }),
83
83
  };
84
84
  }
@@ -88,11 +88,11 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
88
88
  /** Every asset materialised through the copy-tree engine, whatever its declared renderer:
89
89
  * verbatim mirrors declare 'copy-tree', transformed projections (output styles) declare their
90
90
  * own name so the registry can tell the shapes apart. Routing is on `kind`, which both share. */
91
- function claudeTreeAssets(assets: any) {
92
- return [...copyTreeAssets(assets), ...(assets || []).filter((asset: any) => asset.renderer === 'claude-output-styles')];
91
+ function claudeTreeAssets(assets ) {
92
+ return [...copyTreeAssets(assets), ...(assets || []).filter((asset ) => asset.renderer === 'claude-output-styles')];
93
93
  }
94
94
 
95
- function planCopyTreeAssets({ assets, scope, scopeRoot, context, ledger, removing }: any) {
95
+ function planCopyTreeAssets({ assets, scope, scopeRoot, context, ledger, removing } ) {
96
96
  const paths = nativePaths({ scope, scopeRoot });
97
97
  const changes = [];
98
98
  const conflicts = [];
@@ -109,10 +109,10 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
109
109
  // is never deleted on removal, forced or not.
110
110
  force: !removing && context?.force === true, });
111
111
  treeResults.push(result);
112
- conflicts.push(...result.conflicts.map((reason: any) => `${asset.id}: ${reason}`));
112
+ conflicts.push(...result.conflicts.map((reason ) => `${asset.id}: ${reason}`));
113
113
  // A hand-edited file at a path DoFlow no longer writes is the user's: it stays, only its
114
114
  // ownership row is released.
115
- notices.push(...result.kept.map((item: any) => `kept hand-edited ${path.relative(paths.root, item.target)}; DoFlow no longer manages it`));
115
+ notices.push(...result.kept.map((item ) => `kept hand-edited ${path.relative(paths.root, item.target)}; DoFlow no longer manages it`));
116
116
  for (const change of result.changes) {
117
117
  changes.push({
118
118
  assetId: asset.id, target: change.target, source: change.source, operation: change.operation,
@@ -128,7 +128,7 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
128
128
  return { changes, conflicts, notices: [...siblingReplacedNotices(treeResults), ...notices] };
129
129
  }
130
130
 
131
- function applyCopyTreeAssets(changes: any) {
131
+ function applyCopyTreeAssets(changes ) {
132
132
  let applied = 0;
133
133
  const grouped = new Map();
134
134
  for (const change of changes) {
@@ -143,13 +143,13 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
143
143
  return applied;
144
144
  }
145
145
 
146
- function removeCopyTreeAssets(changes: any) {
147
- const treeChanges = changes.filter((change: any) => change.kind === 'copy-tree-file' && change.operation === 'remove' && !change.retained)
148
- .map((change: any) => ({ relPath: change.identity, target: change.target, operation: 'remove', fingerprint: change.fingerprint, pruneGuard: change.pruneGuard }));
146
+ function removeCopyTreeAssets(changes ) {
147
+ const treeChanges = changes.filter((change ) => change.kind === 'copy-tree-file' && change.operation === 'remove' && !change.retained)
148
+ .map((change ) => ({ relPath: change.identity, target: change.target, operation: 'remove', fingerprint: change.fingerprint, pruneGuard: change.pruneGuard }));
149
149
  return removeTree({ changes: treeChanges }).removed;
150
150
  }
151
151
 
152
- function verifyCopyTreeAssets({ assets, scope, scopeRoot, context }: any) {
152
+ function verifyCopyTreeAssets({ assets, scope, scopeRoot, context } ) {
153
153
  const paths = nativePaths({ scope, scopeRoot });
154
154
  const statuses = [];
155
155
  const resources = [];
@@ -158,7 +158,7 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
158
158
  const destDir = copyTreeDestDir(paths.configDir, asset);
159
159
  const sourceDir = sourcePath(asset, context);
160
160
  const result = verifyTree({ sourceDir, destDir, layout: asset.layout, transform: asset.transform, plannedWrites: context?.plannedWrites });
161
- conflicts.push(...result.conflicts.map((reason: any) => `${asset.id}: ${reason}`));
161
+ conflicts.push(...result.conflicts.map((reason ) => `${asset.id}: ${reason}`));
162
162
  for (const resource of result.resources) {
163
163
  resources.push({
164
164
  assetId: asset.id, target: resource.target, ownershipIdentity: `doflow:claude:copy-tree:${asset.id}:${resource.relPath}`,
@@ -174,16 +174,16 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
174
174
 
175
175
  // ---- claude-settings asset (settings.json + keybindings.json) ----
176
176
 
177
- function settingsAsset(assets: any) { return (assets || []).find((asset: any) => asset?.renderer === SETTINGS_RENDERER); }
178
- function settingsTarget(fileName: any, paths: any) {
177
+ function settingsAsset(assets ) { return (assets || []).find((asset ) => asset?.renderer === SETTINGS_RENDERER); }
178
+ function settingsTarget(fileName , paths ) {
179
179
  // Per-file dispatch across the two DECLARED settings surfaces (paths.settings / paths.keybindings):
180
180
  // residue because the authored file list is content-shaped, not a single declarable destination.
181
181
  return fileName === 'settings.json' ? paths.settings : paths.keybindings;
182
182
  }
183
- function settingsContent(fileName: any, raw: any, scope: any) {
183
+ function settingsContent(fileName , raw , scope ) {
184
184
  return fileName === 'settings.json' && scope !== 'global' ? raw.split(GLOBAL_HOOK_PREFIX).join(PROJECT_HOOK_PREFIX) : raw;
185
185
  }
186
- function settingsLedgerResources(ledger: any, assetId: any) {
186
+ function settingsLedgerResources(ledger , assetId ) {
187
187
  const byFile = new Map();
188
188
  for (const resource of ledger?.resources || []) {
189
189
  if (resource.harness === 'claude' && resource.assetId === assetId && resource.kind === 'settings-file') byFile.set(resource.identity, resource);
@@ -194,7 +194,7 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
194
194
 
195
195
  /** Inject (or leave untouched) the statusLine key pointing at the projected script. Refuses to
196
196
  * overwrite a user's existing custom status line unless forced: their script is theirs. */
197
- function withStatusLineKey(rawSettingsJson: any, scriptPath: any, force: any) {
197
+ function withStatusLineKey(rawSettingsJson , scriptPath , force ) {
198
198
  let parsed;
199
199
  try {
200
200
  parsed = JSON.parse(rawSettingsJson);
@@ -207,10 +207,10 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
207
207
  return serializeSettings(parsed);
208
208
  }
209
209
 
210
- function planSettingsAsset({ assets, scope, scopeRoot, context, ledger, removing }: any) {
210
+ function planSettingsAsset({ assets, scope, scopeRoot, context, ledger, removing } ) {
211
211
  const asset = settingsAsset(assets);
212
- const changes: any[] = [];
213
- const conflicts: any[] = [];
212
+ const changes = [];
213
+ const conflicts = [];
214
214
  if (!asset) return { changes, conflicts };
215
215
  const paths = nativePaths({ scope, scopeRoot });
216
216
  const sourceDir = sourcePath(asset, context);
@@ -311,7 +311,7 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
311
311
  // other copy-tree/settings write in this codebase — planSettingsAsset's own change detection is
312
312
  // fingerprint(sha256)-based, not mtime-based, so this is a consistency convention, not a
313
313
  // correctness requirement.
314
- function applySettingsAsset(changes: any) {
314
+ function applySettingsAsset(changes ) {
315
315
  let applied = 0;
316
316
  for (const change of changes) {
317
317
  if (change.projection?.renderer !== SETTINGS_RENDERER || change.operation === 'remove') continue;
@@ -328,7 +328,7 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
328
328
  // is deleted outright only when nothing but schema pointers remains — i.e. DoFlow created it.
329
329
  // Previously this rmSync'd unconditionally, which on a user-maintained settings.json would have
330
330
  // destroyed their model, permissions, env, and every foreign tool's hooks along with ours.
331
- function removeSettingsAsset(changes: any) {
331
+ function removeSettingsAsset(changes ) {
332
332
  let removed = 0;
333
333
  for (const change of changes) {
334
334
  if (change.projection?.renderer !== SETTINGS_RENDERER || change.operation !== 'remove') continue;
@@ -347,11 +347,11 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
347
347
  return removed;
348
348
  }
349
349
 
350
- function verifySettingsAsset({ assets, scope, scopeRoot, context }: any) {
350
+ function verifySettingsAsset({ assets, scope, scopeRoot, context } ) {
351
351
  const asset = settingsAsset(assets);
352
- const statuses: any[] = [];
353
- const resources: any[] = [];
354
- const conflicts: any[] = [];
352
+ const statuses = [];
353
+ const resources = [];
354
+ const conflicts = [];
355
355
  if (!asset) return { statuses, resources, conflicts };
356
356
  const paths = nativePaths({ scope, scopeRoot });
357
357
  const sourceDir = sourcePath(asset, context);
@@ -424,9 +424,9 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
424
424
 
425
425
  /** Render native Claude input without writing it.
426
426
  * `asset` is the lifecycle-projected shape (flat `renderer`/`capability` fields — see
427
- * src/adapters/index.ts#projectAdapterInput), not the raw registry asset's nested
427
+ * src/adapters/index.js#projectAdapterInput), not the raw registry asset's nested
428
428
  * `asset.projection.claude`. Every adapter method below shares that same expectation. */
429
- function render({ asset, scope, scopeRoot, context = {} }: any) {
429
+ function render({ asset, scope, scopeRoot, context = {} } ) {
430
430
  const paths = nativePaths({ scope, scopeRoot });
431
431
  if (asset?.renderer === INSTRUCTION_RENDERER) {
432
432
  const source = sourcePath(asset, context);
@@ -444,7 +444,7 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
444
444
  return { type: 'unsupported', assetId: asset?.id, renderer: asset?.renderer ?? null };
445
445
  }
446
446
 
447
- function plan({ assets, scope, scopeRoot, mcp = [], mcpAdoptable = [], discovery, context = {}, ledger }: any) {
447
+ function plan({ assets, scope, scopeRoot, mcp = [], mcpAdoptable = [], discovery, context = {}, ledger } ) {
448
448
  const changes = [];
449
449
  const conflicts = [];
450
450
  const paths = nativePaths({ scope, scopeRoot });
@@ -480,13 +480,26 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
480
480
  return { changes, conflicts, prerequisites: [], notices: [...copyTree.notices, ...mcpPlan.notices] };
481
481
  }
482
482
 
483
- function apply({ changes, scope, scopeRoot, context = {} }: any) {
483
+ /** The hook front doors (IC-037): the one asset that holds the scripts the settings hooks run. */
484
+ function hookDoorAssets(assets ) { return (assets || []).filter((asset ) => asset.id === 'claude.hooks-scripts'); }
485
+
486
+ function planHookDoors({ assets, scope, scopeRoot, context = {}, ledger } ) {
487
+ const doors = planCopyTreeAssets({ assets: hookDoorAssets(assets), scope, scopeRoot, context, ledger, removing: false });
488
+ return { changes: doors.changes, conflicts: doors.conflicts, prerequisites: [], notices: doors.notices };
489
+ }
490
+
491
+ function verifyHookDoors({ assets, scope, scopeRoot, context = {} } ) {
492
+ const doors = verifyCopyTreeAssets({ assets: hookDoorAssets(assets), scope, scopeRoot, context });
493
+ return { ok: doors.conflicts.length === 0, statuses: doors.statuses, resources: doors.resources, conflicts: doors.conflicts };
494
+ }
495
+
496
+ function apply({ changes, scope, scopeRoot, context = {} } ) {
484
497
  for (const change of changes) {
485
498
  if (change.projection?.renderer !== INSTRUCTION_RENDERER) continue;
486
499
  // A plan records the resolved source. This keeps apply self-contained when
487
500
  // the lifecycle supplies normalized changes rather than the original asset
488
501
  // array, while still avoiding any implicit source discovery at write time.
489
- const source = change.source ?? sourcePath((context.assets || []).find((item: any) => item.id === change.assetId), context);
502
+ const source = change.source ?? sourcePath((context.assets || []).find((item ) => item.id === change.assetId), context);
490
503
  mergeMarkedSection(source, change.target ?? nativePaths({ scope, scopeRoot }).instructions);
491
504
  }
492
505
  applyCopyTreeAssets(changes);
@@ -498,7 +511,7 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
498
511
  return { applied: changes.length };
499
512
  }
500
513
 
501
- function remove({ changes }: any) {
514
+ function remove({ changes } ) {
502
515
  let removed = 0;
503
516
  for (const change of changes) {
504
517
  if (change.projection?.renderer === INSTRUCTION_RENDERER && removeMarkedSection(change.target)) removed += 1;
@@ -509,11 +522,11 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
509
522
  return { removed };
510
523
  }
511
524
 
512
- function verify({ assets, scope, scopeRoot, mcp = [], mcpAdoptable = [], discovery, ledger, operation, context = {} }: any) {
525
+ function verify({ assets, scope, scopeRoot, mcp = [], mcpAdoptable = [], discovery, ledger, operation, context = {} } ) {
513
526
  const paths = nativePaths({ scope, scopeRoot });
514
527
  const statuses = [];
515
528
  const resources = [];
516
- const instruction = assets.find((asset: any) => asset?.renderer === INSTRUCTION_RENDERER);
529
+ const instruction = assets.find((asset ) => asset?.renderer === INSTRUCTION_RENDERER);
517
530
  const state = markerState(paths.instructions);
518
531
  if (instruction) {
519
532
  statuses.push({ assetId: instruction.id, status: state.managed ? 'managed' : 'absent', target: paths.instructions });
@@ -536,7 +549,7 @@ function createClaudeAdapter({ declaredPaths = declaredHarnessPaths().claude } =
536
549
  return { ok: conflicts.length === 0, statuses, resources, conflicts };
537
550
  }
538
551
 
539
- return { nativePaths, discover, render, plan, apply, remove, verify };
552
+ return { nativePaths, discover, render, plan, apply, remove, verify, planHookDoors, verifyHookDoors };
540
553
  }
541
554
 
542
555
  const singleton = createClaudeAdapter();
@@ -544,5 +557,6 @@ const singleton = createClaudeAdapter();
544
557
  module.exports = {
545
558
  nativePaths: singleton.nativePaths, discover: singleton.discover, render: singleton.render,
546
559
  plan: singleton.plan, apply: singleton.apply, remove: singleton.remove, verify: singleton.verify,
560
+ planHookDoors: singleton.planHookDoors, verifyHookDoors: singleton.verifyHookDoors,
547
561
  createClaudeAdapter,
548
562
  };
@@ -10,8 +10,8 @@
10
10
  const fs = require('node:fs');
11
11
  const os = require('node:os');
12
12
  const path = require('node:path');
13
- const { nativeMcpCatalog } = require('../../registry/index.ts');
14
- const { readMcpFiles, planMcpEntries, verifyMcpEntries, ownedMcpIds, writeMcpEntries } = require('../mcp-entries.ts');
13
+ const { nativeMcpCatalog } = require('../../registry/index.js');
14
+ const { readMcpFiles, planMcpEntries, verifyMcpEntries, ownedMcpIds, writeMcpEntries } = require('../mcp-entries.js');
15
15
 
16
16
  const HARNESS = 'claude';
17
17
  const MCP_CONTAINER = 'mcpServers';
@@ -20,39 +20,39 @@ const MCP_RENDERER = 'claude-mcp';
20
20
  // install carries.
21
21
  const MCP_ASSET_ID = 'guidance.core';
22
22
 
23
- function ownershipIdentity(id: any) { return `doflow:${HARNESS}:mcp-server:${id}`; }
23
+ function ownershipIdentity(id ) { return `doflow:${HARNESS}:mcp-server:${id}`; }
24
24
 
25
25
  /** Claude Code's own per-server shape, the one the registry's native catalog renders. */
26
- function rendered(servers: any) {
26
+ function rendered(servers ) {
27
27
  const { serverDefs } = nativeMcpCatalog(servers);
28
- return servers.map((server: any) => ({ id: server.id, entry: serverDefs[server.id] }));
28
+ return servers.map((server ) => ({ id: server.id, entry: serverDefs[server.id] }));
29
29
  }
30
30
 
31
31
  /** Everything the shared entry-ownership rules need from this adapter. */
32
- function mcpEntriesInput({ paths, mcp = [], mcpAdoptable = [], ledger }: any) {
33
- const rows = (ledger?.resources || []).filter((row: any) => row.kind === 'mcp-server');
32
+ function mcpEntriesInput({ paths, mcp = [], mcpAdoptable = [], ledger } ) {
33
+ const rows = (ledger?.resources || []).filter((row ) => row.kind === 'mcp-server');
34
34
  return {
35
35
  file: paths.mcp, selected: rendered(mcp), adoptable: rendered(mcpAdoptable),
36
- ownRows: rows.filter((row: any) => row.harness === HARNESS).map((row: any) => ({
36
+ ownRows: rows.filter((row ) => row.harness === HARNESS).map((row ) => ({
37
37
  identity: row.identity, target: row.target, fingerprint: row.fingerprint ?? null, ownershipIdentity: row.ownershipIdentity, legacy: false,
38
38
  })),
39
- foreignRows: rows.filter((row: any) => row.harness !== HARNESS).map((row: any) => ({ harness: row.harness, identity: row.identity, target: row.target })),
39
+ foreignRows: rows.filter((row ) => row.harness !== HARNESS).map((row ) => ({ harness: row.harness, identity: row.identity, target: row.target })),
40
40
  identityFor: ownershipIdentity, assetId: MCP_ASSET_ID, renderer: MCP_RENDERER, label: 'Claude MCP',
41
41
  };
42
42
  }
43
43
 
44
- function readFiles(entries: any, fsImpl: any) {
44
+ function readFiles(entries , fsImpl ) {
45
45
  return readMcpFiles({ file: entries.file, ownRows: entries.ownRows, container: MCP_CONTAINER, fsImpl });
46
46
  }
47
47
 
48
48
  /** Server names Claude Code merges into a project from `~/.claude.json` beside the project's own
49
49
  * `.mcp.json`: the local scope (`projects[<root>].mcpServers`) and the user scope (`mcpServers`).
50
50
  * Read-only and for reach alone; a file that cannot be read contributes nothing (null). */
51
- function claudeJsonNames({ scopeRoot, homeDir, fsImpl }: any) {
51
+ function claudeJsonNames({ scopeRoot, homeDir, fsImpl } ) {
52
52
  let doc;
53
53
  try { doc = JSON.parse(fsImpl.readFileSync(path.join(homeDir, '.claude.json'), 'utf8')); } catch { return null; }
54
54
  if (!doc || typeof doc !== 'object' || Array.isArray(doc)) return null;
55
- const names = (servers: any) => (servers && typeof servers === 'object' && !Array.isArray(servers) ? Object.keys(servers) : []);
55
+ const names = (servers ) => (servers && typeof servers === 'object' && !Array.isArray(servers) ? Object.keys(servers) : []);
56
56
  const projects = doc.projects && typeof doc.projects === 'object' ? doc.projects : {};
57
57
  let real = scopeRoot;
58
58
  try { real = fsImpl.realpathSync(scopeRoot); } catch { /* the path as given */ }
@@ -64,7 +64,7 @@ function claudeJsonNames({ scopeRoot, homeDir, fsImpl }: any) {
64
64
  * (`mcpConfigured`): the scope's file, plus at project scope the local- and user-scope entries in
65
65
  * `~/.claude.json`. Claude Code also loads plugin, managed and connector servers DoFlow does not
66
66
  * read, so the view is never complete (`mcpComplete: false`) and absence is never proof. */
67
- function discoverMcp({ paths, mcp, mcpAdoptable, ledger, scope, scopeRoot, homeDir = os.homedir(), fsImpl = fs }: any) {
67
+ function discoverMcp({ paths, mcp, mcpAdoptable, ledger, scope, scopeRoot, homeDir = os.homedir(), fsImpl = fs } ) {
68
68
  const entries = mcpEntriesInput({ paths, mcp, mcpAdoptable, ledger });
69
69
  const mcpSnapshot = readFiles(entries, fsImpl);
70
70
  // `null` while nothing could be read; every name otherwise, whoever wrote it.
@@ -75,17 +75,17 @@ function discoverMcp({ paths, mcp, mcpAdoptable, ledger, scope, scopeRoot, homeD
75
75
  return { mcpSnapshot, mcpOwned: ownedMcpIds({ ...entries, files: mcpSnapshot }), mcpConfigured, mcpComplete: false };
76
76
  }
77
77
 
78
- function planMcp({ paths, mcp, mcpAdoptable, ledger, snapshot, removing, fsImpl = fs }: any) {
78
+ function planMcp({ paths, mcp, mcpAdoptable, ledger, snapshot, removing, fsImpl = fs } ) {
79
79
  const entries = mcpEntriesInput({ paths, mcp, mcpAdoptable, ledger });
80
80
  return planMcpEntries({ ...entries, files: snapshot ?? readFiles(entries, fsImpl), removing });
81
81
  }
82
82
 
83
83
  /** An emptied `mcpServers` stays as `{}`, as Claude Code itself leaves it. */
84
- function writeMcp(changes: any, { fsImpl = fs } = {}) {
84
+ function writeMcp(changes , { fsImpl = fs } = {}) {
85
85
  return writeMcpEntries(changes, { container: MCP_CONTAINER, keepEmptyContainer: true, fsImpl });
86
86
  }
87
87
 
88
- function verifyMcp({ paths, mcp, mcpAdoptable, ledger, snapshot, removing, sourceVersion, fsImpl = fs }: any) {
88
+ function verifyMcp({ paths, mcp, mcpAdoptable, ledger, snapshot, removing, sourceVersion, fsImpl = fs } ) {
89
89
  const entries = mcpEntriesInput({ paths, mcp, mcpAdoptable, ledger });
90
90
  const files = readFiles(entries, fsImpl);
91
91
  return verifyMcpEntries({ ...entries, files, snapshot: snapshot ?? files, removing, harness: HARNESS, sourceVersion });
@@ -8,7 +8,7 @@
8
8
  const crypto = require('node:crypto');
9
9
  const fs = require('node:fs');
10
10
  const path = require('node:path');
11
- const { atomicWrite } = require('./config.ts');
11
+ const { atomicWrite } = require('./config.js');
12
12
 
13
13
  const AGENT_DIRECTORY = 'agents';
14
14
  const AGENT_KIND = 'custom-agent';
@@ -23,38 +23,38 @@ const IMPLEMENTATION_ROLES = new Set([
23
23
  ]);
24
24
  const ALLOWED_FIELDS = new Set([...REQUIRED_FIELDS, 'sandbox_mode']);
25
25
 
26
- function fingerprint(content: string): string {
26
+ function fingerprint(content ) {
27
27
  return `sha256:${crypto.createHash('sha256').update(content).digest('hex')}`;
28
28
  }
29
29
 
30
- function assertAgentName(name: any, label: string = 'agent name'): string {
30
+ function assertAgentName(name , label = 'agent name') {
31
31
  if (typeof name !== 'string' || !/^[a-z][a-z0-9-]*$/.test(name)) {
32
32
  throw new Error(`${label} must be a lowercase kebab-case identifier`);
33
33
  }
34
34
  return name;
35
35
  }
36
36
 
37
- function filenameFor(name: string): string {
37
+ function filenameFor(name ) {
38
38
  assertAgentName(name);
39
39
  return `${name}.toml`;
40
40
  }
41
41
 
42
- function expectedName(fileName: any): string {
42
+ function expectedName(fileName ) {
43
43
  if (typeof fileName !== 'string' || path.basename(fileName) !== fileName || !fileName.endsWith('.toml')) {
44
44
  throw new Error('Agent filename must be a direct .toml filename');
45
45
  }
46
46
  return assertAgentName(fileName.slice(0, -'.toml'.length), 'Agent filename');
47
47
  }
48
48
 
49
- function parseQuoted(value: string, field: string, line: number): string {
49
+ function parseQuoted(value , field , line ) {
50
50
  if (!/^"(?:[^"\\\n]|\\.)*"$/.test(value)) throw new Error(`${field} must be a quoted TOML string on line ${line}`);
51
51
  try { return JSON.parse(value); } catch { throw new Error(`${field} has an invalid quoted value on line ${line}`); }
52
52
  }
53
53
 
54
54
  /** Parse the intentionally small TOML contract supported by Codex agent definitions. */
55
- function parseAgentToml(source: any, { fileName }: { fileName?: string } = {}): Record<string, string> {
55
+ function parseAgentToml(source , { fileName } = {}) {
56
56
  if (typeof source !== 'string') throw new Error('Agent TOML source must be text');
57
- const values: Record<string, string> = {};
57
+ const values = {};
58
58
  const lines = source.split(/\r?\n/);
59
59
  for (let index = 0; index < lines.length; index++) {
60
60
  const line = lines[index];
@@ -64,7 +64,7 @@ function parseAgentToml(source: any, { fileName }: { fileName?: string } = {}):
64
64
  const field = triple[1];
65
65
  if (!ALLOWED_FIELDS.has(field)) throw new Error(`Unsupported agent field '${field}'`);
66
66
  if (Object.hasOwn(values, field)) throw new Error(`Duplicate agent field '${field}'`);
67
- const body: string[] = [];
67
+ const body = [];
68
68
  let closed = false;
69
69
  while (++index < lines.length) {
70
70
  if (/^"""\s*$/.test(lines[index])) { closed = true; break; }
@@ -85,7 +85,7 @@ function parseAgentToml(source: any, { fileName }: { fileName?: string } = {}):
85
85
  return values;
86
86
  }
87
87
 
88
- function validateAgentContract(source: any, { fileName }: { fileName?: string } = {}): any {
88
+ function validateAgentContract(source , { fileName } = {}) {
89
89
  const agent = parseAgentToml(source, { fileName });
90
90
  for (const field of REQUIRED_FIELDS) {
91
91
  if (typeof agent[field] !== 'string' || !agent[field].trim()) throw new Error(`Agent is missing required '${field}'`);
@@ -106,7 +106,7 @@ function validateAgentContract(source: any, { fileName }: { fileName?: string }
106
106
  return Object.freeze({ ...agent, fileName: filenameFor(agent.name) });
107
107
  }
108
108
 
109
- function agentDirectory({ scope, codexDir, projectRoot, paths }: { scope?: string, codexDir?: string, projectRoot?: string, paths?: any } = {}): string {
109
+ function agentDirectory({ scope, codexDir, projectRoot, paths } = {}) {
110
110
  // Preferred: the declared path resolved by the adapter (harnesses.json "paths".agentsDirectory).
111
111
  if (paths?.agentsDirectory) return paths.agentsDirectory;
112
112
  // Legacy derivation for direct callers passing raw scope inputs; kept byte-compatible with the
@@ -122,19 +122,19 @@ function agentDirectory({ scope, codexDir, projectRoot, paths }: { scope?: strin
122
122
  throw new Error(`Unsupported Codex agent scope: ${scope}`);
123
123
  }
124
124
 
125
- function destinationFor(directory: string, name: string): string {
125
+ function destinationFor(directory , name ) {
126
126
  const file = path.resolve(directory, filenameFor(name));
127
127
  const root = `${path.resolve(directory)}${path.sep}`;
128
128
  if (!file.startsWith(root)) throw new Error(`Refusing to write agent '${name}' outside the Codex agents directory`);
129
129
  return file;
130
130
  }
131
131
 
132
- function discoverCodexAgents(sourceDir: any, fsImpl: any = fs): any[] {
132
+ function discoverCodexAgents(sourceDir , fsImpl = fs) {
133
133
  if (!sourceDir) throw new Error('sourceDir is required for Codex agents');
134
134
  const directory = path.resolve(sourceDir);
135
135
  if (!fsImpl.existsSync(directory)) throw new Error(`Codex agent source directory does not exist: ${sourceDir}`);
136
- const agents: any[] = [];
137
- for (const entry of fsImpl.readdirSync(directory, { withFileTypes: true }).sort((a: any, b: any) => a.name.localeCompare(b.name))) {
136
+ const agents = [];
137
+ for (const entry of fsImpl.readdirSync(directory, { withFileTypes: true }).sort((a , b ) => a.name.localeCompare(b.name))) {
138
138
  if (!entry.name.endsWith('.toml')) continue;
139
139
  if (!entry.isFile()) throw new Error(`Codex agent source '${entry.name}' must be a regular file`);
140
140
  const name = expectedName(entry.name);
@@ -145,11 +145,11 @@ function discoverCodexAgents(sourceDir: any, fsImpl: any = fs): any[] {
145
145
  return agents;
146
146
  }
147
147
 
148
- function isOwnedResource(resource: any, scope: any): boolean {
148
+ function isOwnedResource(resource , scope ) {
149
149
  return resource && resource.target === 'codex' && resource.scope === scope && resource.kind === AGENT_KIND && typeof resource.identity === 'string';
150
150
  }
151
151
 
152
- function resourceFor(agent: any, scope: any, sourceVersion: any): any {
152
+ function resourceFor(agent , scope , sourceVersion ) {
153
153
  return {
154
154
  target: 'codex', scope, kind: AGENT_KIND, identity: `agent:${agent.name}`,
155
155
  sourceVersion, fingerprint: agent.fingerprint, selection: true,
@@ -163,13 +163,13 @@ function resourceFor(agent: any, scope: any, sourceVersion: any): any {
163
163
  * recording ownership instead of refusing. See planCodexConfig for why this is not `force`: a
164
164
  * record that disagrees with the file on disk stays a conflict regardless of `adopt`.
165
165
  */
166
- function planCodexAgents({ scope, codexDir, projectRoot, sourceDir, sourceVersion = 'unknown', managedResources = [], adopt = false, fsImpl = fs }: any): any {
166
+ function planCodexAgents({ scope, codexDir, projectRoot, sourceDir, sourceVersion = 'unknown', managedResources = [], adopt = false, fsImpl = fs } ) {
167
167
  const directory = agentDirectory({ scope, codexDir, projectRoot });
168
168
  const agents = discoverCodexAgents(sourceDir, fsImpl);
169
- const owned = new Map<string, any>(managedResources.filter((resource: any) => isOwnedResource(resource, scope)).map((resource: any) => [resource.identity, resource]));
170
- const changes: any[] = [];
171
- const conflicts: string[] = [];
172
- const nextManagedResources = managedResources.filter((resource: any) => !isOwnedResource(resource, scope));
169
+ const owned = new Map (managedResources.filter((resource ) => isOwnedResource(resource, scope)).map((resource ) => [resource.identity, resource]));
170
+ const changes = [];
171
+ const conflicts = [];
172
+ const nextManagedResources = managedResources.filter((resource ) => !isOwnedResource(resource, scope));
173
173
  for (const agent of agents) {
174
174
  const file = destinationFor(directory, agent.name);
175
175
  const identity = `agent:${agent.name}`;
@@ -191,13 +191,13 @@ function planCodexAgents({ scope, codexDir, projectRoot, sourceDir, sourceVersio
191
191
  };
192
192
  }
193
193
 
194
- function applyCodexAgents(plan: any, { dryRun = false, fsImpl = fs }: { dryRun?: boolean, fsImpl?: any } = {}): any {
194
+ function applyCodexAgents(plan , { dryRun = false, fsImpl = fs } = {}) {
195
195
  if (!plan.ok || dryRun || plan.status === 'unchanged') return { ...plan, applied: false };
196
196
  for (const change of plan.changes) atomicWrite(change.file, change.content, fsImpl);
197
197
  return { ...plan, applied: true };
198
198
  }
199
199
 
200
- function reconcileCodexAgents(options: any): any {
200
+ function reconcileCodexAgents(options ) {
201
201
  return applyCodexAgents(planCodexAgents(options), options);
202
202
  }
203
203