@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
@@ -11,15 +11,15 @@
11
11
 
12
12
  const fs = require('node:fs');
13
13
  const path = require('node:path');
14
- const { loadRegistry } = require('../registry/index.ts');
15
- const { finishRuntime, usageError, captureCaught } = require('./cli-result.ts');
16
- const { REPO_ROOT } = require('../helper/repo-root.ts');
14
+ const { loadRegistry } = require('../registry/index.js');
15
+ const { finishRuntime, usageError, captureCaught } = require('./cli-result.js');
16
+ const { REPO_ROOT } = require('../helper/repo-root.js');
17
17
 
18
18
  /** The machine-level command each provider's backend answers to. A provider without a local CLI
19
19
  * (hosted-only access through another harness) reports backendCli null and is never "available". */
20
- const BACKEND_CLI: Readonly<Record<string, string>> = Object.freeze({ claude: 'claude', codex: 'codex', copilot: 'copilot', ollama: 'ollama' });
20
+ const BACKEND_CLI = Object.freeze({ claude: 'claude', codex: 'codex', copilot: 'copilot', ollama: 'ollama' });
21
21
 
22
- function whichLike(command: string | undefined, { fsImpl = fs, pathEnv = process.env.PATH }: { fsImpl?: any; pathEnv?: string } = {}): boolean {
22
+ function whichLike(command , { fsImpl = fs, pathEnv = process.env.PATH } = {}) {
23
23
  if (!command) return false;
24
24
  for (const dir of String(pathEnv ?? '').split(path.delimiter)) {
25
25
  if (!dir) continue;
@@ -33,7 +33,7 @@ function whichLike(command: string | undefined, { fsImpl = fs, pathEnv = process
33
33
  }
34
34
 
35
35
  /** Providers whose backend CLI resolves on PATH. Injectable in tests; never guessed otherwise. */
36
- function availableProviderIds({ fsImpl = fs }: { fsImpl?: any } = {}): string[] {
36
+ function availableProviderIds({ fsImpl = fs } = {}) {
37
37
  return Object.entries(BACKEND_CLI)
38
38
  .filter(([, cli]) => whichLike(cli, { fsImpl }))
39
39
  .map(([id]) => id);
@@ -46,13 +46,13 @@ function availableProviderIds({ fsImpl = fs }: { fsImpl?: any } = {}): string[]
46
46
  * review with require:different-family) and is reported back rather than hidden.
47
47
  * Availability unknown stays null — absence of evidence is not reported as absent.
48
48
  */
49
- function resolveModelRole({ registry, roleId, isAvailable = null, exclude = [] }: any = {}): any {
50
- const role = (registry.modelRoles || []).find((entry: any) => entry.id === roleId);
49
+ function resolveModelRole({ registry, roleId, isAvailable = null, exclude = [] } = {}) {
50
+ const role = (registry.modelRoles || []).find((entry ) => entry.id === roleId);
51
51
  if (!role) {
52
- throw new Error(`Unknown model role '${roleId}'; valid: ${(registry.modelRoles || []).map((r: any) => r.id).join(', ')}`);
52
+ throw new Error(`Unknown model role '${roleId}'; valid: ${(registry.modelRoles || []).map((r ) => r.id).join(', ')}`);
53
53
  }
54
54
  const excluded = new Set(exclude);
55
- const candidates: any[] = [];
55
+ const candidates = [];
56
56
  for (const [index, provider] of (registry.modelProviders || []).entries()) {
57
57
  if (excluded.has(provider.id)) continue;
58
58
  const tiers = provider.tiers ?? [];
@@ -67,13 +67,13 @@ function resolveModelRole({ registry, roleId, isAvailable = null, exclude = [] }
67
67
  _index: index,
68
68
  });
69
69
  }
70
- const rank = (candidate: any): number[] => [
70
+ const rank = (candidate ) => [
71
71
  candidate.available === true ? 0 : candidate.available === false ? 1 : 2,
72
72
  candidate.servesPreferredTier ? 0 : 1,
73
73
  candidate.servesFallbackTier ? 0 : 1,
74
74
  candidate._index,
75
75
  ];
76
- candidates.sort((a: any, b: any) => {
76
+ candidates.sort((a , b ) => {
77
77
  const ra = rank(a); const rb = rank(b);
78
78
  for (let i = 0; i < ra.length; i += 1) if (ra[i] !== rb[i]) return ra[i] - rb[i];
79
79
  return 0;
@@ -98,10 +98,10 @@ function resolveModelRole({ registry, roleId, isAvailable = null, exclude = [] }
98
98
  * lexical rather than guess. Unknown slot ids also resolve to `{active:false}` rather than
99
99
  * throwing: absence of a slot is every install's normal state, unlike an unknown role.
100
100
  */
101
- function resolveRetrievalSlot({ registry, slotId, isAvailable = null }: any = {}): any {
102
- const slot = (registry.retrievalSlots || []).find((entry: any) => entry.id === slotId);
101
+ function resolveRetrievalSlot({ registry, slotId, isAvailable = null } = {}) {
102
+ const slot = (registry.retrievalSlots || []).find((entry ) => entry.id === slotId);
103
103
  if (!slot || !slot.enabled) return { slotId, active: false, reason: slot ? 'disabled' : 'undeclared' };
104
- const provider = (registry.modelProviders || []).find((entry: any) => entry.id === slot.provider);
104
+ const provider = (registry.modelProviders || []).find((entry ) => entry.id === slot.provider);
105
105
  if (!provider) return { slotId, active: false, reason: 'provider-missing' };
106
106
  return {
107
107
  slotId,
@@ -118,11 +118,11 @@ function resolveRetrievalSlot({ registry, slotId, isAvailable = null }: any = {}
118
118
 
119
119
  /** CLI handler for `doflow model-role`. Read-only advisory routing; exits 1 on an unknown role
120
120
  * because a silently-empty candidate list would read as "no providers" rather than "bad input". */
121
- function handleModelRoleCommand({ role, exclude, json = false, repoRoot }: any = {}): number | undefined {
121
+ function handleModelRoleCommand({ role, exclude, json = false, repoRoot } = {}) {
122
122
  if (!role) return usageError('model-role', '--role is required (one of the roles in core/registry/models.json)', json);
123
123
  const registry = (() => {
124
124
  try { return loadRegistry({ repoRoot: repoRoot || REPO_ROOT }); }
125
- catch (error: any) { captureCaught(error, 'model-role', 1); console.error(`[ERROR] model-role: ${error.message}`); return finishRuntime(1); }
125
+ catch (error ) { captureCaught(error, 'model-role', 1); console.error(`[ERROR] model-role: ${error.message}`); return finishRuntime(1); }
126
126
  })();
127
127
  if (!registry) return undefined;
128
128
  const available = new Set(availableProviderIds());
@@ -130,8 +130,8 @@ function handleModelRoleCommand({ role, exclude, json = false, repoRoot }: any =
130
130
  const resolution = resolveModelRole({
131
131
  registry,
132
132
  roleId: role,
133
- isAvailable: (providerId: string) => available.has(providerId),
134
- exclude: Array.isArray(exclude) ? exclude : String(exclude ?? '').split(',').map((s: string) => s.trim()).filter(Boolean),
133
+ isAvailable: (providerId ) => available.has(providerId),
134
+ exclude: Array.isArray(exclude) ? exclude : String(exclude ?? '').split(',').map((s ) => s.trim()).filter(Boolean),
135
135
  });
136
136
  if (json) console.log(JSON.stringify(resolution, null, 2));
137
137
  else {
@@ -143,7 +143,7 @@ function handleModelRoleCommand({ role, exclude, json = false, repoRoot }: any =
143
143
  if (resolution.excluded.length) console.log(`Excluded: ${resolution.excluded.join(', ')}`);
144
144
  }
145
145
  return finishRuntime(0);
146
- } catch (error: any) {
146
+ } catch (error ) {
147
147
  captureCaught(error, 'model-role', 1);
148
148
  console.error(`[ERROR] model-role: ${error.message}`);
149
149
  return finishRuntime(1);
@@ -42,22 +42,22 @@
42
42
 
43
43
  const fs = require('node:fs');
44
44
  const path = require('node:path');
45
- const { EvidenceLedger, assertSafeTaskId } = require('./evidence-ledger.ts');
46
- const { taskStoreDir } = require('./task-scope.ts');
45
+ const { EvidenceLedger, assertSafeTaskId } = require('./evidence-ledger.js');
46
+ const { taskStoreDir } = require('./task-scope.js');
47
47
  // The two verdict vocabularies, imported from the modules that own them rather than respelled
48
48
  // here. A second copy would let this file accept a readiness state readiness itself has retired.
49
- const { READINESS_STATES } = require('./readiness.ts');
50
- const { VERIFICATION_STATUSES } = require('./verification/engine.ts');
51
- const { WorkflowEngine } = require('./workflow-engine.ts');
49
+ const { READINESS_STATES } = require('./readiness.js');
50
+ const { VERIFICATION_STATUSES } = require('./verification/engine.js');
51
+ const { WorkflowEngine } = require('./workflow-engine.js');
52
52
  // Read, not re-derived: the retrieval plan's location is `retrieval-plan.ts`'s to define, and the
53
53
  // unreached items this record carries forward are the ones that record already holds.
54
- const { planPath, UNREACHED } = require('./retrieval-plan.ts');
54
+ const { planPath, UNREACHED } = require('./retrieval-plan.js');
55
55
  // One definition of the score refusal, applied at a further boundary. See the note on
56
56
  // EVIDENCE_SCORE_FIELDS in cli.js: a terminal state that carried a confidence would be exactly the
57
57
  // number NFR-001 exists to keep out of the one record the next worker reads first.
58
- const { assertNoScoreFields } = require('./cli.ts');
59
- const { finishRuntime, usageError } = require('./cli-result.ts');
60
- const { REPO_ROOT } = require('../helper/repo-root.ts');
58
+ const { assertNoScoreFields } = require('./evidence-fields.js');
59
+ const { finishRuntime, usageError } = require('./cli-result.js');
60
+ const { REPO_ROOT } = require('../helper/repo-root.js');
61
61
 
62
62
  // ── the closed terminal vocabulary (design §4) ───────────────────────────────────────────────
63
63
 
@@ -96,7 +96,7 @@ const NOT_RECORDED = 'NOT_RECORDED';
96
96
  * @param {string|null} [slug] the feature the task belongs to, when not the branch's (task-scope.js)
97
97
  * @returns {string}
98
98
  */
99
- function outcomePath(projectRoot: any, taskId: any, slug: any = null) {
99
+ function outcomePath(projectRoot , taskId , slug = null) {
100
100
  const dir = taskStoreDir({ projectRoot, store: 'outcome', taskId: assertSafeTaskId(taskId), slug });
101
101
  return path.join(dir, `${taskId}.json`);
102
102
  }
@@ -106,12 +106,12 @@ function outcomePath(projectRoot: any, taskId: any, slug: any = null) {
106
106
  * @param {string} taskId
107
107
  * @returns {Object|null} the record, or null when no outcome was recorded
108
108
  */
109
- function readOutcome(projectRoot: any, taskId: any, slug: any = null) {
109
+ function readOutcome(projectRoot , taskId , slug = null) {
110
110
  const file = outcomePath(projectRoot, taskId, slug);
111
111
  if (!fs.existsSync(file)) return null;
112
112
  try {
113
113
  return JSON.parse(fs.readFileSync(file, 'utf8'));
114
- } catch (error: any) {
114
+ } catch (error ) {
115
115
  throw new Error(`the outcome record at '${file}' is not readable: ${error.message}`);
116
116
  }
117
117
  }
@@ -122,7 +122,7 @@ function readOutcome(projectRoot: any, taskId: any, slug: any = null) {
122
122
  * @param {Object} record
123
123
  * @returns {string} the file written
124
124
  */
125
- function writeOutcome(projectRoot: any, taskId: any, record: any, slug: any = null) {
125
+ function writeOutcome(projectRoot , taskId , record , slug = null) {
126
126
  const file = outcomePath(projectRoot, taskId, slug);
127
127
  fs.mkdirSync(path.dirname(file), { recursive: true });
128
128
  fs.writeFileSync(file, `${JSON.stringify(record, null, 2)}\n`, 'utf8');
@@ -142,7 +142,7 @@ function writeOutcome(projectRoot: any, taskId: any, record: any, slug: any = nu
142
142
  * @param {string} taskId
143
143
  * @returns {number}
144
144
  */
145
- function countEvidence(projectRoot: any, taskId: any, slug: any = null) {
145
+ function countEvidence(projectRoot , taskId , slug = null) {
146
146
  const ledger = new EvidenceLedger({ repoRoot: projectRoot, slug });
147
147
  ledger.load(taskId);
148
148
  return ledger.queryEvidence({ taskId }).length;
@@ -164,14 +164,14 @@ function countEvidence(projectRoot: any, taskId: any, slug: any = null) {
164
164
  * @param {string} verification the stated verification verdict, or NOT_RECORDED
165
165
  * @returns {Array<string>}
166
166
  */
167
- function unreachedItems(projectRoot: any, taskId: any, verification: any, slug: any = null) {
167
+ function unreachedItems(projectRoot , taskId , verification , slug = null) {
168
168
  const items = [];
169
169
  const file = planPath(projectRoot, taskId, slug);
170
170
  if (fs.existsSync(file)) {
171
171
  let plan;
172
172
  try {
173
173
  plan = JSON.parse(fs.readFileSync(file, 'utf8'));
174
- } catch (error: any) {
174
+ } catch (error ) {
175
175
  throw new Error(`the retrieval plan at '${file}' is not readable: ${error.message}`);
176
176
  }
177
177
  for (const need of plan.needs || []) {
@@ -198,7 +198,7 @@ function unreachedItems(projectRoot: any, taskId: any, verification: any, slug:
198
198
  * @param {string} flag the flag name, for the refusal
199
199
  * @returns {{value: string, stated: boolean}}
200
200
  */
201
- function statedVerdict(value: any, vocabulary: any, flag: any) {
201
+ function statedVerdict(value , vocabulary , flag ) {
202
202
  if (value === undefined || value === null || String(value).trim() === '') {
203
203
  return { value: NOT_RECORDED, stated: false };
204
204
  }
@@ -226,7 +226,7 @@ function statedVerdict(value: any, vocabulary: any, flag: any) {
226
226
  *
227
227
  * @returns {number} exit code
228
228
  */
229
- function recordOutcome({ projectRoot, packageRoot, taskId, taskClass, stage, state, readiness, verification, json, slug }: any) {
229
+ function recordOutcome({ projectRoot, packageRoot, taskId, taskClass, stage, state, readiness, verification, json, slug } ) {
230
230
  if (state === undefined || state === null || String(state).trim() === '') {
231
231
  return usageError('outcome',
232
232
  `--action record needs --state <state>. Valid: ${OUTCOME_STATES.join(', ')}`, json);
@@ -249,7 +249,7 @@ function recordOutcome({ projectRoot, packageRoot, taskId, taskClass, stage, sta
249
249
  let workflow;
250
250
  try {
251
251
  workflow = new WorkflowEngine({ repoRoot: packageRoot }).resolveWorkflow(taskClass);
252
- } catch (error: any) {
252
+ } catch (error ) {
253
253
  return usageError('outcome', error.message, json, error);
254
254
  }
255
255
  const terminalStage = workflow.terminalStage;
@@ -266,7 +266,7 @@ function recordOutcome({ projectRoot, packageRoot, taskId, taskClass, stage, sta
266
266
  try {
267
267
  basisReadiness = statedVerdict(readiness, READINESS_STATES, '--readiness');
268
268
  basisVerification = statedVerdict(verification, VERIFICATION_STATUSES, '--verification');
269
- } catch (error: any) {
269
+ } catch (error ) {
270
270
  return usageError('outcome', error.message, json, error);
271
271
  }
272
272
 
@@ -275,7 +275,7 @@ function recordOutcome({ projectRoot, packageRoot, taskId, taskClass, stage, sta
275
275
  try {
276
276
  evidenceCount = countEvidence(projectRoot, taskId, slug);
277
277
  unreached = unreachedItems(projectRoot, taskId, basisVerification.value, slug);
278
- } catch (error: any) {
278
+ } catch (error ) {
279
279
  return usageError('outcome', error.message, json, error);
280
280
  }
281
281
 
@@ -331,11 +331,11 @@ function recordOutcome({ projectRoot, packageRoot, taskId, taskClass, stage, sta
331
331
  *
332
332
  * @returns {number} exit code
333
333
  */
334
- function showOutcome({ projectRoot, taskId, json, slug }: any) {
334
+ function showOutcome({ projectRoot, taskId, json, slug } ) {
335
335
  let record;
336
336
  try {
337
337
  record = readOutcome(projectRoot, taskId, slug);
338
- } catch (error: any) {
338
+ } catch (error ) {
339
339
  return usageError('outcome', error.message, json, error);
340
340
  }
341
341
  if (!record) {
@@ -365,7 +365,7 @@ function showOutcome({ projectRoot, taskId, json, slug }: any) {
365
365
  }
366
366
 
367
367
  /** The one text rendering both actions print, so a shown record reads exactly as the written one. */
368
- function printOutcome(record: any, file: any, verb: any) {
368
+ function printOutcome(record , file , verb ) {
369
369
  const basis = record.basis || {};
370
370
  console.log(`\nDoFlow Task Outcome [Task: ${record.taskId}] — ${record.state}:`);
371
371
  console.log('═'.repeat(78));
@@ -413,7 +413,7 @@ function printOutcome(record: any, file: any, verb: any) {
413
413
  * @param {string} [options.stateRoot] the project the task belongs to, holding its state
414
414
  * @returns {number} exit code
415
415
  */
416
- function handleOutcomeCommand(options: any = {}) {
416
+ function handleOutcomeCommand(options = {}) {
417
417
  const {
418
418
  taskId, action = 'show', state, taskClass, stage, readiness, verification,
419
419
  json = false, repoRoot, stateRoot, slug,
@@ -424,7 +424,7 @@ function handleOutcomeCommand(options: any = {}) {
424
424
  // option object, so a second input surface cannot arrive later without inheriting the refusal.
425
425
  try {
426
426
  assertNoScoreFields(options, '');
427
- } catch (error: any) {
427
+ } catch (error ) {
428
428
  return usageError('outcome', error.message, json, error);
429
429
  }
430
430
 
@@ -443,7 +443,7 @@ function handleOutcomeCommand(options: any = {}) {
443
443
 
444
444
  try {
445
445
  assertSafeTaskId(taskId);
446
- } catch (error: any) {
446
+ } catch (error ) {
447
447
  return usageError('outcome', error.message, json, error);
448
448
  }
449
449
 
@@ -15,7 +15,7 @@
15
15
  const fs = require('node:fs');
16
16
  const os = require('node:os');
17
17
  const path = require('node:path');
18
- const { readLedger, stateRoot } = require('../state/index.ts');
18
+ const { readLedger, stateRoot } = require('../state/index.js');
19
19
 
20
20
  /** Where the dispatcher sits under a `.doflow` root; the skill resolver and the locator shim spell the same path. */
21
21
  const REACH_DISPATCHER_REL = 'scripts/doflow/bin/doflow-run';
@@ -23,18 +23,18 @@ const REACH_DISPATCHER_REL = 'scripts/doflow/bin/doflow-run';
23
23
  const REACH_RUNTIME_REL = 'runtime/bin/doflow.js';
24
24
 
25
25
  /** `dir`, then each parent, ending when the parent is the directory itself (`/`, `C:\`). */
26
- function* ancestors(dir: string): Generator<string> {
26
+ function* ancestors(dir ) {
27
27
  for (let current = dir; ; current = path.dirname(current)) {
28
28
  yield current;
29
29
  if (path.dirname(current) === current) return;
30
30
  }
31
31
  }
32
32
 
33
- function statIs(fsImpl: any, target: string, kind: string): boolean {
33
+ function statIs(fsImpl , target , kind ) {
34
34
  try { return fsImpl.statSync(target)[kind](); } catch { return false; }
35
35
  }
36
36
 
37
- function isExecutableFile(fsImpl: any, target: string): boolean {
37
+ function isExecutableFile(fsImpl , target ) {
38
38
  if (!statIs(fsImpl, target, 'isFile')) return false;
39
39
  try { fsImpl.accessSync(target, fs.constants.X_OK); return true; } catch { return false; }
40
40
  }
@@ -47,8 +47,8 @@ function isExecutableFile(fsImpl: any, target: string): boolean {
47
47
  * @param {Object} [options.fsImpl]
48
48
  * @returns {{rows: Array<{harness: string, scope: 'project'|'global', installRoot: string, state: 'REACHED'|'NO-REACH'|'N/A', root?: string, reason?: string, fix?: string}>, unreadable: Array<{scope: string, ledger: string, detail: string}>}}
49
49
  */
50
- function evaluateReach({ registry, projectRoot, homeDir = os.homedir(), fsImpl = fs }: { registry: any; projectRoot: string; homeDir?: string; fsImpl?: any }): { rows: any[]; unreadable: any[] } {
51
- const real = (target: string): string => { try { return fsImpl.realpathSync(target); } catch { return path.resolve(target); } };
50
+ function evaluateReach({ registry, projectRoot, homeDir = os.homedir(), fsImpl = fs } ) {
51
+ const real = (target ) => { try { return fsImpl.realpathSync(target); } catch { return path.resolve(target); } };
52
52
  const start = real(projectRoot);
53
53
  const home = real(homeDir);
54
54
  const homeDoflow = path.join(home, '.doflow');
@@ -57,14 +57,14 @@ function evaluateReach({ registry, projectRoot, homeDir = os.homedir(), fsImpl =
57
57
  // Every ledger on the walk is read, not only the nearest: a removed harness's residue in a
58
58
  // subdirectory must not hide the install that encloses it. The walk stops at the home directory,
59
59
  // whose own ledger is the global scope; nothing above it is read.
60
- const scopes: any[] = [];
60
+ const scopes = [];
61
61
  if (start !== home) {
62
- const walk: string[] = [];
62
+ const walk = [];
63
63
  for (const dir of ancestors(start)) {
64
64
  if (dir === home) break;
65
65
  walk.push(dir);
66
66
  }
67
- for (const installRoot of walk.filter((dir: string) => statIs(fsImpl, path.join(dir, '.doflow', 'state'), 'isDirectory'))) {
67
+ for (const installRoot of walk.filter((dir ) => statIs(fsImpl, path.join(dir, '.doflow', 'state'), 'isDirectory'))) {
68
68
  scopes.push({
69
69
  scope: 'project',
70
70
  installRoot,
@@ -72,7 +72,7 @@ function evaluateReach({ registry, projectRoot, homeDir = os.homedir(), fsImpl =
72
72
  from: start,
73
73
  searched: `${path.join(start, '.doflow', REACH_DISPATCHER_REL)} and each directory above it, then ${homeDispatcher}`,
74
74
  doflowDirs: [...ancestors(start)].map((dir) => path.join(dir, '.doflow')).concat(homeDoflow),
75
- fix: (harness: string) => `npx @khoavu882/doflow install ${installRoot} -t ${harness}`,
75
+ fix: (harness ) => `npx @khoavu882/doflow install ${installRoot} -t ${harness}`,
76
76
  });
77
77
  }
78
78
  }
@@ -83,14 +83,14 @@ function evaluateReach({ registry, projectRoot, homeDir = os.homedir(), fsImpl =
83
83
  from: home,
84
84
  searched: homeDispatcher,
85
85
  doflowDirs: [homeDoflow],
86
- fix: (harness: string) => `npx @khoavu882/doflow install -g -t ${harness}`,
86
+ fix: (harness ) => `npx @khoavu882/doflow install -g -t ${harness}`,
87
87
  });
88
88
 
89
- const harnessIds = registry.harnesses.map((harness: any) => harness.id);
90
- const rows: any[] = [];
91
- const unreadable: any[] = [];
92
- const seen = new Set<string>();
93
- const addRow = (row: any): void => {
89
+ const harnessIds = registry.harnesses.map((harness ) => harness.id);
90
+ const rows = [];
91
+ const unreadable = [];
92
+ const seen = new Set ();
93
+ const addRow = (row ) => {
94
94
  // A stale outer ledger that says what a nearer one already said adds nothing.
95
95
  const key = JSON.stringify([row.harness, row.scope, row.state, row.root, row.reason]);
96
96
  if (seen.has(key)) return;
@@ -99,20 +99,20 @@ function evaluateReach({ registry, projectRoot, homeDir = os.homedir(), fsImpl =
99
99
  };
100
100
 
101
101
  for (const { scope, installRoot, stateDir, from, searched, doflowDirs, fix } of scopes) {
102
- let ledger: any;
102
+ let ledger ;
103
103
  try {
104
104
  ledger = readLedger(stateDir, { fsImpl });
105
- } catch (error: any) {
105
+ } catch (error ) {
106
106
  unreadable.push({ scope, ledger: stateDir, detail: error.message });
107
107
  continue;
108
108
  }
109
109
  if (!ledger) continue;
110
110
 
111
111
  const resources = ledger.resources || [];
112
- const installed = harnessIds.filter((id: string) => resources.some((resource: any) => resource.harness === id));
112
+ const installed = harnessIds.filter((id ) => resources.some((resource ) => resource.harness === id));
113
113
  if (!installed.length) continue;
114
114
 
115
- const root = doflowDirs.find((dir: string) => isExecutableFile(fsImpl, path.join(dir, REACH_DISPATCHER_REL)));
115
+ const root = doflowDirs.find((dir ) => isExecutableFile(fsImpl, path.join(dir, REACH_DISPATCHER_REL)));
116
116
  const dispatcher = root && path.join(root, REACH_DISPATCHER_REL);
117
117
  const configDir = [...ancestors(from)].map((dir) => path.join(dir, '.doflow')).find((dir) => statIs(fsImpl, dir, 'isDirectory'));
118
118
  const runtime = [configDir, homeDoflow].filter(Boolean).some((dir) => statIs(fsImpl, path.join(dir, REACH_RUNTIME_REL), 'isFile'));
@@ -121,7 +121,7 @@ function evaluateReach({ registry, projectRoot, homeDir = os.homedir(), fsImpl =
121
121
  const hiddenBy = scope === 'project' && configDir && configDir !== path.join(installRoot, '.doflow') ? configDir : null;
122
122
 
123
123
  for (const harness of installed) {
124
- if (!resources.some((resource: any) => resource.harness === harness && resource.assetId === 'skills.doflow')) {
124
+ if (!resources.some((resource ) => resource.harness === harness && resource.assetId === 'skills.doflow')) {
125
125
  addRow({ harness, scope, installRoot, state: 'N/A', reason: `no skills at ${scope} scope` });
126
126
  } else if (dispatcher && runtime) {
127
127
  addRow({ harness, scope, installRoot, state: 'REACHED', root });
@@ -4,9 +4,9 @@
4
4
 
5
5
  const fs = require('node:fs');
6
6
  const path = require('node:path');
7
- const { updateTaskState } = require('./task-state.ts');
8
- const { resolveTaskScope } = require('./task-scope.ts');
9
- const { findStateFile } = require('./checkouts.ts');
7
+ const { updateTaskState } = require('./task-state.js');
8
+ const { resolveTaskScope } = require('./task-scope.js');
9
+ const { findStateFile } = require('./checkouts.js');
10
10
 
11
11
  // The readiness record: the latest evaluation of one task, kept where `readiness` ran.
12
12
  //
@@ -26,19 +26,19 @@ const STORE = path.join('.doflow', 'state', 'readiness');
26
26
  * @param {string|null} slug the task's feature slug, when one is known
27
27
  * @returns {Array<string>} paths relative to a checkout root
28
28
  */
29
- function recordCandidates(taskId: string, slug: any) {
29
+ function recordCandidates(taskId , slug ) {
30
30
  const flat = path.join(STORE, `${taskId}.json`);
31
31
  return slug && slug !== taskId ? [path.join(STORE, slug, `${taskId}.json`), flat] : [flat];
32
32
  }
33
33
 
34
34
  /** A record version this runtime cannot read because a newer DoFlow wrote it, else null. */
35
- function newerVersionOf(record: any) {
35
+ function newerVersionOf(record ) {
36
36
  const v = record && typeof record === 'object' ? record.version : undefined;
37
37
  return Number.isInteger(v) && v > RECORD_VERSION ? v : null;
38
38
  }
39
39
 
40
40
  /** The refusal for a record a newer DoFlow wrote: it names the file and is never overwritten. */
41
- function newerRecordText(file: any, version: any) {
41
+ function newerRecordText(file , version ) {
42
42
  return `the readiness record ${file} was written by a newer DoFlow (record version ${version}; this runtime reads ${RECORD_VERSION}), `
43
43
  + 'so it was left as it is. Run this command with the DoFlow that wrote the record, or upgrade DoFlow here.';
44
44
  }
@@ -48,11 +48,11 @@ function newerRecordText(file: any, version: any) {
48
48
  * wrote, or bytes no evaluation can be read from.
49
49
  * @returns {{kind: 'none'|'record'|'newer'|'unreadable', version?: number}}
50
50
  */
51
- function priorRecord(file: any, fsImpl: any) {
51
+ function priorRecord(file , fsImpl ) {
52
52
  let text;
53
53
  try {
54
54
  text = fsImpl.readFileSync(file, 'utf8');
55
- } catch (error: any) {
55
+ } catch (error ) {
56
56
  if (error.code === 'ENOENT') return { kind: 'none' };
57
57
  throw error;
58
58
  }
@@ -86,7 +86,7 @@ function priorRecord(file: any, fsImpl: any) {
86
86
  * @returns {{file: string, record: Object, replacedUnreadable: string|null}} the `.unreadable` path when
87
87
  * a previous file was set aside
88
88
  */
89
- function writeReadinessRecord({ stateRoot, taskId, slug = null, report, inputs, declaredScope = null, mode, now = new Date(), fsImpl = fs }: any) {
89
+ function writeReadinessRecord({ stateRoot, taskId, slug = null, report, inputs, declaredScope = null, mode, now = new Date(), fsImpl = fs } ) {
90
90
  const scope = resolveTaskScope({ projectRoot: stateRoot, taskId, slug });
91
91
  const recordSlug = scope.slug || slug || null;
92
92
  // The record a reader would find in this checkout is the one replaced; with none, the record goes
@@ -104,7 +104,7 @@ function writeReadinessRecord({ stateRoot, taskId, slug = null, report, inputs,
104
104
  executionMode: mode,
105
105
  inputs: { ...inputs },
106
106
  declaredScope: Array.isArray(declaredScope) ? [...declaredScope] : null,
107
- unmet: (report.requirements || []).filter((r: any) => r.required && !r.satisfied).map((r: any) => r.id),
107
+ unmet: (report.requirements || []).filter((r ) => r.required && !r.satisfied).map((r ) => r.id),
108
108
  evidenceCount: Number.isInteger(report.evidenceCount) ? report.evidenceCount : 0,
109
109
  evaluatedAt: now.toISOString(),
110
110
  };
@@ -136,13 +136,13 @@ function writeReadinessRecord({ stateRoot, taskId, slug = null, report, inputs,
136
136
  * @returns {{status: 'found'|'missing'|'ambiguous'|'unreadable', record: Object|null, file: string|null,
137
137
  * origin: 'current'|'other'|null, candidates: Array<string>, detail: string|null}}
138
138
  */
139
- function readReadinessRecord({ stateRoot, taskId, slug = null, exec, fsImpl = fs }: any) {
139
+ function readReadinessRecord({ stateRoot, taskId, slug = null, exec, fsImpl = fs } ) {
140
140
  const found = findStateFile({ stateRoot, relPath: recordCandidates(taskId, slug), ...(exec ? { exec } : {}), fsImpl });
141
141
  const base = { record: null, file: found.file, origin: found.origin, candidates: found.candidates, detail: null };
142
142
  if (found.status !== 'found') return { ...base, status: found.status };
143
143
  try {
144
144
  return { ...base, status: 'found', record: JSON.parse(fsImpl.readFileSync(found.file, 'utf8')) };
145
- } catch (error: any) {
145
+ } catch (error ) {
146
146
  return { ...base, status: 'unreadable', detail: `unparsable JSON: ${error.message}` };
147
147
  }
148
148
  }