@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
@@ -63,9 +63,9 @@
63
63
  * @returns {ShadowVerdict|null} `null` when `presentScopes` carries no usable scope name — there is
64
64
  * no asset to resolve a verdict for. Otherwise a `ShadowVerdict`.
65
65
  */
66
- function resolveShadowVerdict(presentScopes: any, precedence: any): any {
66
+ function resolveShadowVerdict(presentScopes , precedence ) {
67
67
  const scopes = Array.isArray(presentScopes)
68
- ? [...new Set(presentScopes.filter((scope: any) => typeof scope === 'string' && scope !== ''))]
68
+ ? [...new Set(presentScopes.filter((scope ) => typeof scope === 'string' && scope !== ''))]
69
69
  : [];
70
70
  if (scopes.length === 0) return null;
71
71
 
@@ -41,11 +41,11 @@
41
41
  */
42
42
 
43
43
  const os = require('node:os');
44
- const { registryLifecycleView, LIFECYCLE_HARNESSES } = require('../../lifecycle/view.ts');
45
- const { readLock } = require('../../state/lockfile.ts');
46
- const { stateRoot, readLedger } = require('../../state/index.ts');
47
- const { recordedMcpSelections } = require('../../install/mcp.ts');
48
- const { readInstallManifest } = require('../../install/manifest.ts');
44
+ const { registryLifecycleView, LIFECYCLE_HARNESSES } = require('../../lifecycle/view.js');
45
+ const { readLock } = require('../../state/lockfile.js');
46
+ const { stateRoot, readLedger } = require('../../state/index.js');
47
+ const { recordedMcpSelections } = require('../../install/mcp.js');
48
+ const { readInstallManifest } = require('../../install/manifest.js');
49
49
 
50
50
  /**
51
51
  * @typedef {Object} ScopeSnapshot The `SCOPE_SNAPSHOT` entity of the feature's data model.
@@ -68,7 +68,7 @@ const { readInstallManifest } = require('../../install/manifest.ts');
68
68
  */
69
69
 
70
70
  /** @returns {ScopeSnapshot} */
71
- function snapshot(scope: any, view: any, targets: any): any {
71
+ function snapshot(scope , view , targets ) {
72
72
  const { ledger } = view;
73
73
  const wanted = new Set(targets);
74
74
  return {
@@ -77,7 +77,7 @@ function snapshot(scope: any, view: any, targets: any): any {
77
77
  stateRoot: view.stateRoot,
78
78
  recorded: ledger.resources.length > 0 || Object.keys(ledger.targets).length > 0,
79
79
  targets,
80
- resources: ledger.resources.filter((resource: any) => wanted.has(resource?.harness)),
80
+ resources: ledger.resources.filter((resource ) => wanted.has(resource?.harness)),
81
81
  ledger,
82
82
  plan: view.plan,
83
83
  };
@@ -104,7 +104,7 @@ function snapshot(scope: any, view: any, targets: any): any {
104
104
  * computed from a selection nobody can read, so a currency judgement derived from it would be
105
105
  * fiction. `reconcile` fails on the same document.
106
106
  */
107
- function readScopes({ registry, repoRoot, projectRoot, targets = LIFECYCLE_HARNESSES, locks }: any): any {
107
+ function readScopes({ registry, repoRoot, projectRoot, targets = LIFECYCLE_HARNESSES, locks } ) {
108
108
  const wanted = [...new Set(targets)];
109
109
  const resolved = locks ?? {
110
110
  // The global lock root is the home directory, the same root design R7 keeps out of this
@@ -112,7 +112,7 @@ function readScopes({ registry, repoRoot, projectRoot, targets = LIFECYCLE_HARNE
112
112
  global: readLock({ scope: 'global' }),
113
113
  project: readLock({ scope: 'project', projectRoot }),
114
114
  };
115
- const read = (scope: any) => {
115
+ const read = (scope ) => {
116
116
  // Each scope's own ledger, at the root the view itself reads it from.
117
117
  const ledger = readLedger(scope === 'global'
118
118
  ? stateRoot({ scope: 'global', homeDir: os.homedir() }) : stateRoot({ scope: 'project', projectRoot }));
@@ -88,8 +88,8 @@ const WHOLESALE_ASSETS = Object.freeze({
88
88
 
89
89
  /** Whether this harness loads this asset's native directory wholesale. `Array.isArray` also guards
90
90
  * a harness id that collides with an `Object.prototype` key. */
91
- function loadsWholesale(harness: any, assetId: any): boolean {
92
- const assets = (WHOLESALE_ASSETS as any)[harness];
91
+ function loadsWholesale(harness , assetId ) {
92
+ const assets = (WHOLESALE_ASSETS )[harness];
93
93
  return Array.isArray(assets) && assets.includes(assetId);
94
94
  }
95
95
 
@@ -98,7 +98,7 @@ function loadsWholesale(harness: any, assetId: any): boolean {
98
98
  * subdirectory holding managed assets is recognised as structure, not as a foreign entry); only
99
99
  * resources whose harness loads them wholesale contribute a `wholesale` target, and only a
100
100
  * directory with at least one of those is ever read. */
101
- function groupByParentDir(resources: any): any {
101
+ function groupByParentDir(resources ) {
102
102
  const byDir = new Map();
103
103
  const managedDirs = new Set();
104
104
  for (const resource of resources ?? []) {
@@ -119,10 +119,10 @@ function groupByParentDir(resources: any): any {
119
119
  /** Whether a directory entry is part of the managed tree's own structure — it is, or contains at
120
120
  * some depth, the parent directory of a managed resource. Scans `managedDirs`, which is bounded by
121
121
  * the number of managed resources rather than by directory size (R6). */
122
- function holdsManagedAsset(candidatePath: any, managedDirs: any): boolean {
122
+ function holdsManagedAsset(candidatePath , managedDirs ) {
123
123
  const prefix = candidatePath + path.sep;
124
124
  for (const dir of managedDirs) {
125
- if (dir === candidatePath || (dir as string).startsWith(prefix)) return true;
125
+ if (dir === candidatePath || (dir ).startsWith(prefix)) return true;
126
126
  }
127
127
  return false;
128
128
  }
@@ -152,13 +152,13 @@ function holdsManagedAsset(candidatePath: any, managedDirs: any): boolean {
152
152
  * beside eight reported siblings invited the reading that eight more had been hidden. IC-002's
153
153
  * final field is dropped with it (task F.3); see `index.js#buildInventoryReport`.
154
154
  */
155
- function inspectSiblings({ resources, fsImpl = fs }: any = {}): any {
155
+ function inspectSiblings({ resources, fsImpl = fs } = {}) {
156
156
  const { byDir, managedDirs } = groupByParentDir(resources);
157
- const candidatesByTarget: any = {};
157
+ const candidatesByTarget = {};
158
158
  let directoriesInspected = 0;
159
159
 
160
160
  for (const [dir, { basenames, wholesale }] of byDir) {
161
- if ((wholesale as any[]).length === 0) continue; // name-resolved: never read, not even to count.
161
+ if ((wholesale ).length === 0) continue; // name-resolved: never read, not even to count.
162
162
 
163
163
  let entries;
164
164
  try {
@@ -168,12 +168,12 @@ function inspectSiblings({ resources, fsImpl = fs }: any = {}): any {
168
168
  }
169
169
  directoriesInspected += 1;
170
170
 
171
- const unmanaged: any[] = [];
171
+ const unmanaged = [];
172
172
  for (const entry of entries) {
173
- const name = (entry as any).name;
174
- if ((basenames as Set<string>).has(name)) continue; // the managed file itself.
175
- const entryPath = path.join(dir as string, name);
176
- const isDirectory = (entry as any).isDirectory?.() === true;
173
+ const name = (entry ).name;
174
+ if ((basenames ).has(name)) continue; // the managed file itself.
175
+ const entryPath = path.join(dir , name);
176
+ const isDirectory = (entry ).isDirectory?.() === true;
177
177
  if (isDirectory && holdsManagedAsset(entryPath, managedDirs)) continue; // managed structure.
178
178
  unmanaged.push({ name, path: entryPath, parentDir: dir, kind: isDirectory ? 'directory' : 'file' });
179
179
  }
@@ -181,8 +181,8 @@ function inspectSiblings({ resources, fsImpl = fs }: any = {}): any {
181
181
 
182
182
  // Attributed per managed target rather than shared, so each candidate names the harness and
183
183
  // asset whose wholesale load is the reason it is operative at all.
184
- for (const { target, harness, assetId } of (wholesale as any[])) {
185
- candidatesByTarget[target] = unmanaged.map((found: any) => ({ ...found, harness, assetId }));
184
+ for (const { target, harness, assetId } of (wholesale )) {
185
+ candidatesByTarget[target] = unmanaged.map((found ) => ({ ...found, harness, assetId }));
186
186
  }
187
187
  }
188
188
 
@@ -15,10 +15,10 @@ const HARD_MAX_CHUNK_CHARS = 1200;
15
15
  /** Split raw markdown into chunks: {id, path, section, text}. Ids are stable path+ordinal pairs,
16
16
  * not content hashes — the index manifest owns content addressing, and a chunk whose text changed
17
17
  * should keep its identity so diffs are legible. */
18
- function chunkMarkdown(rawText: any, { path: filePath }: { path?: string } = {}): any[] {
18
+ function chunkMarkdown(rawText , { path: filePath } = {}) {
19
19
  const { body, title } = stripFrontmatter(String(rawText ?? ''));
20
20
  const sections = splitSections(body);
21
- const chunks: any[] = [];
21
+ const chunks = [];
22
22
  let ordinal = 0;
23
23
  for (const section of sections) {
24
24
  for (const piece of packSection(section.text)) {
@@ -35,7 +35,7 @@ function chunkMarkdown(rawText: any, { path: filePath }: { path?: string } = {})
35
35
  return chunks;
36
36
  }
37
37
 
38
- function stripFrontmatter(text: string): { body: string; title: string | null } {
38
+ function stripFrontmatter(text ) {
39
39
  const match = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(text);
40
40
  if (!match) return { body: text, title: null };
41
41
  const meta = match[1];
@@ -44,10 +44,10 @@ function stripFrontmatter(text: string): { body: string; title: string | null }
44
44
  }
45
45
 
46
46
  /** Heading-bounded sections; a leading H1 is metadata (the title), not a section boundary. */
47
- function splitSections(body: string): Array<{ heading: string | null; text: string }> {
47
+ function splitSections(body ) {
48
48
  const lines = body.split(/\r?\n/);
49
- const sections: Array<{ heading: string | null; text: string }> = [];
50
- let current: { heading: string | null; lines: string[] } = { heading: null, lines: [] };
49
+ const sections = [];
50
+ let current = { heading: null, lines: [] };
51
51
  const flush = () => {
52
52
  if (current.lines.some((l) => l.trim() !== '')) {
53
53
  sections.push({ heading: current.heading, text: current.lines.join('\n') });
@@ -68,9 +68,9 @@ function splitSections(body: string): Array<{ heading: string | null; text: stri
68
68
 
69
69
  /** Group a section's blocks (paragraphs, lists, fenced code) into chunks near the target size.
70
70
  * A block larger than the hard max (a long code fence) stands alone rather than being cut. */
71
- function packSection(text: string): string[] {
71
+ function packSection(text ) {
72
72
  const blocks = splitBlocks(text).filter((b) => b.trim() !== '');
73
- const packed: string[] = [];
73
+ const packed = [];
74
74
  let buffer = '';
75
75
  for (const block of blocks) {
76
76
  if (block.length > HARD_MAX_CHUNK_CHARS) {
@@ -91,11 +91,11 @@ function packSection(text: string): string[] {
91
91
  }
92
92
 
93
93
  /** Split into blocks at blank lines, keeping fenced code blocks intact across their blank lines. */
94
- function splitBlocks(text: string): string[] {
94
+ function splitBlocks(text ) {
95
95
  const lines = text.split(/\r?\n/);
96
- const blocks: string[] = [];
97
- let buffer: string[] = [];
98
- let fence: string | null = null;
96
+ const blocks = [];
97
+ let buffer = [];
98
+ let fence = null;
99
99
  for (const line of lines) {
100
100
  const opening = /^\s*(```|~~~)/.exec(line);
101
101
  if (fence) {
@@ -11,9 +11,9 @@ const path = require('node:path');
11
11
  * @param {{ k?: number }} [options]
12
12
  * @returns {Array<{ id: string, rrfScore: number }>}
13
13
  */
14
- function reciprocalRankFusion(rankedLists: any[][], { k = 60 }: { k?: number } = {}): any[] {
15
- const scores = new Map<string, number>();
16
- const items = new Map<string, any>();
14
+ function reciprocalRankFusion(rankedLists , { k = 60 } = {}) {
15
+ const scores = new Map ();
16
+ const items = new Map ();
17
17
 
18
18
  for (const list of rankedLists) {
19
19
  if (!Array.isArray(list)) continue;
@@ -32,7 +32,7 @@ function reciprocalRankFusion(rankedLists: any[][], { k = 60 }: { k?: number } =
32
32
  }
33
33
  }
34
34
 
35
- const fused: any[] = [];
35
+ const fused = [];
36
36
  for (const [id, rrfScore] of scores.entries()) {
37
37
  fused.push({
38
38
  ...items.get(id),
@@ -41,7 +41,7 @@ function reciprocalRankFusion(rankedLists: any[][], { k = 60 }: { k?: number } =
41
41
  });
42
42
  }
43
43
 
44
- fused.sort((a: any, b: any) => b.rrfScore - a.rrfScore || (a.id < b.id ? -1 : 1));
44
+ fused.sort((a , b ) => b.rrfScore - a.rrfScore || (a.id < b.id ? -1 : 1));
45
45
  return fused;
46
46
  }
47
47
 
@@ -51,7 +51,7 @@ function reciprocalRankFusion(rankedLists: any[][], { k = 60 }: { k?: number } =
51
51
  * @param {string} [projectRoot]
52
52
  * @returns {{ file: string, line?: number, endLine?: number }}
53
53
  */
54
- function normalizeLocator(raw: any, projectRoot: string = process.cwd()): { file: string; line?: number; endLine?: number } {
54
+ function normalizeLocator(raw , projectRoot = process.cwd()) {
55
55
  if (!raw) return { file: '' };
56
56
  if (typeof raw === 'string') {
57
57
  const match = raw.match(/^([^:]+)(?::(\d+))?(?::(\d+))?$/);
@@ -97,22 +97,22 @@ function fuseHybridResults({
97
97
  projectRoot = process.cwd(),
98
98
  maxSnippetLines = 50,
99
99
  fsImpl = fs,
100
- }: {
101
- lexicalResults?: any[];
102
- semanticResults?: any[];
103
- k?: number;
104
- topN?: number;
105
- projectRoot?: string;
106
- maxSnippetLines?: number;
107
- fsImpl?: any;
108
- } = {}): any[] {
109
- const normLex = (Array.isArray(lexicalResults) ? lexicalResults : []).map((item: any, idx: number) => {
100
+ }
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+ = {}) {
109
+ const normLex = (Array.isArray(lexicalResults) ? lexicalResults : []).map((item , idx ) => {
110
110
  const loc = normalizeLocator(item.locator || item.path || item.file, projectRoot);
111
111
  const id = `${loc.file}:${loc.line || 1}`;
112
112
  return { ...item, id, locator: loc, sourceList: 'lexical', originalRank: idx };
113
113
  });
114
114
 
115
- const normSem = (Array.isArray(semanticResults) ? semanticResults : []).map((item: any, idx: number) => {
115
+ const normSem = (Array.isArray(semanticResults) ? semanticResults : []).map((item , idx ) => {
116
116
  const loc = normalizeLocator(item.locator || item.path || item.file, projectRoot);
117
117
  const id = `${loc.file}:${loc.line || 1}`;
118
118
  return { ...item, id, locator: loc, sourceList: 'semantic', originalRank: idx };
@@ -11,23 +11,23 @@
11
11
  const fs = require('node:fs');
12
12
  const path = require('node:path');
13
13
  const crypto = require('node:crypto');
14
- const { chunkMarkdown } = require('./chunker.ts');
14
+ const { chunkMarkdown } = require('./chunker.js');
15
15
 
16
16
  const INDEX_VERSION = 1;
17
17
  const MANIFEST_FILE = 'manifest.json';
18
18
  const CHUNKS_FILE = 'chunks.jsonl';
19
19
 
20
- function sha256(buffer: any): string {
20
+ function sha256(buffer ) {
21
21
  return crypto.createHash('sha256').update(buffer).digest('hex');
22
22
  }
23
23
 
24
24
  /** Every .md file under the corpus root, as sorted relative paths (deterministic builds). */
25
- function listMarkdownFiles(corpusDir: string, { fsImpl = fs }: { fsImpl?: any } = {}): string[] {
26
- const out: string[] = [];
27
- const walk = (dir: string) => {
28
- let entries: any[];
25
+ function listMarkdownFiles(corpusDir , { fsImpl = fs } = {}) {
26
+ const out = [];
27
+ const walk = (dir ) => {
28
+ let entries ;
29
29
  try { entries = fsImpl.readdirSync(dir, { withFileTypes: true }); } catch { return; }
30
- entries.sort((a: any, b: any) => (a.name < b.name ? -1 : 1));
30
+ entries.sort((a , b ) => (a.name < b.name ? -1 : 1));
31
31
  for (const entry of entries) {
32
32
  const abs = path.join(dir, entry.name);
33
33
  if (entry.isDirectory()) walk(abs);
@@ -38,22 +38,22 @@ function listMarkdownFiles(corpusDir: string, { fsImpl = fs }: { fsImpl?: any }
38
38
  return out.sort((a, b) => (a < b ? -1 : 1));
39
39
  }
40
40
 
41
- function readManifest(indexDir: string, { fsImpl = fs }: { fsImpl?: any } = {}): any {
41
+ function readManifest(indexDir , { fsImpl = fs } = {}) {
42
42
  try {
43
43
  return JSON.parse(fsImpl.readFileSync(path.join(indexDir, MANIFEST_FILE), 'utf8'));
44
44
  } catch { return null; }
45
45
  }
46
46
 
47
- function loadChunksByPath(indexDir: string, { fsImpl = fs }: { fsImpl?: any } = {}): Map<string, any[]> {
48
- const byPath = new Map<string, any[]>();
49
- let raw: string;
47
+ function loadChunksByPath(indexDir , { fsImpl = fs } = {}) {
48
+ const byPath = new Map ();
49
+ let raw ;
50
50
  try { raw = fsImpl.readFileSync(path.join(indexDir, CHUNKS_FILE), 'utf8'); } catch { return byPath; }
51
51
  for (const line of raw.split('\n')) {
52
52
  if (!line.trim()) continue;
53
- let chunk: any;
53
+ let chunk ;
54
54
  try { chunk = JSON.parse(line); } catch { continue; }
55
55
  if (!byPath.has(chunk.path)) byPath.set(chunk.path, []);
56
- byPath.get(chunk.path)!.push(chunk);
56
+ byPath.get(chunk.path) .push(chunk);
57
57
  }
58
58
  return byPath;
59
59
  }
@@ -61,22 +61,22 @@ function loadChunksByPath(indexDir: string, { fsImpl = fs }: { fsImpl?: any } =
61
61
  /** Build (or incrementally refresh) the index. Files whose digest already sits in the manifest
62
62
  * reuse their stored chunks byte-for-byte; only changed or new files are re-chunked. Returns
63
63
  * {files, chunks, rebuilt[], reusedCount}. */
64
- function buildIndex({ corpusDir, indexDir, fsImpl = fs }: { corpusDir: string; indexDir: string; fsImpl?: any } = {} as any): any {
64
+ function buildIndex({ corpusDir, indexDir, fsImpl = fs } = {} ) {
65
65
  const relPaths = listMarkdownFiles(corpusDir, { fsImpl });
66
66
  const previous = readManifest(indexDir, { fsImpl });
67
67
  const previousFiles = previous?.files ?? {};
68
68
  const reusableChunks = loadChunksByPath(indexDir, { fsImpl });
69
69
 
70
- const files: Record<string, any> = {};
71
- const allChunks: any[] = [];
72
- const rebuilt: string[] = [];
70
+ const files = {};
71
+ const allChunks = [];
72
+ const rebuilt = [];
73
73
  let reusedCount = 0;
74
74
  for (const rel of relPaths) {
75
75
  const content = fsImpl.readFileSync(path.join(corpusDir, rel), 'utf8');
76
76
  const digest = sha256(Buffer.from(content, 'utf8'));
77
77
  const prior = previousFiles[rel];
78
78
  if (prior && prior.digest === digest && reusableChunks.has(rel)) {
79
- const chunks = reusableChunks.get(rel)!;
79
+ const chunks = reusableChunks.get(rel) ;
80
80
  files[rel] = { digest, chunks: chunks.length };
81
81
  allChunks.push(...chunks);
82
82
  reusedCount += 1;
@@ -89,7 +89,7 @@ function buildIndex({ corpusDir, indexDir, fsImpl = fs }: { corpusDir: string; i
89
89
  }
90
90
 
91
91
  fsImpl.mkdirSync(indexDir, { recursive: true });
92
- const body = allChunks.map((chunk: any) => JSON.stringify(chunk)).join('\n') + (allChunks.length ? '\n' : '');
92
+ const body = allChunks.map((chunk ) => JSON.stringify(chunk)).join('\n') + (allChunks.length ? '\n' : '');
93
93
  const tmpChunks = `${path.join(indexDir, CHUNKS_FILE)}.${process.pid}.tmp`;
94
94
  fsImpl.writeFileSync(tmpChunks, body, 'utf8');
95
95
  fsImpl.renameSync(tmpChunks, path.join(indexDir, CHUNKS_FILE));
@@ -108,11 +108,11 @@ function buildIndex({ corpusDir, indexDir, fsImpl = fs }: { corpusDir: string; i
108
108
 
109
109
  /** Load the index for querying. Returns null when absent/malformed; staleness is the caller's
110
110
  * policy decision (see ensureFreshIndex), never a silent assumption here. */
111
- function loadIndex({ indexDir, fsImpl = fs }: { indexDir: string; fsImpl?: any } = {} as any): any {
111
+ function loadIndex({ indexDir, fsImpl = fs } = {} ) {
112
112
  const manifest = readManifest(indexDir, { fsImpl });
113
113
  if (!manifest || manifest.version !== INDEX_VERSION) return null;
114
- const chunks: any[] = [];
115
- let raw: string;
114
+ const chunks = [];
115
+ let raw ;
116
116
  try { raw = fsImpl.readFileSync(path.join(indexDir, CHUNKS_FILE), 'utf8'); } catch { return null; }
117
117
  for (const line of raw.split('\n')) {
118
118
  if (!line.trim()) continue;
@@ -123,7 +123,7 @@ function loadIndex({ indexDir, fsImpl = fs }: { indexDir: string; fsImpl?: any }
123
123
 
124
124
  /** True when every corpus file's current digest matches the manifest. Missing extra corpus files
125
125
  * (present on disk, absent from the manifest) also count as stale — they are not yet searchable. */
126
- function isFresh({ corpusDir, indexDir, fsImpl = fs }: { corpusDir: string; indexDir: string; fsImpl?: any } = {} as any): boolean {
126
+ function isFresh({ corpusDir, indexDir, fsImpl = fs } = {} ) {
127
127
  const manifest = readManifest(indexDir, { fsImpl });
128
128
  if (!manifest) return false;
129
129
  const relPaths = listMarkdownFiles(corpusDir, { fsImpl });
@@ -10,9 +10,9 @@
10
10
 
11
11
  const fs = require('node:fs');
12
12
  const path = require('node:path');
13
- const { buildIndex, loadIndex, isFresh } = require('./index-store.ts');
14
- const { finishRuntime, usageError, captureCaught } = require('../cli-result.ts');
15
- const { resolveRunsLocation } = require('../trace/ledger.ts');
13
+ const { buildIndex, loadIndex, isFresh } = require('./index-store.js');
14
+ const { finishRuntime, usageError, captureCaught } = require('../cli-result.js');
15
+ const { resolveRunsLocation } = require('../trace/ledger.js');
16
16
 
17
17
  const BM25_K1 = 1.5;
18
18
  const BM25_B = 0.75;
@@ -22,7 +22,7 @@ const STOPWORDS = new Set([
22
22
  'do', 'does', 'did', 'how', 'what', 'when', 'which', 'who', 'why', 'not', 'no', 'yes', 'can',
23
23
  ]);
24
24
 
25
- function tokenize(text: any): string[] {
25
+ function tokenize(text ) {
26
26
  return String(text ?? '')
27
27
  .toLowerCase()
28
28
  .split(/[^a-z0-9]+/)
@@ -31,24 +31,24 @@ function tokenize(text: any): string[] {
31
31
 
32
32
  /** Deterministic BM25 (Okapi) over preloaded chunks. Corpus sizes here are thousands of chunks at
33
33
  * most, so scoring at query time from plain arrays beats maintaining incremental postings. */
34
- function bm25Rank(queryText: string, chunks: any[], { k = 5 }: { k?: number } = {}): any[] {
34
+ function bm25Rank(queryText , chunks , { k = 5 } = {}) {
35
35
  const queryTerms = [...new Set(tokenize(queryText))];
36
36
  if (!queryTerms.length || !chunks.length) return [];
37
- const docTokens = chunks.map((chunk: any) => tokenize(`${chunk.title ?? ''} ${chunk.text}`));
38
- const avgLen = docTokens.reduce((sum: number, tokens: string[]) => sum + tokens.length, 0) / docTokens.length || 1;
37
+ const docTokens = chunks.map((chunk ) => tokenize(`${chunk.title ?? ''} ${chunk.text}`));
38
+ const avgLen = docTokens.reduce((sum , tokens ) => sum + tokens.length, 0) / docTokens.length || 1;
39
39
 
40
- const df = new Map<string, number>();
40
+ const df = new Map ();
41
41
  for (const term of queryTerms) {
42
42
  let count = 0;
43
43
  for (const tokens of docTokens) if (tokens.includes(term)) count += 1;
44
44
  df.set(term, count);
45
45
  }
46
46
 
47
- const scored: Array<{ score: number; chunk: any }> = [];
47
+ const scored = [];
48
48
  for (let i = 0; i < chunks.length; i += 1) {
49
49
  const tokens = docTokens[i];
50
50
  if (!tokens.length) continue;
51
- const tf = new Map<string, number>();
51
+ const tf = new Map ();
52
52
  for (const token of tokens) tf.set(token, (tf.get(token) ?? 0) + 1);
53
53
  let score = 0;
54
54
  for (const term of queryTerms) {
@@ -67,17 +67,17 @@ function bm25Rank(queryText: string, chunks: any[], { k = 5 }: { k?: number } =
67
67
  /** Registry-derived document graph: every `@file.md` import inside a corpus document is an edge.
68
68
  * Guidance's own path-anchor rule makes these resolvable against the corpus root, which turns the
69
69
  * content itself into the knowledge graph — no LLM extraction, no external store. */
70
- function buildImportGraph(corpusDir: string, { fsImpl = fs }: { fsImpl?: any } = {}): Map<string, string[]> {
71
- const edges = new Map<string, string[]>();
70
+ function buildImportGraph(corpusDir , { fsImpl = fs } = {}) {
71
+ const edges = new Map ();
72
72
  try { fsImpl.readdirSync(corpusDir); } catch { return edges; }
73
- const walk = (dir: string, rel: string) => {
73
+ const walk = (dir , rel ) => {
74
74
  for (const entry of fsImpl.readdirSync(dir, { withFileTypes: true })) {
75
75
  const abs = path.join(dir, entry.name);
76
76
  const relPath = rel ? `${rel}/${entry.name}` : entry.name;
77
77
  if (entry.isDirectory()) { walk(abs, relPath); continue; }
78
78
  if (!entry.name.toLowerCase().endsWith('.md')) continue;
79
79
  const text = (() => { try { return fsImpl.readFileSync(abs, 'utf8'); } catch { return ''; } })();
80
- const targets = new Set<string>();
80
+ const targets = new Set ();
81
81
  for (const match of text.matchAll(/(?:^|\s)@([^\s`]+\.md)\b/g)) {
82
82
  const target = path.posix.normalize(match[1].replace(/^\.\//, ''));
83
83
  if (target.startsWith('..') || path.isAbsolute(target)) continue;
@@ -93,17 +93,17 @@ function buildImportGraph(corpusDir: string, { fsImpl = fs }: { fsImpl?: any } =
93
93
  /** Expand BM25 hits along import edges (1 hop): a linked document is "what to read next" for the
94
94
  * question that surfaced its anchor. Graph results are capped separately and never displace
95
95
  * lexical hits — they extend the answer instead of reranking it. */
96
- function expandViaGraph(hits: any[], chunks: any[], graph: Map<string, string[]>, { maxExtra = 3 }: { maxExtra?: number } = {}): any[] {
97
- const hitPaths = new Set(hits.map((h: any) => h.path));
98
- const seen = new Set<string>();
99
- const extras: any[] = [];
96
+ function expandViaGraph(hits , chunks , graph , { maxExtra = 3 } = {}) {
97
+ const hitPaths = new Set(hits.map((h ) => h.path));
98
+ const seen = new Set ();
99
+ const extras = [];
100
100
  for (const hit of hits) {
101
101
  for (const target of graph.get(hit.path) ?? []) {
102
102
  if (hitPaths.has(target) || seen.has(target)) continue;
103
103
  seen.add(target);
104
- const linkedChunks = chunks.filter((c: any) => c.path === target);
104
+ const linkedChunks = chunks.filter((c ) => c.path === target);
105
105
  if (!linkedChunks.length) continue;
106
- const best = linkedChunks.reduce((a: any, b: any) => (b.text.length > a.text.length ? b : a));
106
+ const best = linkedChunks.reduce((a , b ) => (b.text.length > a.text.length ? b : a));
107
107
  extras.push({
108
108
  path: best.path,
109
109
  title: best.title,
@@ -119,18 +119,18 @@ function expandViaGraph(hits: any[], chunks: any[], graph: Map<string, string[]>
119
119
 
120
120
  /** Ensure the on-disk index matches the corpus, rebuilding only what changed, then rank.
121
121
  * Returns {results, rebuilt}. A missing corpus is the caller's usage problem, thrown loudly. */
122
- function searchGuidance({ corpusDir, indexDir, query, k = 5, fsImpl = fs }: { corpusDir: string; indexDir: string; query: string; k?: number; fsImpl?: any } = {} as any): any {
122
+ function searchGuidance({ corpusDir, indexDir, query, k = 5, fsImpl = fs } = {} ) {
123
123
  if (!fsImpl.existsSync(corpusDir)) {
124
124
  throw new Error(`No guidance tree found at '${corpusDir}' — run \`doflow install\` first`);
125
125
  }
126
- let rebuiltFiles: string[] | null = null;
126
+ let rebuiltFiles = null;
127
127
  if (!isFresh({ corpusDir, indexDir, fsImpl })) {
128
128
  const build = buildIndex({ corpusDir, indexDir, fsImpl });
129
129
  rebuiltFiles = build.rebuilt;
130
130
  }
131
131
  const loaded = loadIndex({ indexDir, fsImpl });
132
132
  if (!loaded) throw new Error(`Index at '${indexDir}' is unreadable after rebuild`);
133
- const ranked = bm25Rank(query, loaded.chunks, { k }).map((hit: any) => ({
133
+ const ranked = bm25Rank(query, loaded.chunks, { k }).map((hit ) => ({
134
134
  path: hit.path,
135
135
  title: hit.title,
136
136
  score: Number(hit.score.toFixed(4)),
@@ -145,7 +145,7 @@ function searchGuidance({ corpusDir, indexDir, query, k = 5, fsImpl = fs }: { co
145
145
  * code from this install, knowledge from the project being worked on. The `.doflow` root is
146
146
  * $DOFLOW_CONFIG_DIR, else the nearest one above `stateRoot` that holds a guidance tree, else the
147
147
  * home install; the index is kept beside the corpus chosen. */
148
- function handleRetrieveCommand({ query, top, json = false, stateRoot }: { query?: any; top?: any; json?: boolean; stateRoot?: any } = {}): any {
148
+ function handleRetrieveCommand({ query, top, json = false, stateRoot } = {}) {
149
149
  const { configDir } = resolveRunsLocation({ start: stateRoot, containing: 'guidance' });
150
150
  const corpusDir = path.join(configDir, 'guidance');
151
151
  const indexDir = path.join(configDir, 'index', 'guidance');
@@ -161,13 +161,13 @@ function handleRetrieveCommand({ query, top, json = false, stateRoot }: { query?
161
161
  } else if (!results.length) {
162
162
  console.log('[OK] No matching guidance found.');
163
163
  } else {
164
- results.forEach((result: any, i: number) => {
164
+ results.forEach((result , i ) => {
165
165
  console.log(`${i + 1}. [${result.score}] ${result.path}${result.title ? ` — ${result.title}` : ''}`);
166
166
  console.log(` ${result.snippet}`);
167
167
  });
168
168
  }
169
169
  return finishRuntime(0);
170
- } catch (error: any) {
170
+ } catch (error ) {
171
171
  captureCaught(error, 'retrieve', 1);
172
172
  console.error(`[ERROR] retrieve: ${error.message}`);
173
173
  return finishRuntime(1);
@@ -178,7 +178,7 @@ const {
178
178
  reciprocalRankFusion,
179
179
  normalizeLocator,
180
180
  fuseHybridResults,
181
- } = require('./hybrid.ts');
181
+ } = require('./hybrid.js');
182
182
 
183
183
  module.exports = {
184
184
  bm25Rank,
@@ -4,7 +4,7 @@
4
4
 
5
5
  const fs = require('node:fs');
6
6
  const path = require('node:path');
7
- const { finishRuntime, usageError } = require('./cli-result.ts');
7
+ const { finishRuntime, usageError } = require('./cli-result.js');
8
8
 
9
9
  /**
10
10
  * Reports DoFlow's own process vocabulary appearing in files that ship to people who never used
@@ -44,7 +44,7 @@ const DEFAULT_EXCLUDED_SEGMENTS = ['agent-docs'];
44
44
  // here as an exported Set that nothing read, including no test: a second place to keep the list
45
45
  // correct, with nothing to notice when the two disagreed.
46
46
 
47
- function isExcluded(relPath: string, excludedSegments: string[]): boolean {
47
+ function isExcluded(relPath , excludedSegments ) {
48
48
  const segments = relPath.split(path.sep);
49
49
  return excludedSegments.some((seg) => segments.includes(seg));
50
50
  }
@@ -58,7 +58,7 @@ function isExcluded(relPath: string, excludedSegments: string[]): boolean {
58
58
  *
59
59
  * @returns {{relative: string, content: string}|{relative: string, reason: string}}
60
60
  */
61
- function readScannable(target: string, root: string, excluded: string[], impl: any): { relative: string; content?: string; reason?: string } {
61
+ function readScannable(target , root , excluded , impl ) {
62
62
  const absolute = path.isAbsolute(target) ? target : path.join(root, target);
63
63
  const relative = path.relative(root, absolute);
64
64
 
@@ -77,8 +77,8 @@ function readScannable(target: string, root: string, excluded: string[], impl: a
77
77
  }
78
78
 
79
79
  /** Every pattern match in one file's lines, as finding records. */
80
- function findLeaksInLines(lines: string[], relative: string): any[] {
81
- const findings: any[] = [];
80
+ function findLeaksInLines(lines , relative ) {
81
+ const findings = [];
82
82
  for (let i = 0; i < lines.length; i += 1) {
83
83
  for (const rule of LEAK_PATTERNS) {
84
84
  const match = lines[i].match(rule.pattern);
@@ -104,14 +104,14 @@ function findLeaksInLines(lines: string[], relative: string): any[] {
104
104
  * @param {Object} [options.fsImpl] injectable fs, for tests
105
105
  * @returns {{findings: Array, scanned: string[], unscanned: Array}}
106
106
  */
107
- function scanPaths({ paths: targets, repoRoot, excludedSegments, fsImpl }: any = {}): { findings: any[]; scanned: string[]; unscanned: any[] } {
107
+ function scanPaths({ paths: targets, repoRoot, excludedSegments, fsImpl } = {}) {
108
108
  const impl = fsImpl || fs;
109
109
  const root = repoRoot || process.cwd();
110
110
  const excluded = excludedSegments || DEFAULT_EXCLUDED_SEGMENTS;
111
111
 
112
- const findings: any[] = [];
113
- const scanned: string[] = [];
114
- const unscanned: any[] = [];
112
+ const findings = [];
113
+ const scanned = [];
114
+ const unscanned = [];
115
115
 
116
116
  for (const target of targets || []) {
117
117
  if (typeof target !== 'string' || target.trim() === '') continue;
@@ -123,7 +123,7 @@ function scanPaths({ paths: targets, repoRoot, excludedSegments, fsImpl }: any =
123
123
  }
124
124
 
125
125
  scanned.push(read.relative);
126
- findings.push(...findLeaksInLines((read.content as string).split('\n'), read.relative));
126
+ findings.push(...findLeaksInLines((read.content ).split('\n'), read.relative));
127
127
  }
128
128
 
129
129
  return { findings, scanned, unscanned };
@@ -140,14 +140,14 @@ function scanPaths({ paths: targets, repoRoot, excludedSegments, fsImpl }: any =
140
140
  * @param {string} [options.repoRoot]
141
141
  * @returns {number} exit code
142
142
  */
143
- function handleLeakScanCommand({ paths: targets, exclude, json = false, repoRoot }: any = {}): number {
143
+ function handleLeakScanCommand({ paths: targets, exclude, json = false, repoRoot } = {}) {
144
144
  if (!Array.isArray(targets) || targets.length === 0) {
145
145
  return usageError('leak-scan', '--path is required (repeatable): the files to scan', json);
146
146
  }
147
147
 
148
148
  // `--exclude` extends the built-in artifact-directory exclusion rather than replacing it: a
149
149
  // caller narrowing the scan should not be able to accidentally widen it back over agent-docs/.
150
- const extra = Array.isArray(exclude) ? exclude.filter((e: any) => typeof e === 'string' && e.trim() !== '') : [];
150
+ const extra = Array.isArray(exclude) ? exclude.filter((e ) => typeof e === 'string' && e.trim() !== '') : [];
151
151
  const excludedSegments = [...DEFAULT_EXCLUDED_SEGMENTS, ...extra];
152
152
 
153
153
  const result = scanPaths({ paths: targets, repoRoot, excludedSegments });