@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
@@ -0,0 +1,91 @@
1
+ 'use strict';
2
+
3
+ // Build the JavaScript form published to npm in an isolated staging directory. The checkout stays
4
+ // TypeScript so local development and the source CLI keep using Node's native type stripping.
5
+ const fs = require('node:fs');
6
+ const path = require('node:path');
7
+ const { stripTypeScriptTypes } = require('node:module');
8
+ const { REPO_ROOT } = require('../helper/repo-root.js');
9
+
10
+ const TEXT_EXTENSIONS = new Set(['.js', '.json', '.sh', '.md', '.yaml', '.yml']);
11
+
12
+ function walkFiles(root ) {
13
+ const files = [];
14
+ for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
15
+ const file = path.join(root, entry.name);
16
+ if (entry.isDirectory()) files.push(...walkFiles(file));
17
+ else if (entry.isFile()) files.push(file);
18
+ }
19
+ return files;
20
+ }
21
+
22
+ function buildPackage(outDir , { repoRoot = REPO_ROOT } = {}) {
23
+ if (typeof stripTypeScriptTypes !== 'function') {
24
+ throw new Error('Node does not provide node:module.stripTypeScriptTypes');
25
+ }
26
+ const packageJson = JSON.parse(fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8'));
27
+ const output = path.resolve(outDir);
28
+ fs.rmSync(output, { recursive: true, force: true });
29
+ fs.mkdirSync(output, { recursive: true });
30
+
31
+ for (const rel of packageJson.files || []) {
32
+ const source = path.join(repoRoot, rel);
33
+ if (fs.existsSync(source)) fs.cpSync(source, path.join(output, rel), { recursive: true });
34
+ }
35
+ for (const name of ['package.json', 'README.md', 'LICENSE', 'CHANGELOG.md']) {
36
+ const source = path.join(repoRoot, name);
37
+ if (fs.existsSync(source)) fs.copyFileSync(source, path.join(output, name));
38
+ }
39
+
40
+ const converted = new Set ();
41
+ for (const file of walkFiles(path.join(output, 'src'))) {
42
+ if (!file.endsWith('.ts') || file.endsWith('.d.ts')) continue;
43
+ const relative = path.relative(output, file).split(path.sep).join('/');
44
+ const jsRelative = relative.slice(0, -3) + '.js';
45
+ const code = fs.readFileSync(file, 'utf8');
46
+ fs.writeFileSync(path.join(output, jsRelative), stripTypeScriptTypes(code, { mode: 'strip' }));
47
+ fs.rmSync(file);
48
+ converted.add(relative);
49
+ }
50
+
51
+ for (const file of walkFiles(output)) {
52
+ if (!TEXT_EXTENSIONS.has(path.extname(file))) continue;
53
+ const relative = path.relative(output, file).split(path.sep).join('/');
54
+ let content = fs.readFileSync(file, 'utf8');
55
+ content = content.replace(/(['"`])((?:\.\.?\/)[^'"`\n]*?\.ts)\1/g, (whole , quote , specifier ) => {
56
+ const resolved = path.posix.normalize(path.posix.join(path.posix.dirname(relative), specifier));
57
+ if (!converted.has(resolved)) return whole;
58
+ return `${quote}${specifier.slice(0, -3)}.js${quote}`;
59
+ });
60
+ for (const rel of [...converted].sort((a, b) => b.length - a.length)) {
61
+ content = content.split(rel).join(rel.slice(0, -3) + '.js');
62
+ }
63
+ fs.writeFileSync(file, content);
64
+ }
65
+
66
+ const remaining = walkFiles(output);
67
+ const runtimeFiles = ['src', 'bin'].flatMap((directory) => {
68
+ const root = path.join(output, directory);
69
+ return fs.existsSync(root) ? walkFiles(root) : [];
70
+ });
71
+ const nonDeclarationTs = runtimeFiles.filter((file ) => file.endsWith('.ts') && !file.endsWith('.d.ts'));
72
+ if (nonDeclarationTs.length) throw new Error(`staged package retains TypeScript files: ${nonDeclarationTs.join(', ')}`);
73
+ for (const file of remaining) {
74
+ if (!TEXT_EXTENSIONS.has(path.extname(file))) continue;
75
+ const content = fs.readFileSync(file, 'utf8');
76
+ const unresolved = [...converted].filter((rel) => content.includes(rel));
77
+ if (unresolved.length) throw new Error(`${path.relative(output, file)} still references converted TypeScript paths: ${unresolved.join(', ')}`);
78
+ }
79
+ return output;
80
+ }
81
+
82
+ if (require.main === module) {
83
+ const outDir = process.argv[2];
84
+ if (!outDir) {
85
+ process.stderr.write('Usage: node src/release/build-package.js <outDir>\n');
86
+ process.exit(2);
87
+ }
88
+ buildPackage(outDir);
89
+ }
90
+
91
+ module.exports = { buildPackage };
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
4
+
5
+ // ── One release version, one CHANGELOG section, one GitHub Release body ─────────────────────────
6
+ //
7
+ // `gh release create --generate-notes` lists merged pull requests, and this repository merges
8
+ // locally, so every Release the workflow created carried only a compare link. CHANGELOG.md is
9
+ // where the release text is already written (Keep a Changelog, one `## [X.Y.Z]` heading per
10
+ // version), so the release workflow extracts the tagged version's section from it and passes that
11
+ // as the Release body. A tag whose section is missing or empty fails the job instead of
12
+ // publishing an empty Release.
13
+ //
14
+ // Usage: node src/release/changelog-section.js <version|tag> [CHANGELOG path]
15
+
16
+ const fs = require('node:fs');
17
+ const path = require('node:path');
18
+ const { REPO_ROOT } = require('../helper/repo-root.js');
19
+
20
+ function escapeRegExp(text ) {
21
+ return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
22
+ }
23
+
24
+ /**
25
+ * Returns the body of a version's section: the lines after its `## [version]` heading up to the
26
+ * next `## [` heading, trimmed. The closing `]` after the version makes 1.2.1 and 1.2.10 distinct.
27
+ * A leading `v` on the version is ignored. Returns null when the heading is absent or the body is
28
+ * empty.
29
+ * @param {string} changelogText
30
+ * @param {string} version
31
+ * @returns {string|null}
32
+ */
33
+ function changelogSection(changelogText , version ) {
34
+ const wanted = String(version).trim().replace(/^v/, '');
35
+ if (wanted === '') return null;
36
+ const lines = changelogText.split(/\r?\n/);
37
+ const heading = new RegExp(`^##\\s+\\[${escapeRegExp(wanted)}\\](\\s|$)`);
38
+ const start = lines.findIndex((line) => heading.test(line));
39
+ if (start === -1) return null;
40
+ let end = lines.length;
41
+ for (let i = start + 1; i < lines.length; i++) {
42
+ if (/^##\s+\[/.test(lines[i])) { end = i; break; }
43
+ }
44
+ const body = lines.slice(start + 1, end).join('\n').trim();
45
+ return body === '' ? null : body;
46
+ }
47
+
48
+ if (require.main === module) {
49
+ const version = process.argv[2];
50
+ const file = process.argv[3] || path.join(REPO_ROOT, 'CHANGELOG.md');
51
+ if (!version) {
52
+ console.error('usage: node src/release/changelog-section.js <version|tag> [CHANGELOG path]');
53
+ process.exit(1);
54
+ }
55
+ let text ;
56
+ try {
57
+ text = fs.readFileSync(file, 'utf8');
58
+ } catch (err) {
59
+ console.error(`cannot read ${file}: ${(err ).message}`);
60
+ process.exit(1);
61
+ }
62
+ const body = changelogSection(text, version);
63
+ if (body === null) {
64
+ console.error(`no non-empty CHANGELOG section for ${String(version).replace(/^v/, '')} in ${file}`);
65
+ process.exit(1);
66
+ }
67
+ process.stdout.write(`${body}\n`);
68
+ }
69
+
70
+ module.exports = { changelogSection };
@@ -14,7 +14,7 @@
14
14
 
15
15
  const fs = require('node:fs');
16
16
  const path = require('node:path');
17
- const { REPO_ROOT } = require('../helper/repo-root.ts');
17
+ const { REPO_ROOT } = require('../helper/repo-root.js');
18
18
 
19
19
  /** Every distribution manifest that repeats the release version, relative to the repo root. */
20
20
  const PLUGIN_MANIFESTS = [
@@ -31,14 +31,14 @@ const PLUGIN_MANIFESTS = [
31
31
  * @param {Object} [options.fsImpl]
32
32
  * @returns {{version: string, updated: Array<string>, unchanged: Array<string>}}
33
33
  */
34
- function syncPluginVersions({ repoRoot = REPO_ROOT, fsImpl = fs }: { repoRoot?: string, fsImpl?: any } = {}): { version: string, updated: string[], unchanged: string[] } {
34
+ function syncPluginVersions({ repoRoot = REPO_ROOT, fsImpl = fs } = {}) {
35
35
  const pkg = JSON.parse(fsImpl.readFileSync(path.join(repoRoot, 'package.json'), 'utf8'));
36
36
  if (typeof pkg.version !== 'string' || pkg.version.trim() === '') {
37
37
  throw new Error('package.json declares no version to project');
38
38
  }
39
39
 
40
- const updated: string[] = [];
41
- const unchanged: string[] = [];
40
+ const updated = [];
41
+ const unchanged = [];
42
42
  for (const rel of PLUGIN_MANIFESTS) {
43
43
  const file = path.join(repoRoot, rel);
44
44
  const text = fsImpl.readFileSync(file, 'utf8');
@@ -4,19 +4,19 @@
4
4
 
5
5
  const fs = require('node:fs');
6
6
  const path = require('node:path');
7
- const { finishRuntime, usageError } = require('../cli-result.ts');
8
- const { REPO_ROOT } = require('../../helper/repo-root.ts');
9
- const { loadAdviceRegistry } = require('./registry.ts');
10
- const { loadStorageRegistry } = require('../storage/registry.ts');
11
- const { resolveRoots } = require('../storage/roots.ts');
12
- const { resolveSetting, writeSetting } = require('./config.ts');
13
- const { createAdviceClient } = require('./client.ts');
14
- const { materializeKind, validateQuestionSet, validateStaticAnswer } = require('./kinds.ts');
15
- const { findPick, appendOutcome } = require('./record.ts');
16
- const { strengthWords } = require('./strength.ts');
7
+ const { finishRuntime, usageError } = require('../cli-result.js');
8
+ const { REPO_ROOT } = require('../../helper/repo-root.js');
9
+ const { loadAdviceRegistry } = require('./registry.js');
10
+ const { loadStorageRegistry } = require('../storage/registry.js');
11
+ const { resolveRoots } = require('../storage/roots.js');
12
+ const { resolveSetting, writeSetting } = require('./config.js');
13
+ const { createAdviceClient } = require('./client.js');
14
+ const { materializeKind, validateQuestionSet, validateStaticAnswer } = require('./kinds.js');
15
+ const { findPick, appendOutcome } = require('./record.js');
16
+ const { strengthWords } = require('./strength.js');
17
17
 
18
- function loadSources(repoRoot: any) {
19
- const read = (name: any) => JSON.parse(fs.readFileSync(path.join(repoRoot, 'core/registry', name), 'utf8'));
18
+ function loadSources(repoRoot ) {
19
+ const read = (name ) => JSON.parse(fs.readFileSync(path.join(repoRoot, 'core/registry', name), 'utf8'));
20
20
  return {
21
21
  workflows: read('workflows.json'),
22
22
  verification: read('verification.json'),
@@ -24,7 +24,7 @@ function loadSources(repoRoot: any) {
24
24
  };
25
25
  }
26
26
 
27
- function loadRuntime({ projectRoot, global = false }: any = {}) {
27
+ function loadRuntime({ projectRoot, global = false } = {}) {
28
28
  const advice = loadAdviceRegistry({ repoRoot: REPO_ROOT });
29
29
  const storage = loadStorageRegistry({ repoRoot: REPO_ROOT });
30
30
  const roots = resolveRoots({ registry: storage, projectRoot, global });
@@ -33,7 +33,7 @@ function loadRuntime({ projectRoot, global = false }: any = {}) {
33
33
  return { adviceRegistry, adviceError: advice.ok ? null : advice.detail, storage, roots, sources };
34
34
  }
35
35
 
36
- function emitResult(result: any, { json, kind }: any) {
36
+ function emitResult(result , { json, kind } ) {
37
37
  if (result.reason === 'over-limit') {
38
38
  return usageError('advise', result.detail || 'request exceeds an advice limit', json);
39
39
  }
@@ -50,11 +50,11 @@ function emitResult(result: any, { json, kind }: any) {
50
50
  return finishRuntime(0);
51
51
  }
52
52
 
53
- function isPresent(value: any) {
53
+ function isPresent(value ) {
54
54
  return value !== undefined && value !== null;
55
55
  }
56
56
 
57
- function readState({ state, stateFile, json }: any) {
57
+ function readState({ state, stateFile, json } ) {
58
58
  if (isPresent(state) === isPresent(stateFile)) {
59
59
  usageError('advise', 'provide exactly one of --state or --state-file', json);
60
60
  return null;
@@ -64,26 +64,26 @@ function readState({ state, stateFile, json }: any) {
64
64
  const content = fs.readFileSync(stateFile, 'utf8');
65
65
  if (!content.length) throw new Error('file is empty');
66
66
  return content;
67
- } catch (error: any) {
67
+ } catch (error ) {
68
68
  usageError('advise', `cannot read state file ${stateFile}: ${error.message}`, json);
69
69
  return null;
70
70
  }
71
71
  }
72
72
 
73
- function readQuestions(file: any, json: any) {
73
+ function readQuestions(file , json ) {
74
74
  try {
75
75
  const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
76
76
  if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed) || !Array.isArray(parsed.questions)) {
77
77
  throw new Error('expected an object with a questions array');
78
78
  }
79
79
  return parsed.questions;
80
- } catch (error: any) {
80
+ } catch (error ) {
81
81
  usageError('advise', `cannot read questions file ${file}: ${error.message}`, json);
82
82
  return null;
83
83
  }
84
84
  }
85
85
 
86
- function parseAskInput(options: any) {
86
+ function parseAskInput(options ) {
87
87
  const hasKind = typeof options.kind === 'string' && options.kind.length > 0;
88
88
  const hasQuestionsFile = isPresent(options.questionsFile);
89
89
  if (hasKind === hasQuestionsFile) {
@@ -103,7 +103,7 @@ function parseAskInput(options: any) {
103
103
  return { state, hasKind, hasQuestionsFile };
104
104
  }
105
105
 
106
- function endpointSource(userSetting: any, endpoint: any) {
106
+ function endpointSource(userSetting , endpoint ) {
107
107
  if (userSetting?.decidedBy?.user) {
108
108
  try {
109
109
  const file = JSON.parse(fs.readFileSync(userSetting.decidedBy.user, 'utf8'));
@@ -113,7 +113,7 @@ function endpointSource(userSetting: any, endpoint: any) {
113
113
  return 'provider default';
114
114
  }
115
115
 
116
- function inspectFailure(inspected: any, { endpoint, model, provider }: any) {
116
+ function inspectFailure(inspected , { endpoint, model, provider } ) {
117
117
  if (inspected.endpoint.state === 'refused') return inspected.endpoint.message;
118
118
  if (inspected.endpoint.state !== 'reached') {
119
119
  return `advise: Ollama did not answer at ${endpoint}; start it yourself and re-run. Nothing was written.`;
@@ -126,21 +126,21 @@ function inspectFailure(inspected: any, { endpoint, model, provider }: any) {
126
126
  }
127
127
  if (!inspected.model.decisionCapable) {
128
128
  const capable = inspected.models
129
- .filter((entry: any) => Array.isArray(entry.capabilities) && entry.capabilities.includes(provider.capability))
130
- .map((entry: any) => entry.name);
129
+ .filter((entry ) => Array.isArray(entry.capabilities) && entry.capabilities.includes(provider.capability))
130
+ .map((entry ) => entry.name);
131
131
  return `advise: model ${model} is not decision-capable; decision-capable here: ${capable.length ? capable.join(', ') : 'none'}. Nothing was written.`;
132
132
  }
133
133
  return null;
134
134
  }
135
135
 
136
- function writeFailure(message: any, json: any) {
136
+ function writeFailure(message , json ) {
137
137
  if (json) console.log(JSON.stringify({ ok: false, error: 'write-failed', message }, null, 2));
138
138
  else if (message.startsWith('decision model: endpoint ') || message.startsWith('advise:')) console.error(message);
139
139
  else console.error(`advise: ${message}`);
140
140
  return finishRuntime(1);
141
141
  }
142
142
 
143
- async function handleConfigure(options: any, runtime: any) {
143
+ async function handleConfigure(options , runtime ) {
144
144
  const { adviceRegistry, adviceError, roots, sources } = runtime;
145
145
  const { json, project, global, force } = options;
146
146
  const hasModel = typeof options.model === 'string' && options.model.length > 0;
@@ -173,7 +173,7 @@ async function handleConfigure(options: any, runtime: any) {
173
173
  return writeFailure('turn the decision model on at user level first; a project cannot enable it', json);
174
174
  }
175
175
  const providerId = userSetting.provider || 'ollama';
176
- const provider = adviceRegistry.providers.find((entry: any) => entry.id === providerId);
176
+ const provider = adviceRegistry.providers.find((entry ) => entry.id === providerId);
177
177
  if (!provider) return writeFailure(`provider '${providerId}' is not in core/registry/advice.json`, json);
178
178
  const endpoint = project
179
179
  ? userSetting.endpoint
@@ -197,7 +197,7 @@ async function handleConfigure(options: any, runtime: any) {
197
197
  return finishRuntime(0);
198
198
  }
199
199
 
200
- async function handleAsk(options: any, runtime: any) {
200
+ async function handleAsk(options , runtime ) {
201
201
  const parsed = parseAskInput(options);
202
202
  if (!parsed) return finishRuntime(2);
203
203
  const { adviceRegistry, adviceError, roots, sources } = runtime;
@@ -243,7 +243,7 @@ async function handleAsk(options: any, runtime: any) {
243
243
  return emitResult(result, { json: options.json, kind });
244
244
  }
245
245
 
246
- function handleOutcome(options: any, runtime: any) {
246
+ function handleOutcome(options , runtime ) {
247
247
  const { json } = options;
248
248
  if (typeof options.pickId !== 'string' || !options.pickId) return usageError('advise', '--pick-id is required', json);
249
249
  if (typeof options.actual !== 'string' || !options.actual) return usageError('advise', '--actual is required', json);
@@ -265,7 +265,7 @@ function handleOutcome(options: any, runtime: any) {
265
265
  return finishRuntime(0);
266
266
  }
267
267
 
268
- async function handleAdviseCommand(options: any = {}) {
268
+ async function handleAdviseCommand(options = {}) {
269
269
  const action = options.actionGiven ? options.action : 'ask';
270
270
  if (!['ask', 'outcome', 'configure'].includes(action)) return usageError('advise', `unknown action '${action}'`, options.json);
271
271
  try {
@@ -275,7 +275,7 @@ async function handleAdviseCommand(options: any = {}) {
275
275
  if (action === 'configure') return await handleConfigure(shaped, runtime);
276
276
  if (action === 'outcome') return handleOutcome(shaped, runtime);
277
277
  return await handleAsk(shaped, runtime);
278
- } catch (error: any) {
278
+ } catch (error ) {
279
279
  return writeFailure(error?.message || 'advice command failed', options.json);
280
280
  }
281
281
  }
@@ -5,27 +5,27 @@
5
5
  const fs = require('node:fs');
6
6
  const http = require('node:http');
7
7
  const https = require('node:https');
8
- const { resolveSetting } = require('./config.ts');
9
- const { checkEndpoint } = require('./endpoint-guard.ts');
10
- const { strengthOf } = require('./strength.ts');
11
- const { validateQuestionSet, validateStaticAnswer } = require('./kinds.ts');
12
- const { appendPick, appendMiss } = require('./record.ts');
8
+ const { resolveSetting } = require('./config.js');
9
+ const { checkEndpoint } = require('./endpoint-guard.js');
10
+ const { strengthOf } = require('./strength.js');
11
+ const { validateQuestionSet, validateStaticAnswer } = require('./kinds.js');
12
+ const { appendPick, appendMiss } = require('./record.js');
13
13
 
14
14
  // Keep this map literal: module reachability must be auditable without dynamic require paths.
15
- const ADAPTERS: Record<string, any> = Object.freeze({
16
- 'ollama-systemone': require('./providers/ollama-systemone.ts'),
15
+ const ADAPTERS = Object.freeze({
16
+ 'ollama-systemone': require('./providers/ollama-systemone.js'),
17
17
  });
18
18
 
19
- function durationSince(startedAt: any) {
19
+ function durationSince(startedAt ) {
20
20
  return Math.max(0, Date.now() - startedAt);
21
21
  }
22
22
 
23
- function versionTuple(version: any) {
23
+ function versionTuple(version ) {
24
24
  const match = typeof version === 'string' && version.match(/^v?(\d+)\.(\d+)\.(\d+)/);
25
25
  return match ? match.slice(1).map(Number) : null;
26
26
  }
27
27
 
28
- function versionAtLeast(version: any, minimum: any) {
28
+ function versionAtLeast(version , minimum ) {
29
29
  const actual = versionTuple(version);
30
30
  const required = versionTuple(minimum);
31
31
  if (!actual || !required) return false;
@@ -36,16 +36,16 @@ function versionAtLeast(version: any, minimum: any) {
36
36
  return true;
37
37
  }
38
38
 
39
- function networkReason(error: any) {
39
+ function networkReason(error ) {
40
40
  return error?.code === 'ADVICE_TIMEOUT' || error?.code === 'ETIMEDOUT' || error?.code === 'ESOCKETTIMEDOUT'
41
41
  ? 'timeout' : 'unreachable';
42
42
  }
43
43
 
44
- function requestAction({ endpoint, action, pinnedLookup, timeoutMs, httpModule = http, httpsModule = https }: any) {
45
- return new Promise<any>((resolve, reject) => {
46
- let request: any;
44
+ function requestAction({ endpoint, action, pinnedLookup, timeoutMs, httpModule = http, httpsModule = https } ) {
45
+ return new Promise ((resolve, reject) => {
46
+ let request ;
47
47
  let settled = false;
48
- const finish = (error: any, response?: any) => {
48
+ const finish = (error , response ) => {
49
49
  if (settled) return;
50
50
  settled = true;
51
51
  clearTimeout(timer);
@@ -53,7 +53,7 @@ function requestAction({ endpoint, action, pinnedLookup, timeoutMs, httpModule =
53
53
  else resolve(response);
54
54
  };
55
55
  const timer = setTimeout(() => {
56
- const error: any = new Error(`decision model request timed out after ${timeoutMs}ms`);
56
+ const error = new Error(`decision model request timed out after ${timeoutMs}ms`);
57
57
  error.code = 'ADVICE_TIMEOUT';
58
58
  request?.destroy(error);
59
59
  finish(error);
@@ -78,25 +78,25 @@ function requestAction({ endpoint, action, pinnedLookup, timeoutMs, httpModule =
78
78
  'content-length': Buffer.byteLength(body),
79
79
  },
80
80
  };
81
- request = transport.request(options, (response: any) => {
82
- const chunks: any[] = [];
83
- response.on('data', (chunk: any) => chunks.push(Buffer.from(chunk)));
84
- response.on('error', (error: any) => finish(error));
81
+ request = transport.request(options, (response ) => {
82
+ const chunks = [];
83
+ response.on('data', (chunk ) => chunks.push(Buffer.from(chunk)));
84
+ response.on('error', (error ) => finish(error));
85
85
  response.on('end', () => finish(null, {
86
86
  status: response.statusCode || 0,
87
87
  bodyText: Buffer.concat(chunks).toString('utf8'),
88
88
  }));
89
89
  });
90
- request.on('error', (error: any) => finish(error));
90
+ request.on('error', (error ) => finish(error));
91
91
  if (body === undefined) request.end();
92
92
  else request.end(body);
93
- } catch (error: any) {
93
+ } catch (error ) {
94
94
  finish(error);
95
95
  }
96
96
  });
97
97
  }
98
98
 
99
- function emptyAdviceResult(status: any, reason: any, detail: any, setting: any, durationMs: any) {
99
+ function emptyAdviceResult(status , reason , detail , setting , durationMs ) {
100
100
  return {
101
101
  status, reason, detail: detail ?? null,
102
102
  provider: setting?.provider ?? null,
@@ -116,14 +116,14 @@ function createAdviceClient({
116
116
  httpModule = http,
117
117
  httpsModule = https,
118
118
  clock = () => new Date(),
119
- }: any = {}) {
120
- async function ask({ questionSet, kind, staticAnswer, caller, taskId = null, record = true }: any = {}) {
119
+ } = {}) {
120
+ async function ask({ questionSet, kind, staticAnswer, caller, taskId = null, record = true } = {}) {
121
121
  const startedAt = Date.now();
122
- let setting: any = null;
122
+ let setting = null;
123
123
  const effectiveKind = typeof kind === 'string' && kind ? kind : 'adhoc';
124
124
  const shouldRecord = record !== false;
125
125
 
126
- function unavailable(reason: any, detail: any) {
126
+ function unavailable(reason , detail ) {
127
127
  const durationMs = durationSince(startedAt);
128
128
  if (shouldRecord && setting?.state === 'on') {
129
129
  try { appendMiss({ roots, now: clock, fsImpl, kind: effectiveKind, caller, reason, model: setting.model, durationMs }); }
@@ -138,12 +138,12 @@ function createAdviceClient({
138
138
  return emptyAdviceResult('off', setting.reason, setting.notes?.[0] || null, setting, durationSince(startedAt));
139
139
  }
140
140
 
141
- const provider = adviceRegistry?.providers?.find((entry: any) => entry.id === setting.provider);
141
+ const provider = adviceRegistry?.providers?.find((entry ) => entry.id === setting.provider);
142
142
  const adapter = provider && ADAPTERS[provider.adapter];
143
143
  if (!provider || !adapter) return unavailable('config-invalid', `provider adapter '${provider?.adapter || setting.provider}' is unavailable`);
144
144
 
145
145
  if (effectiveKind !== 'adhoc') {
146
- const namedKind = adviceRegistry.kinds?.find((entry: any) => entry.id === effectiveKind);
146
+ const namedKind = adviceRegistry.kinds?.find((entry ) => entry.id === effectiveKind);
147
147
  if (!namedKind || questionSet?.questions?.length !== 1 || questionSet.questions[0]?.name !== effectiveKind) {
148
148
  return unavailable('config-invalid', `question set does not match kind '${effectiveKind}'`);
149
149
  }
@@ -185,20 +185,20 @@ function createAdviceClient({
185
185
  httpModule,
186
186
  httpsModule,
187
187
  });
188
- } catch (error: any) {
188
+ } catch (error ) {
189
189
  const reason = networkReason(error);
190
190
  return unavailable(reason, error.message);
191
191
  }
192
192
 
193
193
  let parsed;
194
194
  try { parsed = adapter.parseReply(response.status, response.bodyText, questionSet); }
195
- catch (error: any) { return unavailable('malformed-reply', error.message); }
195
+ catch (error ) { return unavailable('malformed-reply', error.message); }
196
196
  if (!parsed?.ok) return unavailable(parsed?.reason || 'malformed-reply', parsed?.detail || 'reply could not be parsed');
197
197
 
198
- const answers = parsed.answers.map((answer: any, index: any) => {
198
+ const answers = parsed.answers.map((answer , index ) => {
199
199
  const strength = strengthOf(answer, adviceRegistry.strength);
200
200
  const answerStatic = questionSet.questions.length === 1 ? staticAnswer ?? null : null;
201
- const result: any = {
201
+ const result = {
202
202
  name: answer.name,
203
203
  kind: effectiveKind,
204
204
  type: answer.type,
@@ -237,19 +237,19 @@ function createAdviceClient({
237
237
  provider: setting.provider, model: setting.model, endpoint: setting.endpoint,
238
238
  decidedBy: setting.decidedBy, durationMs: durationSince(startedAt), answers,
239
239
  };
240
- } catch (error: any) {
240
+ } catch (error ) {
241
241
  return unavailable('config-invalid', error?.message || 'advice request failed');
242
242
  }
243
243
  }
244
244
 
245
- async function inspect({ endpoint, model, provider: providerId = 'ollama', file, minVersion, timeoutMs }: any = {}) {
246
- const unavailable = (state: any, message: any, version: any = null, versionOk = false) => ({
245
+ async function inspect({ endpoint, model, provider: providerId = 'ollama', file, minVersion, timeoutMs } = {}) {
246
+ const unavailable = (state , message , version = null, versionOk = false) => ({
247
247
  endpoint: { state, version, versionOk, message: message ?? null },
248
248
  models: [],
249
249
  model: { installed: false, decisionCapable: false },
250
250
  });
251
251
  try {
252
- const provider = adviceRegistry?.providers?.find((entry: any) => entry.id === providerId);
252
+ const provider = adviceRegistry?.providers?.find((entry ) => entry.id === providerId);
253
253
  const adapter = provider && ADAPTERS[provider.adapter];
254
254
  if (!provider || !adapter) return unavailable('refused', `provider '${providerId}' is unavailable`);
255
255
  const probeLimit = Number.isFinite(timeoutMs) ? timeoutMs : adviceRegistry.probeTimeoutMs;
@@ -258,7 +258,7 @@ function createAdviceClient({
258
258
  const remaining = () => Math.max(0, budgetMs - (Date.now() - startedAt));
259
259
  const endpointCheck = await checkEndpoint(endpoint, { lookup, file, timeoutMs: remaining() });
260
260
  if (!endpointCheck.ok) return unavailable(endpointCheck.reason === 'timeout' ? 'unreachable' : 'refused', endpointCheck.message);
261
- const requestProbe = (action: any) => {
261
+ const requestProbe = (action ) => {
262
262
  const left = remaining();
263
263
  if (left <= 0) throw Object.assign(new Error('decision model probe budget exhausted'), { code: 'ADVICE_TIMEOUT' });
264
264
  return requestAction({
@@ -269,7 +269,7 @@ function createAdviceClient({
269
269
 
270
270
  let versionResponse;
271
271
  try { versionResponse = await requestProbe(adapter.versionRequest()); }
272
- catch (error: any) { return unavailable('unreachable', error.message); }
272
+ catch (error ) { return unavailable('unreachable', error.message); }
273
273
  const version = adapter.parseVersion(versionResponse.status, versionResponse.bodyText)?.version ?? null;
274
274
  const minimum = minVersion || provider.minVersion;
275
275
  const versionOk = version ? versionAtLeast(version, minimum) : false;
@@ -288,9 +288,9 @@ function createAdviceClient({
288
288
  return { endpoint: endpointResult, models, model: { installed: false, decisionCapable: false } };
289
289
  }
290
290
 
291
- const configuredIndex = models.findIndex((entry: any) => adapter.modelMatches(model, entry.name));
292
- const fallbackIndexes = models.map((entry: any, index: any) => index)
293
- .filter((index: any) => !Array.isArray(models[index].capabilities));
291
+ const configuredIndex = models.findIndex((entry ) => adapter.modelMatches(model, entry.name));
292
+ const fallbackIndexes = models.map((entry , index ) => index)
293
+ .filter((index ) => !Array.isArray(models[index].capabilities));
294
294
  if (configuredIndex >= 0 && fallbackIndexes.includes(configuredIndex)) {
295
295
  fallbackIndexes.splice(fallbackIndexes.indexOf(configuredIndex), 1);
296
296
  fallbackIndexes.unshift(configuredIndex);
@@ -304,7 +304,7 @@ function createAdviceClient({
304
304
  // Keep capabilities unknown when the read-only fallback is unavailable.
305
305
  }
306
306
  }
307
- const match = models.find((entry: any) => adapter.modelMatches(model, entry.name));
307
+ const match = models.find((entry ) => adapter.modelMatches(model, entry.name));
308
308
  return {
309
309
  endpoint: endpointResult,
310
310
  models,
@@ -313,7 +313,7 @@ function createAdviceClient({
313
313
  decisionCapable: Boolean(match?.capabilities?.includes(provider.capability)),
314
314
  },
315
315
  };
316
- } catch (error: any) {
316
+ } catch (error ) {
317
317
  return unavailable('unreachable', error?.message || 'decision model inspection failed');
318
318
  }
319
319
  }