@khoavu882/doflow 2.0.0-beta.3 → 2.0.0-beta.4

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 (167) hide show
  1. package/bin/doflow.js +2 -2
  2. package/core/.claude-plugin/plugin.json +1 -1
  3. package/core/.codex-plugin/plugin.json +1 -1
  4. package/core/.plugin/plugin.json +1 -1
  5. package/core/registry/storage.json +87 -83
  6. package/core/registry/verification.json +1 -1
  7. package/core/shared/scripts/doflow/bash/render-puml.sh +2 -2
  8. package/core/shared/skills/do-execute-plan/references/scaffold.md +2 -2
  9. package/package.json +4 -2
  10. package/src/adapters/antigravity/{index.ts → index.js} +60 -60
  11. package/src/adapters/claude/{index.ts → index.js} +48 -48
  12. package/src/adapters/claude/{mcp.ts → mcp.js} +16 -16
  13. package/src/adapters/codex/{agents.ts → agents.js} +24 -24
  14. package/src/adapters/codex/{config.ts → config.js} +49 -49
  15. package/src/adapters/codex/{hooks.ts → hooks.js} +23 -23
  16. package/src/adapters/codex/{index.ts → index.js} +98 -98
  17. package/src/adapters/codex/{mcp.ts → mcp.js} +38 -38
  18. package/src/adapters/codex/{native-projection.ts → native-projection.js} +5 -5
  19. package/src/adapters/copilot/{index.ts → index.js} +42 -42
  20. package/src/adapters/{copy-tree.ts → copy-tree.js} +70 -70
  21. package/src/adapters/gemini/{hooks.ts → hooks.js} +24 -24
  22. package/src/adapters/gemini/{index.ts → index.js} +41 -41
  23. package/src/adapters/{hook-commands.ts → hook-commands.js} +8 -8
  24. package/src/adapters/{index.ts → index.js} +13 -13
  25. package/src/adapters/kiro/{index.ts → index.js} +34 -34
  26. package/src/adapters/{mcp-entries.ts → mcp-entries.js} +55 -55
  27. package/src/adapters/opencode/{index.ts → index.js} +52 -52
  28. package/src/adapters/pi/{index.ts → index.js} +30 -30
  29. package/src/adapters/pi/{json-members.ts → json-members.js} +23 -23
  30. package/src/adapters/pi/{mcp.ts → mcp.js} +70 -70
  31. package/src/adapters/{resolve-source.ts → resolve-source.js} +1 -1
  32. package/src/cli/commands/{install.ts → install.js} +24 -24
  33. package/src/cli/commands/{list-backups.ts → list-backups.js} +4 -4
  34. package/src/cli/commands/{reconcile.ts → reconcile.js} +19 -19
  35. package/src/cli/commands/{remove.ts → remove.js} +10 -10
  36. package/src/cli/commands/{rollback.ts → rollback.js} +17 -17
  37. package/src/cli/commands/{self-update.ts → self-update.js} +3 -3
  38. package/src/cli/commands/{status.ts → status.js} +24 -24
  39. package/src/cli/commands/{tools.ts → tools.js} +16 -16
  40. package/src/cli/commands/{update.ts → update.js} +19 -19
  41. package/src/cli/{index.ts → index.js} +26 -26
  42. package/src/cli/{runtime-commands.ts → runtime-commands.js} +48 -48
  43. package/src/cli/{shared.ts → shared.js} +40 -40
  44. package/src/helper/{bash-helper.ts → bash-helper.js} +7 -7
  45. package/src/helper/{git.ts → git.js} +2 -2
  46. package/src/helper/{guardrails.ts → guardrails.js} +10 -10
  47. package/src/helper/{harness-paths.ts → harness-paths.js} +24 -24
  48. package/src/helper/{marker-merge.ts → marker-merge.js} +4 -4
  49. package/src/helper/{prompt.ts → prompt.js} +5 -5
  50. package/src/helper/{repo-root.ts → repo-root.js} +2 -2
  51. package/src/helper/{settings-merge.ts → settings-merge.js} +27 -27
  52. package/src/helper/{settings-scope.ts → settings-scope.js} +3 -3
  53. package/src/helper/{toml.ts → toml.js} +48 -48
  54. package/src/install/{backup-set.ts → backup-set.js} +16 -16
  55. package/src/install/{backup.ts → backup.js} +65 -65
  56. package/src/install/{context.ts → context.js} +15 -15
  57. package/src/install/{manifest.ts → manifest.js} +27 -27
  58. package/src/install/{mcp.ts → mcp.js} +30 -30
  59. package/src/install/{paths.ts → paths.js} +15 -15
  60. package/src/install/{targets.ts → targets.js} +10 -10
  61. package/src/install/{tool-lifecycle.ts → tool-lifecycle.js} +20 -20
  62. package/src/lifecycle/{bash-availability.ts → bash-availability.js} +1 -1
  63. package/src/lifecycle/{index.ts → index.js} +140 -140
  64. package/src/lifecycle/{mcp-index.ts → mcp-index.js} +1 -1
  65. package/src/lifecycle/{policies.ts → policies.js} +11 -11
  66. package/src/lifecycle/{view.ts → view.js} +28 -28
  67. package/src/registry/{index.ts → index.js} +60 -60
  68. package/src/release/build-package.js +91 -0
  69. package/src/release/changelog-section.js +70 -0
  70. package/src/release/{sync-plugin-versions.ts → sync-plugin-versions.js} +4 -4
  71. package/src/runtime/advice/{cli.ts → cli.js} +31 -31
  72. package/src/runtime/advice/{client.ts → client.js} +44 -44
  73. package/src/runtime/advice/{config.ts → config.js} +16 -16
  74. package/src/runtime/advice/{doctor.ts → doctor.js} +32 -32
  75. package/src/runtime/advice/{endpoint-guard.ts → endpoint-guard.js} +20 -20
  76. package/src/runtime/advice/{kinds.ts → kinds.js} +16 -16
  77. package/src/runtime/advice/providers/{ollama-systemone.ts → ollama-systemone.js} +21 -21
  78. package/src/runtime/advice/{record.ts → record.js} +19 -19
  79. package/src/runtime/advice/{registry.ts → registry.js} +16 -16
  80. package/src/runtime/advice/{strength.ts → strength.js} +7 -7
  81. package/src/runtime/{brief-tools.ts → brief-tools.js} +50 -50
  82. package/src/runtime/{c4-project.ts → c4-project.js} +27 -27
  83. package/src/runtime/{capability-router.ts → capability-router.js} +39 -39
  84. package/src/runtime/{checkouts.ts → checkouts.js} +21 -21
  85. package/src/runtime/{claims.ts → claims.js} +30 -30
  86. package/src/runtime/{cli-result.ts → cli-result.js} +4 -4
  87. package/src/runtime/{cli.ts → cli.js} +37 -37
  88. package/src/runtime/{command-detect.ts → command-detect.js} +47 -47
  89. package/src/runtime/{context-pack.ts → context-pack.js} +20 -20
  90. package/src/runtime/{decision-register.ts → decision-register.js} +67 -67
  91. package/src/runtime/{evidence-ledger.ts → evidence-ledger.js} +25 -25
  92. package/src/runtime/failure/{capture.ts → capture.js} +29 -29
  93. package/src/runtime/failure/{classifier.ts → classifier.js} +4 -4
  94. package/src/runtime/failure/{cli.ts → cli.js} +30 -30
  95. package/src/runtime/failure/{home.ts → home.js} +6 -6
  96. package/src/runtime/failure/{store.ts → store.js} +32 -32
  97. package/src/runtime/{feature-resolve.ts → feature-resolve.js} +6 -6
  98. package/src/runtime/{freshness.ts → freshness.js} +15 -15
  99. package/src/runtime/{health.ts → health.js} +72 -72
  100. package/src/runtime/{history-compactor.ts → history-compactor.js} +25 -25
  101. package/src/runtime/{implementation-gate.ts → implementation-gate.js} +30 -30
  102. package/src/runtime/inventory/{coverage.ts → coverage.js} +10 -10
  103. package/src/runtime/inventory/{identity.ts → identity.js} +2 -2
  104. package/src/runtime/inventory/{index.ts → index.js} +36 -36
  105. package/src/runtime/inventory/{precedence.ts → precedence.js} +2 -2
  106. package/src/runtime/inventory/{read-scopes.ts → read-scopes.js} +9 -9
  107. package/src/runtime/inventory/{siblings.ts → siblings.js} +15 -15
  108. package/src/runtime/knowledge/{chunker.ts → chunker.js} +12 -12
  109. package/src/runtime/knowledge/{hybrid.ts → hybrid.js} +17 -17
  110. package/src/runtime/knowledge/{index-store.ts → index-store.js} +23 -23
  111. package/src/runtime/knowledge/{retrieval.ts → retrieval.js} +27 -27
  112. package/src/runtime/{leak-scan.ts → leak-scan.js} +12 -12
  113. package/src/runtime/lifecycle/{cli.ts → cli.js} +32 -32
  114. package/src/runtime/lifecycle/{event-store.ts → event-store.js} +48 -48
  115. package/src/runtime/lifecycle/{fold.ts → fold.js} +41 -41
  116. package/src/runtime/lifecycle/{followup.ts → followup.js} +54 -54
  117. package/src/runtime/lifecycle/{goal.ts → goal.js} +50 -50
  118. package/src/runtime/lifecycle/{intent-writer.ts → intent-writer.js} +5 -5
  119. package/src/runtime/lifecycle/{overview.ts → overview.js} +47 -47
  120. package/src/runtime/lifecycle/{release.ts → release.js} +29 -29
  121. package/src/runtime/lifecycle/{report-store.ts → report-store.js} +25 -25
  122. package/src/runtime/lifecycle/{retention.ts → retention.js} +37 -37
  123. package/src/runtime/lifecycle/{root.ts → root.js} +9 -9
  124. package/src/runtime/lifecycle/{status.ts → status.js} +64 -64
  125. package/src/runtime/lifecycle/{store-upkeep.ts → store-upkeep.js} +46 -46
  126. package/src/runtime/{locator-resolve.ts → locator-resolve.js} +7 -7
  127. package/src/runtime/{mask.ts → mask.js} +22 -22
  128. package/src/runtime/{mcp-consultations.ts → mcp-consultations.js} +54 -54
  129. package/src/runtime/{mcp-reach.ts → mcp-reach.js} +24 -24
  130. package/src/runtime/{model-router.ts → model-router.js} +20 -20
  131. package/src/runtime/{outcome.ts → outcome.js} +27 -27
  132. package/src/runtime/{reach.ts → reach.js} +21 -21
  133. package/src/runtime/{readiness-record.ts → readiness-record.js} +12 -12
  134. package/src/runtime/{readiness.ts → readiness.js} +35 -35
  135. package/src/runtime/{recovery.ts → recovery.js} +15 -15
  136. package/src/runtime/{research-request.ts → research-request.js} +34 -34
  137. package/src/runtime/{retrieval-plan.ts → retrieval-plan.js} +40 -40
  138. package/src/runtime/scaffold/{artifacts.ts → artifacts.js} +19 -19
  139. package/src/runtime/scaffold/{fingerprint.ts → fingerprint.js} +3 -3
  140. package/src/runtime/scaffold/{generate.ts → generate.js} +109 -109
  141. package/src/runtime/scaffold/{languages.ts → languages.js} +34 -34
  142. package/src/runtime/storage/{cli.ts → cli.js} +9 -9
  143. package/src/runtime/storage/{engine.ts → engine.js} +37 -37
  144. package/src/runtime/storage/{registry.ts → registry.js} +19 -19
  145. package/src/runtime/storage/{roots.ts → roots.js} +8 -8
  146. package/src/runtime/storage/{rules.ts → rules.js} +26 -26
  147. package/src/runtime/storage/{upkeep.ts → upkeep.js} +35 -35
  148. package/src/runtime/storage/{work-status.ts → work-status.js} +39 -39
  149. package/src/runtime/{task-attempts.ts → task-attempts.js} +61 -61
  150. package/src/runtime/{task-classifier.ts → task-classifier.js} +34 -34
  151. package/src/runtime/{task-scope.ts → task-scope.js} +13 -13
  152. package/src/runtime/{task-state.ts → task-state.js} +15 -15
  153. package/src/runtime/trace/{indicators.ts → indicators.js} +22 -22
  154. package/src/runtime/trace/{ledger.ts → ledger.js} +42 -42
  155. package/src/runtime/trace/{render.ts → render.js} +7 -7
  156. package/src/runtime/trace/{views.ts → views.js} +40 -40
  157. package/src/runtime/verification/{contract-runner.ts → contract-runner.js} +23 -23
  158. package/src/runtime/verification/{engine.ts → engine.js} +143 -143
  159. package/src/runtime/verification/{registry.ts → registry.js} +6 -6
  160. package/src/runtime/verification/{scope-bound.ts → scope-bound.js} +50 -50
  161. package/src/runtime/verification/{test-selection.ts → test-selection.js} +28 -28
  162. package/src/runtime/{workflow-engine.ts → workflow-engine.js} +50 -50
  163. package/src/runtime/{workflow-orchestrator.ts → workflow-orchestrator.js} +91 -91
  164. package/src/runtime/{worktree.ts → worktree.js} +31 -31
  165. package/src/state/{index.ts → index.js} +26 -26
  166. package/src/state/{lockfile.ts → lockfile.js} +20 -20
  167. package/src/state/{run-lock.ts → run-lock.js} +44 -44
@@ -4,9 +4,9 @@
4
4
 
5
5
  const fs = require('node:fs');
6
6
  const path = require('node:path');
7
- const { parseYamlFile } = require('./capability-router.ts');
8
- const { resolveLocator, describeResolution } = require('./locator-resolve.ts');
9
- const { REPO_ROOT } = require('../helper/repo-root.ts');
7
+ const { parseYamlFile } = require('./capability-router.js');
8
+ const { resolveLocator, describeResolution } = require('./locator-resolve.js');
9
+ const { REPO_ROOT } = require('../helper/repo-root.js');
10
10
 
11
11
  const READINESS_STATES = new Set([
12
12
  'READY',
@@ -37,7 +37,7 @@ const STAGE_ENTRY_DECISIONS = new Set(['ENTER', 'GATHER_FIRST', 'ASK_USER', 'STO
37
37
  * @param {string} [mode='workflow'] 'workflow' | 'standalone'
38
38
  * @returns {{decision: string, reason: string}}
39
39
  */
40
- function stageEntryFor(state: any, mode = 'workflow') {
40
+ function stageEntryFor(state , mode = 'workflow') {
41
41
  if (!EXECUTION_MODES.has(mode)) {
42
42
  throw new Error(`Unknown execution mode '${mode}'. Valid: ${[...EXECUTION_MODES].join(', ')} — the standalone exemption is declared, never inferred.`);
43
43
  }
@@ -60,11 +60,11 @@ function stageEntryFor(state: any, mode = 'workflow') {
60
60
  }
61
61
 
62
62
  class ReadinessEngine {
63
- declare fsImpl: any;
64
- declare repoRoot: any;
65
- declare projectRoot: any;
66
- declare templatePath: any;
67
- declare templates: any;
63
+
64
+
65
+
66
+
67
+
68
68
  /**
69
69
  * @param {Object} [options]
70
70
  * @param {string} [options.repoRoot] the DoFlow install, where readiness-templates.json lives
@@ -75,7 +75,7 @@ class ReadinessEngine {
75
75
  * @param {Object} [options.templates]
76
76
  * @param {Object} [options.fsImpl]
77
77
  */
78
- constructor(options: any = {}) {
78
+ constructor(options = {}) {
79
79
  this.fsImpl = options.fsImpl || fs;
80
80
  this.repoRoot = options.repoRoot || REPO_ROOT;
81
81
  this.projectRoot = options.projectRoot || process.cwd();
@@ -92,7 +92,7 @@ class ReadinessEngine {
92
92
  try {
93
93
  const data = parseYamlFile(this.templatePath, this.fsImpl);
94
94
  this.templates = data.templates || {};
95
- } catch (error: any) {
95
+ } catch (error ) {
96
96
  throw new Error(`Failed to load readiness templates from '${this.templatePath}': ${error.message}`);
97
97
  }
98
98
  }
@@ -104,7 +104,7 @@ class ReadinessEngine {
104
104
  * @param {Object} taskProfile
105
105
  * @returns {Object}
106
106
  */
107
- suggestAction(reqId: any, reqDef: any, taskProfile: any) {
107
+ suggestAction(reqId , reqDef , taskProfile ) {
108
108
  if (reqId === 'root_cause') {
109
109
  return {
110
110
  intent: 'trace-dependency',
@@ -152,7 +152,7 @@ class ReadinessEngine {
152
152
  * @param {Object} claimsManager
153
153
  * @returns {Object} ReadinessReport
154
154
  */
155
- evaluateReadiness(taskProfile: any, evidenceLedger: any, claimsManager: any) {
155
+ evaluateReadiness(taskProfile , evidenceLedger , claimsManager ) {
156
156
  if (!taskProfile || typeof taskProfile !== 'object') {
157
157
  throw new Error('taskProfile must be an object');
158
158
  }
@@ -206,7 +206,7 @@ class ReadinessEngine {
206
206
 
207
207
  // Inspect claims
208
208
  const taskClaims = claimsManager ? claimsManager.getClaims(taskId) : [];
209
- const conflictedClaims = taskClaims.filter((c: any) => c.status === 'conflicted');
209
+ const conflictedClaims = taskClaims.filter((c ) => c.status === 'conflicted');
210
210
  if (conflictedClaims.length > 0) {
211
211
  hasBlocked = true;
212
212
  }
@@ -225,8 +225,8 @@ class ReadinessEngine {
225
225
  // in evaluateClaim — it is not a claim that the file never changed. An item that genuinely went
226
226
  // stale and was never superseded still forces NEEDS_EVIDENCE exactly as before.
227
227
  const staleEvidence = (evidenceLedger ? evidenceLedger.getAllEvidence() : [])
228
- .filter((item: any) => item.taskId === taskId && item.freshness?.status === 'STALE' && item.status !== 'superseded')
229
- .map((item: any) => ({ evidenceId: item.id, locator: item.locator, reason: 'file-modified-since-recorded' }));
228
+ .filter((item ) => item.taskId === taskId && item.freshness?.status === 'STALE' && item.status !== 'superseded')
229
+ .map((item ) => ({ evidenceId: item.id, locator: item.locator, reason: 'file-modified-since-recorded' }));
230
230
 
231
231
  const unresolvableEvidence = [];
232
232
  for (const item of taskEvidence) {
@@ -242,7 +242,7 @@ class ReadinessEngine {
242
242
  }
243
243
  }
244
244
 
245
- for (const [reqId, reqDef] of Object.entries<any>(requirements)) {
245
+ for (const [reqId, reqDef] of Object.entries (requirements)) {
246
246
  let isSatisfied = false;
247
247
  let reason = null;
248
248
  let matchedEvidenceIds = [];
@@ -260,9 +260,9 @@ class ReadinessEngine {
260
260
  // not by any supported claim the task happens to hold (review R1 — a supported claim about an
261
261
  // unrelated invariant satisfied the bug template's root-cause requirement).
262
262
  else if (reqDef.requiresClaimStatus) {
263
- let matchingClaims = taskClaims.filter((c: any) => c.status === reqDef.requiresClaimStatus);
263
+ let matchingClaims = taskClaims.filter((c ) => c.status === reqDef.requiresClaimStatus);
264
264
  if (reqDef.requiresClaimRole) {
265
- const withRole = matchingClaims.filter((c: any) => c.role === reqDef.requiresClaimRole);
265
+ const withRole = matchingClaims.filter((c ) => c.role === reqDef.requiresClaimRole);
266
266
  if (withRole.length === 0 && matchingClaims.length > 0) {
267
267
  reason = `${matchingClaims.length} claim(s) have status '${reqDef.requiresClaimStatus}' but none `
268
268
  + `declares role '${reqDef.requiresClaimRole}' — add the claim with --role ${reqDef.requiresClaimRole}, `
@@ -272,7 +272,7 @@ class ReadinessEngine {
272
272
  }
273
273
  if (matchingClaims.length > 0) {
274
274
  isSatisfied = true;
275
- matchedEvidenceIds = matchingClaims.flatMap((c: any) => c.supportingEvidence);
275
+ matchedEvidenceIds = matchingClaims.flatMap((c ) => c.supportingEvidence);
276
276
  } else if (!reason) {
277
277
  reason = `Requires at least one claim with status '${reqDef.requiresClaimStatus}'`
278
278
  + `${reqDef.requiresClaimRole ? ` and role '${reqDef.requiresClaimRole}'` : ''}.`;
@@ -286,21 +286,21 @@ class ReadinessEngine {
286
286
  // (review R1, P1 — reproduced through the public CLI).
287
287
  else if (Array.isArray(reqDef.evidenceKinds) && reqDef.evidenceKinds.length > 0) {
288
288
  const allowedKinds = new Set(reqDef.evidenceKinds);
289
- const kindMatched = taskEvidence.filter((ev: any) => allowedKinds.has(ev.kind));
290
- const extracted = kindMatched.filter((ev: any) => ev.provenance === 'extracted');
291
- const bound = extracted.filter((ev: any) => Array.isArray(ev.establishes) && ev.establishes.includes(reqId));
289
+ const kindMatched = taskEvidence.filter((ev ) => allowedKinds.has(ev.kind));
290
+ const extracted = kindMatched.filter((ev ) => ev.provenance === 'extracted');
291
+ const bound = extracted.filter((ev ) => Array.isArray(ev.establishes) && ev.establishes.includes(reqId));
292
292
  let qualifying = bound;
293
293
  if (reqDef.requiresObservation) {
294
- qualifying = qualifying.filter((ev: any) => ev.observation && Number.isInteger(ev.observation.exitCode));
294
+ qualifying = qualifying.filter((ev ) => ev.observation && Number.isInteger(ev.observation.exitCode));
295
295
  if (reqDef.expectedExit === 'zero') {
296
- qualifying = qualifying.filter((ev: any) => ev.observation.exitCode === 0);
296
+ qualifying = qualifying.filter((ev ) => ev.observation.exitCode === 0);
297
297
  } else if (reqDef.expectedExit === 'nonzero') {
298
- qualifying = qualifying.filter((ev: any) => ev.observation.exitCode !== 0);
298
+ qualifying = qualifying.filter((ev ) => ev.observation.exitCode !== 0);
299
299
  }
300
300
  }
301
301
  if (qualifying.length > 0) {
302
302
  isSatisfied = true;
303
- matchedEvidenceIds = qualifying.map((ev: any) => ev.id);
303
+ matchedEvidenceIds = qualifying.map((ev ) => ev.id);
304
304
  } else if (kindMatched.length === 0) {
305
305
  reason = `Missing fresh evidence of kind: ${reqDef.evidenceKinds.join(', ')}.`;
306
306
  } else if (extracted.length === 0) {
@@ -310,8 +310,8 @@ class ReadinessEngine {
310
310
  reason = `${extracted.length} extracted item(s) of the right kind exist but none declares it `
311
311
  + `establishes '${reqId}' — record evidence with establishes: ['${reqId}'] so the gate grades `
312
312
  + 'what the item was actually gathered to prove.';
313
- } else if (reqDef.expectedExit === 'zero' && bound.some((ev: any) => ev.observation && ev.observation.exitCode !== 0)) {
314
- const failed = bound.find((ev: any) => ev.observation && ev.observation.exitCode !== 0);
313
+ } else if (reqDef.expectedExit === 'zero' && bound.some((ev ) => ev.observation && ev.observation.exitCode !== 0)) {
314
+ const failed = bound.find((ev ) => ev.observation && ev.observation.exitCode !== 0);
315
315
  reason = `The bound observation ran '${failed.observation.command}' and exited ${failed.observation.exitCode}; `
316
316
  + 'this requirement needs an exit status of 0. A failed run does not establish a passing baseline.';
317
317
  } else {
@@ -392,8 +392,8 @@ class ReadinessEngine {
392
392
  requirements: requirementResults,
393
393
  claimsSummary: {
394
394
  total: taskClaims.length,
395
- supported: taskClaims.filter((c: any) => c.status === 'supported').length,
396
- hypotheses: taskClaims.filter((c: any) => c.status === 'hypothesis').length,
395
+ supported: taskClaims.filter((c ) => c.status === 'supported').length,
396
+ hypotheses: taskClaims.filter((c ) => c.status === 'hypothesis').length,
397
397
  conflicts: conflictedClaims.length,
398
398
  },
399
399
  evidenceCount: taskEvidence.length,
@@ -406,15 +406,15 @@ class ReadinessEngine {
406
406
  /** One live snapshot for readiness inspection and orchestration transitions. Reads never persist
407
407
  * derived freshness or claim status; every invocation evaluates the current project again.
408
408
  * `mode` defaults to 'workflow' — fail closed: the standalone exemption must be declared. */
409
- function evaluateTaskReadiness({ taskProfile, repoRoot = REPO_ROOT, projectRoot = process.cwd(), mode = 'workflow' }: any) {
409
+ function evaluateTaskReadiness({ taskProfile, repoRoot = REPO_ROOT, projectRoot = process.cwd(), mode = 'workflow' } ) {
410
410
  // Validated before any ledger work, not just inside stageEntryFor at the end — an invalid mode
411
411
  // used to pay a full freshness/claims evaluation before erroring (review suggestion, 026).
412
412
  if (!EXECUTION_MODES.has(mode)) {
413
413
  throw new Error(`Unknown execution mode '${mode}'. Valid: ${[...EXECUTION_MODES].join(', ')} — the standalone exemption is declared, never inferred.`);
414
414
  }
415
- const { EvidenceLedger } = require('./evidence-ledger.ts');
416
- const { ClaimsManager } = require('./claims.ts');
417
- const { FreshnessValidator } = require('./freshness.ts');
415
+ const { EvidenceLedger } = require('./evidence-ledger.js');
416
+ const { ClaimsManager } = require('./claims.js');
417
+ const { FreshnessValidator } = require('./freshness.js');
418
418
  const ledger = new EvidenceLedger({ repoRoot: projectRoot });
419
419
  ledger.load(taskProfile.taskId);
420
420
  new FreshnessValidator({ repoRoot: projectRoot }).validateLedgerFreshness(ledger);
@@ -20,10 +20,10 @@
20
20
  * names either raised or silently iterated characters.
21
21
  */
22
22
 
23
- const { finishRuntime, usageError } = require('./cli-result.ts');
23
+ const { finishRuntime, usageError } = require('./cli-result.js');
24
24
 
25
25
  /** The eleven classes, in the order the Python declared them. */
26
- const FAILURE_CLASSES: readonly string[] = Object.freeze([
26
+ const FAILURE_CLASSES = Object.freeze([
27
27
  'CONTEXT_MISSING',
28
28
  'WRONG_IMPLEMENTATION',
29
29
  'TEST_FAILURE',
@@ -40,9 +40,9 @@ const FAILURE_CLASSES: readonly string[] = Object.freeze([
40
40
  const DEFAULT_MAX_ITERATIONS = 3;
41
41
 
42
42
  /** Check-name fragments that identify a build-stage failure regardless of the error text. */
43
- const BUILD_CHECK_MARKERS: readonly string[] = Object.freeze(['syntax', 'compile', 'build']);
43
+ const BUILD_CHECK_MARKERS = Object.freeze(['syntax', 'compile', 'build']);
44
44
  /** Check-name fragments that identify a test-stage failure. */
45
- const TEST_CHECK_MARKERS: readonly string[] = Object.freeze(['test', 'unit']);
45
+ const TEST_CHECK_MARKERS = Object.freeze(['test', 'unit']);
46
46
 
47
47
  /**
48
48
  * Per-class recovery strategy — **one entry per class, all eleven** (plan task C.2).
@@ -68,7 +68,7 @@ const TEST_CHECK_MARKERS: readonly string[] = Object.freeze(['test', 'unit']);
68
68
  * already been spent (its `current_iteration >= 2`). `terminal` is new and means the class is not
69
69
  * retryable at any iteration.
70
70
  */
71
- const STRATEGY_MAP: Readonly<Record<string, any>> = Object.freeze({
71
+ const STRATEGY_MAP = Object.freeze({
72
72
  CONTEXT_MISSING: { action: 'RETRIEVE_MORE_CONTEXT', targetRole: 'SCOUT', switchAtIteration: null },
73
73
  WRONG_IMPLEMENTATION: { action: 'REVISE_IMPLEMENTATION', targetRole: 'IMPLEMENTER', switchAtIteration: 2 },
74
74
  TEST_FAILURE: { action: 'TARGETED_DEBUGGER_FIX', targetRole: 'DEBUGGER', switchAtIteration: 2 },
@@ -86,7 +86,7 @@ const STRATEGY_MAP: Readonly<Record<string, any>> = Object.freeze({
86
86
  });
87
87
 
88
88
  /** Reachable only for a class string outside the eleven — see the note on STRATEGY_MAP. */
89
- const GENERIC_STRATEGY: Readonly<Record<string, any>> = Object.freeze({
89
+ const GENERIC_STRATEGY = Object.freeze({
90
90
  action: 'GENERIC_DEBUGGER_FIX',
91
91
  targetRole: 'DEBUGGER',
92
92
  switchAtIteration: 2,
@@ -96,23 +96,23 @@ const GENERIC_STRATEGY: Readonly<Record<string, any>> = Object.freeze({
96
96
  * @param {*} value
97
97
  * @returns {Array<string>} only the string members, lowercased
98
98
  */
99
- function normalizeCheckNames(value: any): string[] {
99
+ function normalizeCheckNames(value ) {
100
100
  // Defect fix (2a): the Python accepted `failed_checks` unvalidated. Handed a plain string it
101
101
  // iterated characters, so every single-letter "check" was tested for "syntax" and none matched —
102
102
  // a build failure silently classified as WRONG_IMPLEMENTATION.
103
103
  if (!Array.isArray(value)) return [];
104
- return value.filter((v: any) => typeof v === 'string').map((v: string) => v.toLowerCase());
104
+ return value.filter((v ) => typeof v === 'string').map((v ) => v.toLowerCase());
105
105
  }
106
106
 
107
107
  class RecoveryManager {
108
- maxIterations: number;
108
+ maxIterations ;
109
109
 
110
110
  /**
111
111
  * @param {Object|number} [options] a number is accepted for parity with the Python's positional
112
112
  * `max_iterations` argument
113
113
  * @param {number} [options.maxIterations=3]
114
114
  */
115
- constructor(options: any = {}) {
115
+ constructor(options = {}) {
116
116
  const opts = typeof options === 'number' ? { maxIterations: options } : options;
117
117
  this.maxIterations = opts.maxIterations || DEFAULT_MAX_ITERATIONS;
118
118
  }
@@ -126,13 +126,13 @@ class RecoveryManager {
126
126
  * @param {Array<string>} [failedChecks=[]]
127
127
  * @returns {string} one of FAILURE_CLASSES
128
128
  */
129
- classifyFailure(errorMessage: any, failedChecks: any = []): string {
129
+ classifyFailure(errorMessage , failedChecks = []) {
130
130
  const checks = normalizeCheckNames(failedChecks);
131
131
  // Defect fix (2b): `None.lower()` raised. A classifier handed no message should return
132
132
  // UNKNOWN_FAILURE, not abort the recovery path that exists to handle failures.
133
133
  const msg = typeof errorMessage === 'string' ? errorMessage.toLowerCase() : '';
134
134
 
135
- const anyCheck = (markers: readonly string[]) => checks.some((chk) => markers.some((m) => chk.includes(m)));
135
+ const anyCheck = (markers ) => checks.some((chk) => markers.some((m) => chk.includes(m)));
136
136
 
137
137
  if (anyCheck(BUILD_CHECK_MARKERS) || msg.includes('build error')) {
138
138
  return 'BUILD_FAILURE';
@@ -174,7 +174,7 @@ class RecoveryManager {
174
174
  * @param {string} [lastAgent='codex']
175
175
  * @returns {{ iteration: number, failureClass: string, action: string, targetRole: string|null, agent: string, canRetry: boolean, reason?: string }}
176
176
  */
177
- planRecovery(failureClass: string, currentIteration: number, lastAgent: string = 'codex'): { iteration: number; failureClass: string; action: string; targetRole: string | null; agent: string; canRetry: boolean; reason?: string } {
177
+ planRecovery(failureClass , currentIteration , lastAgent = 'codex') {
178
178
  // A negative or non-numeric iteration is caller nonsense; clamping keeps it from reading as
179
179
  // "before the first attempt" and skipping the agent switch that iteration 0 is supposed to get.
180
180
  const iteration = Number.isFinite(currentIteration) ? Math.max(0, Math.trunc(currentIteration)) : 0;
@@ -248,7 +248,7 @@ class RecoveryManager {
248
248
  * @param {boolean} [options.json=false]
249
249
  * @returns {number} exit code
250
250
  */
251
- function handleRecoverCommand({ errorMessage, failedChecks = [], iteration = 0, agent, json = false }: any = {}): number {
251
+ function handleRecoverCommand({ errorMessage, failedChecks = [], iteration = 0, agent, json = false } = {}) {
252
252
  // Handed nothing, the classifier answers UNKNOWN_FAILURE — a confident-looking verdict about a
253
253
  // failure it never saw. Refuse instead.
254
254
  if ((typeof errorMessage !== 'string' || errorMessage.trim() === '') && failedChecks.length === 0) {
@@ -258,7 +258,7 @@ function handleRecoverCommand({ errorMessage, failedChecks = [], iteration = 0,
258
258
  const failureClass = manager.classifyFailure(errorMessage, failedChecks);
259
259
  const plan = manager.planRecovery(failureClass, iteration, agent || undefined);
260
260
 
261
- if (json) console.log(JSON.stringify({ failureClass, failedChecks, ...(plan as any) }, null, 2));
261
+ if (json) console.log(JSON.stringify({ failureClass, failedChecks, ...(plan ) }, null, 2));
262
262
  else {
263
263
  console.log(`\nDoFlow Recovery [${plan.failureClass}]:`);
264
264
  console.log('═'.repeat(78));
@@ -5,24 +5,24 @@
5
5
  const fs = require('node:fs');
6
6
  const path = require('node:path');
7
7
  const crypto = require('node:crypto');
8
- const { acquireLock, updateTaskState, readTaskState } = require('./task-state.ts');
9
- const { EvidenceLedger, assertSafeTaskId } = require('./evidence-ledger.ts');
10
- const { ClaimsManager } = require('./claims.ts');
11
- const { taskStoreDir } = require('./task-scope.ts');
12
- const { FreshnessValidator } = require('./freshness.ts');
13
- const { resolveLocator } = require('./locator-resolve.ts');
14
- const { finishRuntime, usageError } = require('./cli-result.ts');
8
+ const { acquireLock, updateTaskState, readTaskState } = require('./task-state.js');
9
+ const { EvidenceLedger, assertSafeTaskId } = require('./evidence-ledger.js');
10
+ const { ClaimsManager } = require('./claims.js');
11
+ const { taskStoreDir } = require('./task-scope.js');
12
+ const { FreshnessValidator } = require('./freshness.js');
13
+ const { resolveLocator } = require('./locator-resolve.js');
14
+ const { finishRuntime, usageError } = require('./cli-result.js');
15
15
 
16
16
  const STATES = new Set(['OPEN', 'ANSWERED', 'UNRESOLVED']);
17
17
  const REASONS = new Set(['detected-gap', 'user-request']);
18
- const safeId = (value: any, label: any) => {
18
+ const safeId = (value , label ) => {
19
19
  if (typeof value !== 'string' || !/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(value)) {
20
20
  throw new Error(`${label} must be a safe non-empty identifier`);
21
21
  }
22
22
  return value;
23
23
  };
24
24
 
25
- function hasLocatedSource(item: any, projectRoot: any) {
25
+ function hasLocatedSource(item , projectRoot ) {
26
26
  const locator = item.locator || {};
27
27
  if (locator.uri !== undefined) {
28
28
  if (typeof locator.uri !== 'string') return false;
@@ -36,11 +36,11 @@ function hasLocatedSource(item: any, projectRoot: any) {
36
36
  }
37
37
 
38
38
  class ResearchRequestStore {
39
- declare projectRoot: any;
40
- declare fsImpl: any;
41
- declare slug: any;
42
- declare stateDir: any;
43
- constructor({ projectRoot = process.cwd(), fsImpl = fs, slug = null }: any = {}) {
39
+
40
+
41
+
42
+
43
+ constructor({ projectRoot = process.cwd(), fsImpl = fs, slug = null } = {}) {
44
44
  this.projectRoot = projectRoot;
45
45
  this.fsImpl = fsImpl;
46
46
  this.slug = slug;
@@ -48,29 +48,29 @@ class ResearchRequestStore {
48
48
  }
49
49
 
50
50
  /** The feature's namespace directory when the task has one (task-scope.js), else the flat store. */
51
- file(taskId: any) {
51
+ file(taskId ) {
52
52
  const dir = taskStoreDir({ projectRoot: this.projectRoot, store: 'research', taskId: assertSafeTaskId(taskId), slug: this.slug });
53
53
  return path.join(dir, `${taskId}.json`);
54
54
  }
55
55
 
56
- runFile(taskId: any) {
56
+ runFile(taskId ) {
57
57
  return path.join(this.projectRoot, '.doflow', 'state', 'orchestration', `${assertSafeTaskId(taskId)}.json`);
58
58
  }
59
59
 
60
- read(taskId: any) {
60
+ read(taskId ) {
61
61
  const data = readTaskState(this.fsImpl, this.file(taskId));
62
62
  if (!data) return { taskId, revision: 0, requests: [] };
63
63
  if (data.taskId !== taskId || !Array.isArray(data.requests)
64
- || data.requests.some((r: any) => !STATES.has(r.status))) {
64
+ || data.requests.some((r ) => !STATES.has(r.status))) {
65
65
  throw new Error(`Invalid research state for task '${taskId}'`);
66
66
  }
67
67
  return data;
68
68
  }
69
69
 
70
70
  // Re-read inside updateTaskState's lock: overlapping writers cannot lose a request.
71
- change(taskId: any, update: any) {
71
+ change(taskId , update ) {
72
72
  let result;
73
- updateTaskState({ fsImpl: this.fsImpl, file: this.file(taskId), build: (disk: any) => {
73
+ updateTaskState({ fsImpl: this.fsImpl, file: this.file(taskId), build: (disk ) => {
74
74
  if (disk && (disk.taskId !== taskId || !Array.isArray(disk.requests))) {
75
75
  throw new Error(`Invalid research state for task '${taskId}'`);
76
76
  }
@@ -81,7 +81,7 @@ class ResearchRequestStore {
81
81
  return result;
82
82
  }
83
83
 
84
- stageFor(taskId: any, stageId: any) {
84
+ stageFor(taskId , stageId ) {
85
85
  const run = readTaskState(this.fsImpl, this.runFile(taskId));
86
86
  if (!run || run.taskClass !== 'feature' || run.state !== 'RUNNING') {
87
87
  throw new Error(`Task '${taskId}' has no active feature stage`);
@@ -92,7 +92,7 @@ class ResearchRequestStore {
92
92
  }
93
93
  }
94
94
 
95
- open({ taskId, stageId, question, reason, blocking }: any = {}) {
95
+ open({ taskId, stageId, question, reason, blocking } = {}) {
96
96
  safeId(taskId, 'taskId'); safeId(stageId, 'stageId');
97
97
  if (typeof question !== 'string' || !question.trim()) throw new Error('question is required');
98
98
  if (!REASONS.has(reason)) throw new Error(`reason must be one of: ${[...REASONS].join(', ')}`);
@@ -104,8 +104,8 @@ class ResearchRequestStore {
104
104
  const release = acquireLock(this.fsImpl, runFile);
105
105
  try {
106
106
  this.stageFor(taskId, stageId);
107
- return this.change(taskId, (requests: any) => {
108
- const existing = requests.find((r: any) => r.stageId === stageId && r.question === question.trim() && r.status === 'OPEN');
107
+ return this.change(taskId, (requests ) => {
108
+ const existing = requests.find((r ) => r.stageId === stageId && r.question === question.trim() && r.status === 'OPEN');
109
109
  if (existing) {
110
110
  if ((blocking ?? reason === 'detected-gap') && !existing.blocking) {
111
111
  existing.blocking = true;
@@ -124,13 +124,13 @@ class ResearchRequestStore {
124
124
  } finally { release(); }
125
125
  }
126
126
 
127
- list(taskId: any) {
127
+ list(taskId ) {
128
128
  safeId(taskId, 'taskId');
129
129
  return this.read(taskId).requests;
130
130
  }
131
131
 
132
132
  // Validate references before taking the write lock; only the status transition itself mutates state.
133
- resolve({ taskId, requestId, outcome, claimId, evidenceIds = [], gap }: any = {}) {
133
+ resolve({ taskId, requestId, outcome, claimId, evidenceIds = [], gap } = {}) {
134
134
  safeId(taskId, 'taskId'); safeId(requestId, 'requestId');
135
135
  if (!['answered', 'unresolved'].includes(outcome)) throw new Error('outcome must be answered or unresolved');
136
136
  if (!Array.isArray(evidenceIds)) throw new Error('evidenceIds must be an array');
@@ -159,8 +159,8 @@ class ResearchRequestStore {
159
159
  }
160
160
  }
161
161
  }
162
- return this.change(taskId, (requests: any) => {
163
- const request = requests.find((r: any) => r.id === requestId);
162
+ return this.change(taskId, (requests ) => {
163
+ const request = requests.find((r ) => r.id === requestId);
164
164
  if (!request) throw new Error(`Unknown research request '${requestId}' for task '${taskId}'`);
165
165
  if (request.status !== 'OPEN') throw new Error(`Request '${requestId}' is ${request.status}, not OPEN`);
166
166
  Object.assign(request, { status: outcome === 'answered' ? 'ANSWERED' : 'UNRESOLVED',
@@ -170,20 +170,20 @@ class ResearchRequestStore {
170
170
  });
171
171
  }
172
172
 
173
- blockingGap(taskId: any, stageId: any) {
174
- const requests = this.list(taskId).filter((r: any) => r.stageId === stageId && r.blocking);
173
+ blockingGap(taskId , stageId ) {
174
+ const requests = this.list(taskId).filter((r ) => r.stageId === stageId && r.blocking);
175
175
  for (const request of requests) {
176
176
  if (request.status !== 'ANSWERED') return request;
177
177
  try {
178
178
  this.validateAnswer(taskId, request);
179
- } catch (error: any) {
179
+ } catch (error ) {
180
180
  return { ...request, failureReason: error.message };
181
181
  }
182
182
  }
183
183
  return null;
184
184
  }
185
185
 
186
- validateAnswer(taskId: any, request: any) {
186
+ validateAnswer(taskId , request ) {
187
187
  const ledger = new EvidenceLedger({ repoRoot: this.projectRoot, slug: this.slug });
188
188
  ledger.load(taskId);
189
189
  new FreshnessValidator({ repoRoot: this.projectRoot }).validateLedgerFreshness(ledger);
@@ -210,7 +210,7 @@ class ResearchRequestStore {
210
210
  }
211
211
 
212
212
  function handleResearchRequestCommand({ action = 'list', taskId, stageId, question, reason,
213
- blocking, requestId, outcome, claimId, evidenceIds, gap, json = false, projectRoot, slug }: any = {}) {
213
+ blocking, requestId, outcome, claimId, evidenceIds, gap, json = false, projectRoot, slug } = {}) {
214
214
  try {
215
215
  const store = new ResearchRequestStore({ projectRoot, slug });
216
216
  let result;
@@ -223,7 +223,7 @@ function handleResearchRequestCommand({ action = 'list', taskId, stageId, questi
223
223
  if (json) console.log(JSON.stringify(result, null, 2));
224
224
  else console.log(JSON.stringify(result));
225
225
  return finishRuntime(0);
226
- } catch (error: any) {
226
+ } catch (error ) {
227
227
  return usageError('research-request', error.message, json, error);
228
228
  }
229
229
  }