@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
@@ -5,25 +5,25 @@
5
5
  const fs = require('node:fs');
6
6
  const path = require('node:path');
7
7
  const crypto = require('node:crypto');
8
- const { resolveStorePath } = require('../storage/roots.ts');
8
+ const { resolveStorePath } = require('../storage/roots.js');
9
9
 
10
10
  const RETAINED_DAYS = 90;
11
11
  const PARTITION_NAME = /^\d{4}-\d{2}-\d{2}\.jsonl$/;
12
12
 
13
- function timestamp(now: any = () => new Date()): string | null {
13
+ function timestamp(now = () => new Date()) {
14
14
  const value = typeof now === 'function' ? now() : now;
15
15
  const date = new Date(value);
16
16
  return Number.isNaN(date.getTime()) ? null : date.toISOString();
17
17
  }
18
18
 
19
- function selectedStore(roots: any, requestedStore?: string): { store: string; root: string } | null {
19
+ function selectedStore(roots , requestedStore ) {
20
20
  if (requestedStore && roots?.[requestedStore]) return { store: requestedStore, root: roots[requestedStore] };
21
21
  if (roots?.['project-state']) return { store: 'project-state', root: roots['project-state'] };
22
22
  if (roots?.['user-state']) return { store: 'user-state', root: roots['user-state'] };
23
23
  return null;
24
24
  }
25
25
 
26
- function appendLine({ roots, at, line, fsImpl = fs, store }: any): { file: string; store: string } | null {
26
+ function appendLine({ roots, at, line, fsImpl = fs, store } ) {
27
27
  try {
28
28
  const selected = selectedStore(roots, store);
29
29
  if (!selected) return null;
@@ -31,7 +31,7 @@ function appendLine({ roots, at, line, fsImpl = fs, store }: any): { file: strin
31
31
  if (!directory) return null;
32
32
  const file = path.join(directory, `${at.slice(0, 10)}.jsonl`);
33
33
  try { if (fsImpl.lstatSync(file).isSymbolicLink()) return null; }
34
- catch (error: any) { if (error.code !== 'ENOENT') return null; }
34
+ catch (error ) { if (error.code !== 'ENOENT') return null; }
35
35
  fsImpl.mkdirSync(path.dirname(file), { recursive: true });
36
36
  fsImpl.appendFileSync(file, `${JSON.stringify(line)}\n`, 'utf8');
37
37
  return { file, store: selected.store };
@@ -43,7 +43,7 @@ function appendLine({ roots, at, line, fsImpl = fs, store }: any): { file: strin
43
43
  function appendPick({
44
44
  roots, now = () => new Date(), fsImpl = fs, kind, answer, question,
45
45
  staticAnswer = null, provider = null, model = null, state, caller, taskId = null, durationMs = 0,
46
- }: any = {}): { pickId: string; file: string; store: string } | null {
46
+ } = {}) {
47
47
  try {
48
48
  if (typeof state !== 'string' || !answer || !question) return null;
49
49
  const at = timestamp(now);
@@ -54,7 +54,7 @@ function appendPick({
54
54
  : question.type === 'score' ? [...(question.criteria || [])] : ['no', 'yes'];
55
55
  const instructions = kind === 'adhoc' && typeof question.instructions === 'string'
56
56
  ? question.instructions.slice(0, 500) : null;
57
- const line: any = {
57
+ const line = {
58
58
  schema: 1,
59
59
  type: 'pick',
60
60
  pickId,
@@ -90,7 +90,7 @@ function appendPick({
90
90
  }
91
91
  }
92
92
 
93
- function appendMiss({ roots, now = () => new Date(), fsImpl = fs, kind, caller, reason, model = null, durationMs = 0 }: any = {}): any {
93
+ function appendMiss({ roots, now = () => new Date(), fsImpl = fs, kind, caller, reason, model = null, durationMs = 0 } = {}) {
94
94
  try {
95
95
  const at = timestamp(now);
96
96
  if (!at) return null;
@@ -103,7 +103,7 @@ function appendMiss({ roots, now = () => new Date(), fsImpl = fs, kind, caller,
103
103
  } catch { return null; }
104
104
  }
105
105
 
106
- function appendOutcome({ roots, now = () => new Date(), fsImpl = fs, pickId, actual, source, store }: any = {}): any {
106
+ function appendOutcome({ roots, now = () => new Date(), fsImpl = fs, pickId, actual, source, store } = {}) {
107
107
  try {
108
108
  const at = timestamp(now);
109
109
  if (!at) return null;
@@ -112,36 +112,36 @@ function appendOutcome({ roots, now = () => new Date(), fsImpl = fs, pickId, act
112
112
  } catch { return null; }
113
113
  }
114
114
 
115
- function cutoffDate(now: any, maxAgeDays: number = RETAINED_DAYS): string | null {
115
+ function cutoffDate(now , maxAgeDays = RETAINED_DAYS) {
116
116
  const at = timestamp(now);
117
117
  if (!at) return null;
118
118
  const cutoff = new Date(Date.parse(at) - maxAgeDays * 24 * 60 * 60 * 1000);
119
119
  return cutoff.toISOString().slice(0, 10);
120
120
  }
121
121
 
122
- function partitionFiles(root: string | undefined, cutoff: string, fsImpl: any): any[] {
122
+ function partitionFiles(root , cutoff , fsImpl ) {
123
123
  if (!root) return [];
124
124
  const directory = path.join(root, 'advice', 'picks');
125
125
  try {
126
126
  return fsImpl.readdirSync(directory)
127
- .filter((name: string) => PARTITION_NAME.test(name) && name.slice(0, 10) >= cutoff)
127
+ .filter((name ) => PARTITION_NAME.test(name) && name.slice(0, 10) >= cutoff)
128
128
  .sort()
129
- .map((name: string) => path.join(directory, name));
130
- } catch (error: any) {
129
+ .map((name ) => path.join(directory, name));
130
+ } catch (error ) {
131
131
  if (error?.code === 'ENOENT' || error?.code === 'ENOTDIR') return [];
132
132
  return [{ unreadable: true, file: directory }];
133
133
  }
134
134
  }
135
135
 
136
- function readWindow({ roots, now = () => new Date(), maxAgeDays = RETAINED_DAYS, fsImpl = fs }: any = {}): { records: any[]; unreadable: number } {
136
+ function readWindow({ roots, now = () => new Date(), maxAgeDays = RETAINED_DAYS, fsImpl = fs } = {}) {
137
137
  const cutoff = cutoffDate(now, maxAgeDays);
138
138
  if (!cutoff) return { records: [], unreadable: 0 };
139
- const records: any[] = [];
139
+ const records = [];
140
140
  let unreadable = 0;
141
141
  for (const store of ['project-state', 'user-state']) {
142
142
  for (const item of partitionFiles(roots?.[store], cutoff, fsImpl)) {
143
143
  if (typeof item !== 'string') { unreadable += 1; continue; }
144
- let contents: string;
144
+ let contents ;
145
145
  try { contents = fsImpl.readFileSync(item, 'utf8'); } catch { unreadable += 1; continue; }
146
146
  for (const line of contents.split(/\r?\n/)) {
147
147
  if (!line.trim()) continue;
@@ -156,10 +156,10 @@ function readWindow({ roots, now = () => new Date(), maxAgeDays = RETAINED_DAYS,
156
156
  return { records, unreadable };
157
157
  }
158
158
 
159
- function findPick({ pickId, roots, now = () => new Date(), fsImpl = fs }: any = {}): any {
159
+ function findPick({ pickId, roots, now = () => new Date(), fsImpl = fs } = {}) {
160
160
  if (typeof pickId !== 'string') return null;
161
161
  const window = readWindow({ roots, now, fsImpl });
162
- const found = window.records.find((entry: any) => entry.record.type === 'pick' && entry.record.pickId === pickId);
162
+ const found = window.records.find((entry ) => entry.record.type === 'pick' && entry.record.pickId === pickId);
163
163
  return found ? { pick: found.record, file: found.file, store: found.store } : null;
164
164
  }
165
165
 
@@ -4,28 +4,28 @@
4
4
 
5
5
  const fs = require('node:fs');
6
6
  const path = require('node:path');
7
- const { REPO_ROOT } = require('../../helper/repo-root.ts');
7
+ const { REPO_ROOT } = require('../../helper/repo-root.js');
8
8
 
9
9
  const ADVICE_FILE = 'core/registry/advice.json';
10
10
  const MODELS_FILE = 'core/registry/models.json';
11
11
  const ADAPTER_DIR = 'src/runtime/advice/providers';
12
12
  const TIER_KIND = 'tier';
13
13
  const LIMIT_FIELDS = ['maxStateBytes', 'maxBodyBytes', 'minQuestions', 'maxQuestions', 'minOptions', 'maxOptions'];
14
- const BAND_FIELDS: Record<string, string[]> = {
14
+ const BAND_FIELDS = {
15
15
  choice: ['clearAt', 'splitWithin'],
16
16
  yesno: ['clearAbove', 'clearBelow', 'splitFrom', 'splitTo'],
17
17
  };
18
18
 
19
- function isObject(value: any): boolean {
19
+ function isObject(value ) {
20
20
  return value !== null && typeof value === 'object' && !Array.isArray(value);
21
21
  }
22
22
 
23
- function addError(errors: string[], key: string, message: string): void {
23
+ function addError(errors , key , message ) {
24
24
  errors.push(`${key} ${message}`);
25
25
  }
26
26
 
27
- function validateAdviceRegistry(registry: any, { repoRoot = REPO_ROOT, models, fsImpl = fs }: any = {}): { ok: boolean; errors: string[] } {
28
- const errors: string[] = [];
27
+ function validateAdviceRegistry(registry , { repoRoot = REPO_ROOT, models, fsImpl = fs } = {}) {
28
+ const errors = [];
29
29
  if (!isObject(registry)) return { ok: false, errors: ['registry must be an object'] };
30
30
 
31
31
  if (registry.version !== 1) addError(errors, 'version', 'must be 1');
@@ -80,7 +80,7 @@ function validateAdviceRegistry(registry: any, { repoRoot = REPO_ROOT, models, f
80
80
  }
81
81
  }
82
82
  const yesno = strength.yesno;
83
- if (isObject(yesno) && ['clearBelow', 'splitFrom', 'splitTo', 'clearAbove'].every((field: string) => typeof yesno[field] === 'number')) {
83
+ if (isObject(yesno) && ['clearBelow', 'splitFrom', 'splitTo', 'clearAbove'].every((field ) => typeof yesno[field] === 'number')) {
84
84
  if (!(yesno.clearBelow < yesno.splitFrom && yesno.splitFrom < yesno.splitTo && yesno.splitTo < yesno.clearAbove)) {
85
85
  addError(errors, 'strength.yesno', 'bands must satisfy clearBelow < splitFrom < splitTo < clearAbove');
86
86
  }
@@ -89,15 +89,15 @@ function validateAdviceRegistry(registry: any, { repoRoot = REPO_ROOT, models, f
89
89
 
90
90
  if (!models) {
91
91
  try { models = JSON.parse(fsImpl.readFileSync(path.join(repoRoot, MODELS_FILE), 'utf8')); }
92
- catch (error: any) { addError(errors, MODELS_FILE, `could not be loaded: ${error.message}`); }
92
+ catch (error ) { addError(errors, MODELS_FILE, `could not be loaded: ${error.message}`); }
93
93
  }
94
- const modelProviders = Array.isArray(models?.providers) ? new Set(models.providers.map((provider: any) => provider?.id).filter((id: any) => typeof id === 'string')) : new Set();
94
+ const modelProviders = Array.isArray(models?.providers) ? new Set(models.providers.map((provider ) => provider?.id).filter((id ) => typeof id === 'string')) : new Set();
95
95
 
96
96
  if (!Array.isArray(registry.providers) || registry.providers.length === 0) {
97
97
  addError(errors, 'providers', 'must be a non-empty array');
98
98
  } else {
99
99
  const adapterRoot = path.resolve(repoRoot, ADAPTER_DIR);
100
- registry.providers.forEach((provider: any, index: number) => {
100
+ registry.providers.forEach((provider , index ) => {
101
101
  const base = `providers[${index}]`;
102
102
  if (!isObject(provider)) { addError(errors, base, 'must be an object'); return; }
103
103
  for (const field of ['id', 'adapter', 'modelProvider', 'defaultEndpoint', 'route', 'minVersion', 'capability']) {
@@ -132,17 +132,17 @@ function validateAdviceRegistry(registry: any, { repoRoot = REPO_ROOT, models, f
132
132
  if (!['choice', 'yesno'].includes(kind.type)) addError(errors, `${base}.type`, 'must be choice or yesno');
133
133
  if (typeof kind.instructions !== 'string' || !kind.instructions.trim()) addError(errors, `${base}.instructions`, 'must be a non-empty string');
134
134
  if (Object.hasOwn(kind, 'criteria') === Object.hasOwn(kind, 'criteriaFrom')) addError(errors, base, 'must have exactly one of criteria or criteriaFrom');
135
- if (Object.hasOwn(kind, 'criteria') && (!isObject(kind.criteria) || Object.values(kind.criteria).some((value: any) => typeof value !== 'string' || !value.trim()))) {
135
+ if (Object.hasOwn(kind, 'criteria') && (!isObject(kind.criteria) || Object.values(kind.criteria).some((value ) => typeof value !== 'string' || !value.trim()))) {
136
136
  addError(errors, `${base}.criteria`, 'must map option ids to non-empty descriptions');
137
137
  }
138
138
  if (Object.hasOwn(kind, 'criteriaFrom') && (typeof kind.criteriaFrom !== 'string' || !kind.criteriaFrom.trim())) {
139
139
  addError(errors, `${base}.criteriaFrom`, 'must be a non-empty string');
140
140
  }
141
141
  if (typeof kind.staticFrom !== 'string') addError(errors, `${base}.staticFrom`, 'must be a string');
142
- if (!Array.isArray(kind.askedBy) || kind.askedBy.some((caller: any) => typeof caller !== 'string')) addError(errors, `${base}.askedBy`, 'must be an array of strings');
142
+ if (!Array.isArray(kind.askedBy) || kind.askedBy.some((caller ) => typeof caller !== 'string')) addError(errors, `${base}.askedBy`, 'must be an array of strings');
143
143
  }
144
144
 
145
- const tier = registry.kinds.find((kind: any) => kind?.id === TIER_KIND);
145
+ const tier = registry.kinds.find((kind ) => kind?.id === TIER_KIND);
146
146
  const dispatchTiers = models?.dispatchTiers?.tiers;
147
147
  if (!tier || !isObject(tier.criteria) || !Array.isArray(dispatchTiers)
148
148
  || JSON.stringify(Object.keys(tier.criteria)) !== JSON.stringify(dispatchTiers)) {
@@ -153,13 +153,13 @@ function validateAdviceRegistry(registry: any, { repoRoot = REPO_ROOT, models, f
153
153
  return { ok: errors.length === 0, errors };
154
154
  }
155
155
 
156
- function loadAdviceRegistry({ repoRoot = REPO_ROOT, file, fsImpl = fs }: any = {}): { ok: boolean; registry?: any; reason?: string; detail?: string } {
156
+ function loadAdviceRegistry({ repoRoot = REPO_ROOT, file, fsImpl = fs } = {}) {
157
157
  const root = path.resolve(repoRoot);
158
158
  const target = file || path.join(root, ADVICE_FILE);
159
- let registry: any;
159
+ let registry ;
160
160
  try {
161
161
  registry = JSON.parse(fsImpl.readFileSync(target, 'utf8'));
162
- } catch (error: any) {
162
+ } catch (error ) {
163
163
  return { ok: false, reason: 'config-invalid', detail: `${target}: ${error.message}` };
164
164
  }
165
165
  const validation = validateAdviceRegistry(registry, { repoRoot: root, fsImpl });
@@ -2,7 +2,7 @@
2
2
 
3
3
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
4
 
5
- function strengthOf(answer: any, bands: any): { word: string; between: string[] | null } {
5
+ function strengthOf(answer , bands ) {
6
6
  const type = answer?.type;
7
7
  const thresholds = bands?.[type] || bands;
8
8
  const probabilities = answer?.probabilities;
@@ -11,9 +11,9 @@ function strengthOf(answer: any, bands: any): { word: string; between: string[]
11
11
  }
12
12
 
13
13
  if (type === 'choice') {
14
- const ordered: any[] = Object.entries(probabilities)
14
+ const ordered = Object.entries(probabilities)
15
15
  .filter(([, probability]) => typeof probability === 'number' && Number.isFinite(probability))
16
- .sort((left: any, right: any) => right[1] - left[1]);
16
+ .sort((left , right ) => right[1] - left[1]);
17
17
  if (!ordered.length) return { word: 'leaning', between: null };
18
18
  if (ordered[0][1] >= thresholds.clearAt) return { word: 'clear', between: null };
19
19
  if (ordered.length > 1) {
@@ -30,9 +30,9 @@ function strengthOf(answer: any, bands: any): { word: string; between: string[]
30
30
  const choice = bands?.choice;
31
31
  const criteria = answer.criteria;
32
32
  if (!choice || !Array.isArray(criteria)) return { word: 'leaning', between: null };
33
- const ordered = criteria.map((criterion: any, index: number) => [criterion, probabilities[String(index)]])
34
- .filter(([, probability]: any) => typeof probability === 'number' && Number.isFinite(probability))
35
- .sort((left: any, right: any) => right[1] - left[1]);
33
+ const ordered = criteria.map((criterion , index ) => [criterion, probabilities[String(index)]])
34
+ .filter(([, probability] ) => typeof probability === 'number' && Number.isFinite(probability))
35
+ .sort((left , right ) => right[1] - left[1]);
36
36
  if (!ordered.length) return { word: 'leaning', between: null };
37
37
  if (ordered[0][1] >= choice.clearAt) return { word: 'clear', between: null };
38
38
  if (ordered.length > 1) {
@@ -56,7 +56,7 @@ function strengthOf(answer: any, bands: any): { word: string; between: string[]
56
56
  return { word: 'leaning', between: null };
57
57
  }
58
58
 
59
- function strengthWords(strength: any): string {
59
+ function strengthWords(strength ) {
60
60
  if (strength?.word === 'split' && Array.isArray(strength.between) && strength.between.length === 2) {
61
61
  return `split between ${strength.between[0]} and ${strength.between[1]}`;
62
62
  }
@@ -12,53 +12,53 @@
12
12
  * those inputs and prints the block; it writes nothing.
13
13
  */
14
14
 
15
- const { REPO_ROOT } = require('../helper/repo-root.ts');
16
- const { loadRegistry } = require('../registry/index.ts');
17
- const { CapabilityRouter } = require('./capability-router.ts');
18
- const { probeProviders, HEALTHY, UNVERIFIED } = require('./health.ts');
19
- const { mcpReach } = require('./mcp-reach.ts');
20
- const { WorkflowOrchestrator } = require('./workflow-orchestrator.ts');
21
- const { resolveActiveFeature } = require('./feature-resolve.ts');
22
- const { finishRuntime, usageError, captureCaught } = require('./cli-result.ts');
15
+ const { REPO_ROOT } = require('../helper/repo-root.js');
16
+ const { loadRegistry } = require('../registry/index.js');
17
+ const { CapabilityRouter } = require('./capability-router.js');
18
+ const { probeProviders, HEALTHY, UNVERIFIED } = require('./health.js');
19
+ const { mcpReach } = require('./mcp-reach.js');
20
+ const { WorkflowOrchestrator } = require('./workflow-orchestrator.js');
21
+ const { resolveActiveFeature } = require('./feature-resolve.js');
22
+ const { finishRuntime, usageError, captureCaught } = require('./cli-result.js');
23
23
  const fs = require('node:fs');
24
24
  const path = require('node:path');
25
- const { loadAdviceRegistry } = require('./advice/registry.ts');
26
- const { loadStorageRegistry } = require('./storage/registry.ts');
27
- const { resolveRoots } = require('./storage/roots.ts');
28
- const { resolveSetting } = require('./advice/config.ts');
29
- const { materializeKind } = require('./advice/kinds.ts');
30
- const { createAdviceClient } = require('./advice/client.ts');
31
- const { strengthWords } = require('./advice/strength.ts');
25
+ const { loadAdviceRegistry } = require('./advice/registry.js');
26
+ const { loadStorageRegistry } = require('./storage/registry.js');
27
+ const { resolveRoots } = require('./storage/roots.js');
28
+ const { resolveSetting } = require('./advice/config.js');
29
+ const { materializeKind } = require('./advice/kinds.js');
30
+ const { createAdviceClient } = require('./advice/client.js');
31
+ const { strengthWords } = require('./advice/strength.js');
32
32
 
33
33
  const SCHEMA = 1;
34
34
  const REACHABLE = new Set(['selected', 'configured']);
35
35
 
36
36
  /** The state of `server` on a harness: selected or configured on any of its scopes wins; absent
37
37
  * only when every scope says so from a complete view (IC-013); else unknown. */
38
- function stateOn(reach: any, harnessId: any, server: any) {
39
- const rows = (reach?.harnesses || []).filter((row: any) => row.id === harnessId);
40
- if (rows.some((row: any) => row.servers[server] === 'selected')) return 'selected';
41
- if (rows.some((row: any) => row.servers[server] === 'configured')) return 'configured';
42
- const states = rows.map((row: any) => row.servers[server] ?? 'unknown');
38
+ function stateOn(reach , harnessId , server ) {
39
+ const rows = (reach?.harnesses || []).filter((row ) => row.id === harnessId);
40
+ if (rows.some((row ) => row.servers[server] === 'selected')) return 'selected';
41
+ if (rows.some((row ) => row.servers[server] === 'configured')) return 'configured';
42
+ const states = rows.map((row ) => row.servers[server] ?? 'unknown');
43
43
  return states.length && !states.includes('unknown') ? states[0] : 'unknown';
44
44
  }
45
45
 
46
46
  /** Whether `server` is selected or configured on the target harness, or on any harness without one. */
47
- function hasServer(reach: any, harnessId: any, server: any) {
47
+ function hasServer(reach , harnessId , server ) {
48
48
  if (!reach) return false;
49
- return harnessId ? REACHABLE.has(stateOn(reach, harnessId, server)) : reach.harnesses.some((row: any) => REACHABLE.has(row.servers[server]));
49
+ return harnessId ? REACHABLE.has(stateOn(reach, harnessId, server)) : reach.harnesses.some((row ) => REACHABLE.has(row.servers[server]));
50
50
  }
51
51
 
52
52
  /** The target harness: a registry id named by the caller, else the one harness installed at the
53
53
  * project scope (the global scope when the project has none), else none. */
54
- function chooseTarget({ registry, reach, harness, missing }: any) {
54
+ function chooseTarget({ registry, reach, harness, missing } ) {
55
55
  if (harness) {
56
- if (registry.harnesses.some((item: any) => item.id === harness)) return harness;
56
+ if (registry.harnesses.some((item ) => item.id === harness)) return harness;
57
57
  missing.push(`harness '${harness}' is not a registry harness; ignored`);
58
58
  }
59
59
  const rows = reach?.harnesses || [];
60
60
  for (const scope of ['project', 'global']) {
61
- const ids = [...new Set(rows.filter((row: any) => row.scope === scope).map((row: any) => row.id))];
61
+ const ids = [...new Set(rows.filter((row ) => row.scope === scope).map((row ) => row.id))];
62
62
  if (ids.length) return ids.length === 1 ? ids[0] : null;
63
63
  }
64
64
  return null;
@@ -66,7 +66,7 @@ function chooseTarget({ registry, reach, harness, missing }: any) {
66
66
 
67
67
  /** Tier for a dispatch: the task line's tier when valid, else the owner's, else the default (IC-004).
68
68
  * A registry without `dispatchTiers` (the key is optional) gives `standard` with a note. */
69
- function resolveTier({ dispatchTiers, owner, tier, missing }: any) {
69
+ function resolveTier({ dispatchTiers, owner, tier, missing } ) {
70
70
  if (!dispatchTiers) {
71
71
  missing.push('models.json has no dispatchTiers; tier standard assumed');
72
72
  return { tier: 'standard', source: 'default', note: 'models.json has no dispatchTiers' };
@@ -81,14 +81,14 @@ function resolveTier({ dispatchTiers, owner, tier, missing }: any) {
81
81
  }
82
82
 
83
83
  /** The first provider of a capability whose probe status is `status`, in registry order, or null. */
84
- function firstWith(router: any, capabilityId: any, probes: any, status: any) {
85
- return (router.capabilities[capabilityId]?.providers || []).find((provider: any) => probes[provider.id]?.status === status) || null;
84
+ function firstWith(router , capabilityId , probes , status ) {
85
+ return (router.capabilities[capabilityId]?.providers || []).find((provider ) => probes[provider.id]?.status === status) || null;
86
86
  }
87
87
 
88
88
  /** What answers one route intent on this machine: a healthy provider of the primary capability,
89
89
  * else of the route's fallback capabilities in order; failing those, a provider that has no probe
90
90
  * (UNVERIFIED) in the same order; else nothing. An unhealthy provider is never chosen. */
91
- function resolveRoute(router: any, route: any, probes: any) {
91
+ function resolveRoute(router , route , probes ) {
92
92
  const chain = [route.capability, ...(route.fallback || [])];
93
93
  for (const status of [HEALTHY, UNVERIFIED]) {
94
94
  for (const capability of chain) {
@@ -101,8 +101,8 @@ function resolveRoute(router: any, route: any, probes: any) {
101
101
  return { capability: route.capability, provider: null, status: 'NONE', via: null };
102
102
  }
103
103
 
104
- const cell = (text: any) => String(text).replace(/\|/g, '\\|').replace(/\s+/g, ' ');
105
- const trigger = (server: any) => server.trigger.replace(/\.$/, '');
104
+ const cell = (text ) => String(text).replace(/\|/g, '\\|').replace(/\s+/g, ' ');
105
+ const trigger = (server ) => server.trigger.replace(/\.$/, '');
106
106
 
107
107
  /**
108
108
  * @param {Object} input
@@ -117,18 +117,18 @@ const trigger = (server: any) => server.trigger.replace(/\.$/, '');
117
117
  * @param {{feature:?string, runTaskId:?string, stageId:?string, skill:?string}|null} [input.stage]
118
118
  * @returns {{markdown: string, record: Object}} the record is IC-018 without `tasks`
119
119
  */
120
- function renderBriefTools({ registry, router, probes, reach, owner, tier, harness, headingLevel = 2, stage = null }: any) {
121
- const missing: any = [];
120
+ function renderBriefTools({ registry, router, probes, reach, owner, tier, harness, headingLevel = 2, stage = null } ) {
121
+ const missing = [];
122
122
  const hashes = '#'.repeat(Number(headingLevel) === 3 ? 3 : 2);
123
123
  const target = chooseTarget({ registry, reach, harness, missing });
124
- const targetHarness = target ? registry.harnesses.find((item: any) => item.id === target) : null;
124
+ const targetHarness = target ? registry.harnesses.find((item ) => item.id === target) : null;
125
125
  const resolved = resolveTier({ dispatchTiers: registry.dispatchTiers, owner, tier, missing });
126
126
  const sourceText = resolved.source === 'owner' ? `owner ${owner}`
127
127
  : resolved.source === 'task' ? 'task line' : `default; ${resolved.note || `owner ${owner} has no tier`}`;
128
128
 
129
129
  const tools = [];
130
130
  const rows = [];
131
- for (const [intent, route] of Object.entries<any>(router.routes)) {
131
+ for (const [intent, route] of Object.entries (router.routes)) {
132
132
  const found = resolveRoute(router, route, probes);
133
133
  if (!found.provider) {
134
134
  rows.push(`| ${cell(intent)} | no healthy provider and no fallback | - |`);
@@ -163,9 +163,9 @@ function renderBriefTools({ registry, router, probes, reach, owner, tier, harnes
163
163
 
164
164
  const skill = stage?.skill || null;
165
165
  const expectedServers = skill
166
- ? registry.mcp.filter((server: any) => (server.steps || []).some((step: any) => step.skill === skill && !step.expectedWhen)) : [];
167
- const expectedIds = new Set(expectedServers.map((server: any) => server.id));
168
- const expected = expectedServers.map((server: any) => {
166
+ ? registry.mcp.filter((server ) => (server.steps || []).some((step ) => step.skill === skill && !step.expectedWhen)) : [];
167
+ const expectedIds = new Set(expectedServers.map((server ) => server.id));
168
+ const expected = expectedServers.map((server ) => {
169
169
  let state;
170
170
  if (target) state = stateOn(reach, target, server.id);
171
171
  else state = reach ? reach.anyHarnessHas(server.id) ?? 'unknown' : 'unknown';
@@ -173,8 +173,8 @@ function renderBriefTools({ registry, router, probes, reach, owner, tier, harnes
173
173
  : (state === true ? 'reachable' : state === false ? 'unreachable' : 'unknown');
174
174
  return { server: server.id, reach: reachState, detail: target ? state : `any-harness:${state}` };
175
175
  });
176
- const also = registry.mcp.filter((server: any) => !expectedIds.has(server.id) && hasServer(reach, target, server.id));
177
- const list = (servers: any) => (servers.length ? servers.map((server: any) => `\`${server.id}\` (${trigger(server)})`).join('; ') : 'none');
176
+ const also = registry.mcp.filter((server ) => !expectedIds.has(server.id) && hasServer(reach, target, server.id));
177
+ const list = (servers ) => (servers.length ? servers.map((server ) => `\`${server.id}\` (${trigger(server)})`).join('; ') : 'none');
178
178
  const targetName = targetHarness ? targetHarness.displayName || targetHarness.id : 'any installed harness';
179
179
 
180
180
  const lines = [
@@ -218,7 +218,7 @@ function renderBriefTools({ registry, router, probes, reach, owner, tier, harnes
218
218
  tierSource: resolved.source,
219
219
  harness: target,
220
220
  expected,
221
- optional: also.map((server: any) => server.id),
221
+ optional: also.map((server ) => server.id),
222
222
  tools,
223
223
  missing,
224
224
  };
@@ -226,7 +226,7 @@ function renderBriefTools({ registry, router, probes, reach, owner, tier, harnes
226
226
  }
227
227
 
228
228
  /** The stage a feature's run is at, or null when there is no readable run or it is not at a stage. */
229
- function currentStageOf({ repoRoot = REPO_ROOT, projectRoot, taskId }: any) {
229
+ function currentStageOf({ repoRoot = REPO_ROOT, projectRoot, taskId } ) {
230
230
  try {
231
231
  const run = new WorkflowOrchestrator({ repoRoot, projectRoot }).readRun(taskId);
232
232
  const node = run && run.cursor < run.program.length ? run.program[run.cursor] : null;
@@ -235,7 +235,7 @@ function currentStageOf({ repoRoot = REPO_ROOT, projectRoot, taskId }: any) {
235
235
  }
236
236
 
237
237
  /** The feature (`--slug`, else the resolved one) and its current stage, with a note for what is missing. */
238
- function stageFor({ repoRoot, projectRoot, slug, missing }: any) {
238
+ function stageFor({ repoRoot, projectRoot, slug, missing } ) {
239
239
  let feature = slug || null;
240
240
  if (!feature) {
241
241
  const resolved = resolveActiveFeature({ projectRoot });
@@ -258,18 +258,18 @@ function stageFor({ repoRoot, projectRoot, slug, missing }: any) {
258
258
  * @param {Function} [options.buildAdapters] builds the adapter registry `mcpReach` reads installs through
259
259
  * @param {Function} [options.probe] injection seam for `probeProviders`
260
260
  */
261
- function taskLinesForAdvice({ projectRoot, feature, tasks }: any) {
261
+ function taskLinesForAdvice({ projectRoot, feature, tasks } ) {
262
262
  if (!feature || !Array.isArray(tasks) || tasks.length === 0) throw new Error('feature or task ids are unavailable');
263
263
  const planPath = path.join(projectRoot, 'agent-docs', 'doflow', feature, 'plan.md');
264
264
  const plan = fs.readFileSync(planPath, 'utf8');
265
265
  return tasks.map((id) => {
266
- const line = plan.split(/\r?\n/).find((candidate: any) => candidate.match(/^- \[[ x]\] (\S+)/)?.[1] === id);
266
+ const line = plan.split(/\r?\n/).find((candidate ) => candidate.match(/^- \[[ x]\] (\S+)/)?.[1] === id);
267
267
  if (!line) throw new Error(`task '${id}' was not found in ${planPath}`);
268
268
  return line;
269
269
  });
270
270
  }
271
271
 
272
- function adviceRecord(result: any) {
272
+ function adviceRecord(result ) {
273
273
  if (result?.status === 'answered' && result.answers?.[0]) {
274
274
  const answer = result.answers[0];
275
275
  return {
@@ -285,7 +285,7 @@ function adviceRecord(result: any) {
285
285
  /**
286
286
  * The tier renderer remains synchronous/pure; optional local advice is requested afterward.
287
287
  */
288
- async function handleBriefToolsCommand({ owner, tier, harness, slug, headingLevel, tasks, json = false, repoRoot = REPO_ROOT, projectRoot = process.cwd(), buildAdapters = null, probe = probeProviders, adviceClient = null }: any = {}) {
288
+ async function handleBriefToolsCommand({ owner, tier, harness, slug, headingLevel, tasks, json = false, repoRoot = REPO_ROOT, projectRoot = process.cwd(), buildAdapters = null, probe = probeProviders, adviceClient = null } = {}) {
289
289
  if (!owner) return usageError('brief-tools', '--owner is required (the agent type the brief is for)', json);
290
290
  const level = headingLevel === undefined ? 2 : Number(headingLevel);
291
291
  if (level !== 2 && level !== 3) return usageError('brief-tools', `--heading-level must be 2 or 3, got '${headingLevel}'`, json);
@@ -299,7 +299,7 @@ async function handleBriefToolsCommand({ owner, tier, harness, slug, headingLeve
299
299
  const stage = stageFor({ repoRoot, projectRoot, slug, missing: notes });
300
300
  const rendered = renderBriefTools({ registry, router, probes, reach, owner, tier, harness, headingLevel: level, stage });
301
301
  let markdown = rendered.markdown;
302
- const record: any = rendered.record;
302
+ const record = rendered.record;
303
303
  record.missing.push(...notes);
304
304
 
305
305
  const taskIds = Array.isArray(tasks) ? tasks : typeof tasks === 'string' ? tasks.split(',').filter(Boolean) : [];
@@ -325,14 +325,14 @@ async function handleBriefToolsCommand({ owner, tier, harness, slug, headingLeve
325
325
  }
326
326
  }
327
327
  }
328
- } catch (error: any) {
328
+ } catch (error ) {
329
329
  record.advice = { kind: 'tier', status: 'unavailable', reason: error?.reason || 'config-invalid' };
330
330
  }
331
331
  }
332
332
  if (json) console.log(JSON.stringify({ markdown, record }, null, 2));
333
333
  else process.stdout.write(markdown);
334
334
  return finishRuntime(0);
335
- } catch (error: any) {
335
+ } catch (error ) {
336
336
  captureCaught(error, 'brief-tools', 1);
337
337
  console.error(`[ERROR] brief-tools: ${error.message}`);
338
338
  return finishRuntime(1);