@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
@@ -83,11 +83,11 @@ class Refused extends Error {}
83
83
  * Returns the arguments AND how many characters the call occupied, so the caller can resume scanning
84
84
  * after the closing paren rather than assuming the macro owned the rest of its line.
85
85
  */
86
- function splitArgs(text: string): { args: string[]; consumed: number; closed: boolean } {
87
- const args: string[] = [];
86
+ function splitArgs(text ) {
87
+ const args = [];
88
88
  let buf = '';
89
89
  let depth = 0;
90
- let quote: string | null = null;
90
+ let quote = null;
91
91
  let consumed = text.length;
92
92
  let closed = false;
93
93
  for (let i = 0; i < text.length; i += 1) {
@@ -127,9 +127,9 @@ function splitArgs(text: string): { args: string[]; consumed: number; closed: bo
127
127
  * line-level transform running ahead of quote state has silently rewritten a label, so the transform
128
128
  * moved in here rather than being fixed again where it stood.
129
129
  */
130
- function stripComments(raw: string, state: { inBlock: boolean; openedAt: number }, lineno: number): { text: string; continues: boolean } {
130
+ function stripComments(raw , state , lineno ) {
131
131
  let out = '';
132
- let quote: string | null = null;
132
+ let quote = null;
133
133
  let i = 0;
134
134
  let continues = false;
135
135
  while (i < raw.length) {
@@ -161,7 +161,7 @@ function stripComments(raw: string, state: { inBlock: boolean; openedAt: number
161
161
 
162
162
  /** Mermaid delimits a node label with double quotes; an unescaped one inside ends it early and the
163
163
  * rest of the fence stops parsing. `&quot;` is the entity Mermaid documents for this. */
164
- function escapeLabel(text: any): string {
164
+ function escapeLabel(text ) {
165
165
  return String(text).replace(/"/g, '&quot;');
166
166
  }
167
167
 
@@ -185,11 +185,11 @@ function escapeLabel(text: any): string {
185
185
  const ALIAS = /^[A-Za-z0-9_]+([.-][A-Za-z0-9_]+)*$/;
186
186
 
187
187
  /** Every refusal carries the file and line, so the one place that formats it owns both. */
188
- function refuse(ctx: any, lineno: number, message: string): never {
188
+ function refuse(ctx , lineno , message ) {
189
189
  throw new Refused(`${ctx.sourcePath}:${lineno}: ${message}`);
190
190
  }
191
191
 
192
- function requireAlias(ctx: any, alias: string, lineno: number, role: string): void {
192
+ function requireAlias(ctx , alias , lineno , role ) {
193
193
  if (!ALIAS.test(alias)) {
194
194
  refuse(ctx, lineno, `${role} '${alias}' is not a usable node id. Mermaid fails the whole diagram `
195
195
  + 'on one it cannot lex, and silently reads one carrying `--` or `-.-` as a LINK instead, '
@@ -197,7 +197,7 @@ function requireAlias(ctx: any, alias: string, lineno: number, role: string): vo
197
197
  }
198
198
  }
199
199
 
200
- function acceptElement(ctx: any, name: string, args: string[], lineno: number): void {
200
+ function acceptElement(ctx , name , args , lineno ) {
201
201
  if (args.length < 2) refuse(ctx, lineno, `${name} needs an alias and a label`);
202
202
  requireAlias(ctx, args[0], lineno, 'alias');
203
203
  if (ctx.nodes.has(args[0])) {
@@ -211,7 +211,7 @@ function acceptElement(ctx: any, name: string, args: string[], lineno: number):
211
211
  // A boundary opened inside another is that one's CHILD, not a second root. Pushing every boundary
212
212
  // onto one flat list rendered the outer one as an empty subgraph and hoisted the inner one to the
213
213
  // top level -- dropping a containment the source states and Mermaid supports.
214
- function acceptBoundary(ctx: any, name: string, args: string[], lineno: number): void {
214
+ function acceptBoundary(ctx , name , args , lineno ) {
215
215
  if (args.length < 2) refuse(ctx, lineno, `${name} needs an alias and a label`);
216
216
  requireAlias(ctx, args[0], lineno, 'boundary alias');
217
217
  const b = { alias: args[0], label: args[1], members: [], children: [] };
@@ -219,14 +219,14 @@ function acceptBoundary(ctx: any, name: string, args: string[], lineno: number):
219
219
  ctx.stack.push(b);
220
220
  }
221
221
 
222
- function acceptRelation(ctx: any, name: string, args: string[], lineno: number): void {
222
+ function acceptRelation(ctx , name , args , lineno ) {
223
223
  if (args.length < 2) refuse(ctx, lineno, `${name} needs a source and a target`);
224
224
  requireAlias(ctx, args[0], lineno, 'relation source');
225
225
  requireAlias(ctx, args[1], lineno, 'relation target');
226
226
  ctx.edges.push({ from: args[0], to: args[1], label: args[2] || '', bi: name.startsWith('BiRel') });
227
227
  }
228
228
 
229
- function accept(ctx: any, name: string, args: string[], lineno: number): void {
229
+ function accept(ctx , name , args , lineno ) {
230
230
  if (SKIPPED.has(name)) return;
231
231
  if (ELEMENTS.has(name)) acceptElement(ctx, name, args, lineno);
232
232
  else if (BOUNDARIES.has(name)) acceptBoundary(ctx, name, args, lineno);
@@ -234,7 +234,7 @@ function accept(ctx: any, name: string, args: string[], lineno: number): void {
234
234
  else {
235
235
  refuse(ctx, lineno, `unrecognized macro '${name}'. The projector refuses rather than skipping `
236
236
  + 'it, because a skipped macro would silently shrink the diagram. Add it to the recognized '
237
- + 'set in src/runtime/c4-project.ts if the bundled library defines it.');
237
+ + 'set in src/runtime/c4-project.js if the bundled library defines it.');
238
238
  }
239
239
  }
240
240
 
@@ -246,10 +246,10 @@ function accept(ctx: any, name: string, args: string[], lineno: number): void {
246
246
  * is what joins them. A trailing backslash inside a quoted label is therefore not a continuation,
247
247
  * and the call it leaves unterminated refuses in the scan rather than absorbing the next line.
248
248
  */
249
- function toLogicalLines(text: string, state: { inBlock: boolean; openedAt: number }): Array<{ raw: string; lineno: number }> {
249
+ function toLogicalLines(text , state ) {
250
250
  const rawLines = text.split('\n');
251
- const logical: Array<{ raw: string; lineno: number }> = [];
252
- let pending: { raw: string; lineno: number } | null = null;
251
+ const logical = [];
252
+ let pending = null;
253
253
  for (let n = 0; n < rawLines.length; n += 1) {
254
254
  const stripped = stripComments(rawLines[n], state, n + 1);
255
255
  if (pending === null) pending = { raw: stripped.text, lineno: n + 1 };
@@ -263,7 +263,7 @@ function toLogicalLines(text: string, state: { inBlock: boolean; openedAt: numbe
263
263
  }
264
264
 
265
265
  /** Read every construct one logical line carries, in order. */
266
- function scanLine(ctx: any, line: string, lineno: number): void {
266
+ function scanLine(ctx , line , lineno ) {
267
267
  if (!line || /^[#@!]/.test(line)) return;
268
268
  // A line is scanned for constructs only when it BEGINS with one. Scanning every offset of every
269
269
  // line turned any free text containing `word (` into a macro candidate, so `title My Diagram
@@ -283,7 +283,7 @@ function scanLine(ctx: any, line: string, lineno: number): void {
283
283
  // `Rel(a)` must be ignored the way prose is everywhere else.
284
284
  const rest = line.slice(i);
285
285
  const hit = [...rest.matchAll(/([A-Za-z_][A-Za-z0-9_]*)\s*\(/g)]
286
- .find(([, n]: any) => ELEMENTS.has(n) || BOUNDARIES.has(n) || RELATIONS.has(n));
286
+ .find(([, n] ) => ELEMENTS.has(n) || BOUNDARIES.has(n) || RELATIONS.has(n));
287
287
  const dropped = hit && !/[A-Za-z0-9]/.test(rest.slice(0, hit.index)) ? hit[1] : null;
288
288
  if (dropped) {
289
289
  refuse(ctx, lineno, `${dropped}(...) follows text on this line that is not a construct, `
@@ -302,7 +302,7 @@ function scanLine(ctx: any, line: string, lineno: number): void {
302
302
  }
303
303
  }
304
304
 
305
- function parse(text: string, sourcePath: string): { nodes: Map<string, string>; edges: any[]; boundaries: any[] } {
305
+ function parse(text , sourcePath ) {
306
306
  const ctx = { sourcePath, nodes: new Map(), edges: [], boundaries: [], stack: [] };
307
307
  const state = { inBlock: false, openedAt: 0 };
308
308
  for (const entry of toLogicalLines(text, state)) scanLine(ctx, entry.raw.trim(), entry.lineno);
@@ -315,9 +315,9 @@ function parse(text: string, sourcePath: string): { nodes: Map<string, string>;
315
315
  return { nodes: ctx.nodes, edges: ctx.edges, boundaries: ctx.boundaries };
316
316
  }
317
317
 
318
- function emit({ nodes, edges, boundaries }: { nodes: Map<string, string>; edges: any[]; boundaries: any[] }, sourceRel: string, digest: string): string {
319
- const grouped = new Set<string>();
320
- const collect = (list: any[]): void => {
318
+ function emit({ nodes, edges, boundaries } , sourceRel , digest ) {
319
+ const grouped = new Set ();
320
+ const collect = (list ) => {
321
321
  for (const b of list) {
322
322
  for (const a of b.members) grouped.add(a);
323
323
  collect(b.children);
@@ -330,7 +330,7 @@ function emit({ nodes, edges, boundaries }: { nodes: Map<string, string>; edges:
330
330
  '```mermaid',
331
331
  'flowchart TB',
332
332
  ];
333
- const renderBoundary = (b: any, indent: string): void => {
333
+ const renderBoundary = (b , indent ) => {
334
334
  out.push(`${indent}subgraph ${b.alias}["${escapeLabel(b.label)}"]`);
335
335
  for (const a of b.members) out.push(`${indent} ${a}["${escapeLabel(nodes.get(a) ?? a)}"]`);
336
336
  for (const child of b.children) renderBoundary(child, `${indent} `);
@@ -348,7 +348,7 @@ function emit({ nodes, edges, boundaries }: { nodes: Map<string, string>; edges:
348
348
  return `${out.join('\n')}\n`;
349
349
  }
350
350
 
351
- function project(text: string, sourceRel: string = '<source>'): { block: string; digest: string } {
351
+ function project(text , sourceRel = '<source>') {
352
352
  const digest = crypto.createHash('sha256').update(text, 'utf8').digest('hex').slice(0, 12);
353
353
  return { block: emit(parse(text, sourceRel), sourceRel, digest), digest };
354
354
  }
@@ -360,11 +360,11 @@ module.exports = {
360
360
  if (require.main === module) {
361
361
  const file = process.argv[2];
362
362
  if (!file) { process.stderr.write('usage: c4-project.ts <file.puml>\n'); process.exit(2); }
363
- let text: string;
363
+ let text ;
364
364
  try { text = fs.readFileSync(file, 'utf8'); }
365
- catch (err: any) { process.stderr.write(`c4-project: cannot read ${file}: ${err.message}\n`); process.exit(2); }
365
+ catch (err ) { process.stderr.write(`c4-project: cannot read ${file}: ${err.message}\n`); process.exit(2); }
366
366
  try { process.stdout.write(project(text, file).block); }
367
- catch (err: any) {
367
+ catch (err ) {
368
368
  if (err instanceof Refused) { process.stderr.write(`c4-project: ${err.message}\n`); process.exit(1); }
369
369
  throw err;
370
370
  }
@@ -5,39 +5,39 @@
5
5
  const fs = require('node:fs');
6
6
  const path = require('node:path');
7
7
  const { execFileSync } = require('node:child_process');
8
- const { finishRuntime, usageError } = require('./cli-result.ts');
9
- const { REPO_ROOT } = require('../helper/repo-root.ts');
10
- const { validateCapabilityProviders } = require('../registry/index.ts');
8
+ const { finishRuntime, usageError } = require('./cli-result.js');
9
+ const { REPO_ROOT } = require('../helper/repo-root.js');
10
+ const { validateCapabilityProviders } = require('../registry/index.js');
11
11
 
12
12
  // Mirrors bin/doflow.js's own REPO_ROOT computation, relative to this file's location, so
13
13
  // handleRouteCommand resolves the same repo root it did before relocation. (D8)
14
14
 
15
15
  /** POSIX single-quote escaping, for the DISPLAY string only — execution always uses the argv
16
16
  * vector, never a shell string, so retrieved data can never become shell syntax (review R5). */
17
- function shellQuote(word: any): string {
17
+ function shellQuote(word ) {
18
18
  const text = String(word);
19
19
  if (text !== '' && /^[A-Za-z0-9_@%+=:,.\/-]+$/.test(text)) return text;
20
20
  return `'${text.replace(/'/g, `'\\''`)}'`;
21
21
  }
22
22
 
23
- function parseYamlFile(filePath: string, fsImpl: any = fs): any {
23
+ function parseYamlFile(filePath , fsImpl = fs) {
24
24
  try {
25
25
  const text = fsImpl.readFileSync(filePath, 'utf8');
26
26
  return JSON.parse(text);
27
- } catch (error: any) {
27
+ } catch (error ) {
28
28
  throw new Error(`Failed to parse registry file '${filePath}': ${error.message}`);
29
29
  }
30
30
  }
31
31
 
32
32
  class CapabilityRouter {
33
- fsImpl: any;
34
- repoRoot: string;
35
- projectRoot: string;
36
- registryDir: string;
37
- binaryChecker: ((binary: string) => boolean) | null;
38
- binaryCache: Map<string, boolean>;
39
- capabilities!: Record<string, any>;
40
- routes!: Record<string, any>;
33
+ fsImpl ;
34
+ repoRoot ;
35
+ projectRoot ;
36
+ registryDir ;
37
+ binaryChecker ;
38
+ binaryCache ;
39
+ capabilities ;
40
+ routes ;
41
41
 
42
42
  /**
43
43
  * @param {Object} [options]
@@ -48,7 +48,7 @@ class CapabilityRouter {
48
48
  * @param {Object} [options.fsImpl]
49
49
  * @param {Function} [options.binaryChecker]
50
50
  */
51
- constructor(options: any = {}) {
51
+ constructor(options = {}) {
52
52
  this.fsImpl = options.fsImpl || fs;
53
53
  this.repoRoot = options.repoRoot || REPO_ROOT;
54
54
  // Two roots, deliberately distinct (review A3, surfaced by R5's tests): `repoRoot` locates the
@@ -68,7 +68,7 @@ class CapabilityRouter {
68
68
  }
69
69
  }
70
70
 
71
- loadRegistries(): void {
71
+ loadRegistries() {
72
72
  const capsPath = path.join(this.registryDir, 'capabilities.json');
73
73
  const routesPath = path.join(this.registryDir, 'routes.json');
74
74
 
@@ -78,7 +78,7 @@ class CapabilityRouter {
78
78
  this.capabilities = capsData.capabilities || {};
79
79
  // A provider without a valid `sourceMode` cannot be told apart from an index-backed one, so the
80
80
  // file is refused whole rather than loaded with a guess (068).
81
- const providerErrors: string[] = [];
81
+ const providerErrors = [];
82
82
  validateCapabilityProviders(this.capabilities, providerErrors);
83
83
  if (providerErrors.length > 0) {
84
84
  throw new Error(`Invalid registry file '${capsPath}':\n- ${providerErrors.join('\n- ')}`);
@@ -91,13 +91,13 @@ class CapabilityRouter {
91
91
  * @param {string} binary
92
92
  * @returns {boolean}
93
93
  */
94
- isBinaryAvailable(binary: string): boolean {
94
+ isBinaryAvailable(binary ) {
95
95
  if (!binary) return false;
96
96
  if (this.binaryChecker) {
97
97
  return this.binaryChecker(binary);
98
98
  }
99
99
  if (this.binaryCache.has(binary)) {
100
- return this.binaryCache.get(binary) as boolean;
100
+ return this.binaryCache.get(binary) ;
101
101
  }
102
102
  try {
103
103
  const isWin = process.platform === 'win32';
@@ -116,7 +116,7 @@ class CapabilityRouter {
116
116
  * @param {Array<string>} checkCommand
117
117
  * @returns {{ ok: boolean, output?: string, error?: string }}
118
118
  */
119
- executeSmokeCheck(checkCommand: any): { ok: boolean; output?: string; error?: string } {
119
+ executeSmokeCheck(checkCommand ) {
120
120
  if (!Array.isArray(checkCommand) || checkCommand.length === 0) {
121
121
  return { ok: true };
122
122
  }
@@ -128,7 +128,7 @@ class CapabilityRouter {
128
128
  stdio: ['ignore', 'pipe', 'pipe'],
129
129
  });
130
130
  return { ok: true, output: stdout.trim() };
131
- } catch (error: any) {
131
+ } catch (error ) {
132
132
  return { ok: false, error: error.message };
133
133
  }
134
134
  }
@@ -139,13 +139,13 @@ class CapabilityRouter {
139
139
  * @param {boolean} [deepCheck=false]
140
140
  * @returns {{ status: 'HEALTHY'|'UNAVAILABLE', details?: string }}
141
141
  */
142
- evaluateProviderHealth(provider: any, deepCheck: boolean = false): any {
142
+ evaluateProviderHealth(provider , deepCheck = false) {
143
143
  if (!provider) return { status: 'UNAVAILABLE', details: 'No provider declared' };
144
144
 
145
145
  // Declared / installed / responsive are DISTINCT facts (review R5): `facts` reports each one
146
146
  // as true, false, or null-for-not-measured, so "healthy" can never silently mean only
147
147
  // "declared in the registry". The summary `status` stays for existing callers.
148
- const facts: { declared: boolean; installed: boolean | null; responsive: boolean | null } = { declared: true, installed: null, responsive: null };
148
+ const facts = { declared: true, installed: null, responsive: null };
149
149
 
150
150
  // `native.test` has no binary — its installedness is whether this project's manifests declare
151
151
  // a test command at all. Reporting HEALTHY without that check routed verify-runtime-behavior
@@ -205,16 +205,16 @@ class CapabilityRouter {
205
205
  * @param {boolean} [options.deepCheck=false]
206
206
  * @returns {{ capabilityId: string, provider: Object|null, status: string, fallbackProviders: Array<Object> }}
207
207
  */
208
- resolveCapability(capabilityId: string, { deepCheck = false }: { deepCheck?: boolean } = {}): any {
208
+ resolveCapability(capabilityId , { deepCheck = false } = {}) {
209
209
  const capability = this.capabilities[capabilityId];
210
210
  if (!capability) {
211
211
  throw new Error(`Unknown capability '${capabilityId}'`);
212
212
  }
213
213
 
214
214
  const providers = capability.providers || [];
215
- let selectedProvider: any = null;
215
+ let selectedProvider = null;
216
216
  let selectedStatus = 'UNAVAILABLE';
217
- const fallbackProviders: any[] = [];
217
+ const fallbackProviders = [];
218
218
 
219
219
  for (let i = 0; i < providers.length; i++) {
220
220
  const prov = providers[i];
@@ -255,16 +255,16 @@ class CapabilityRouter {
255
255
  * @param {Object} params
256
256
  * @returns {Object}
257
257
  */
258
- formatExecution(intent: string, provider: any, params: any = {}): any {
258
+ formatExecution(intent , provider , params = {}) {
259
259
  const query = params.query || params.symbol || params.concept || '';
260
260
  const targetPath = params.path || '.';
261
261
  // The MCP tool name comes from the provider's registry descriptor (`mcp: {server, tool}`), so a
262
262
  // new MCP-backed provider needs no code change here. A caller may pass a bare `{ id }`, so fall
263
263
  // back to the registry entry with that id.
264
264
  const mcp = provider.mcp
265
- || Object.values(this.capabilities).flatMap((cap: any) => cap.providers || []).find((p: any) => p.id === provider.id && p.mcp)?.mcp;
265
+ || Object.values(this.capabilities).flatMap((cap ) => cap.providers || []).find((p ) => p.id === provider.id && p.mcp)?.mcp;
266
266
  const mcpTool = mcp ? { mcpTool: `mcp__${mcp.server}__${mcp.tool}` } : {};
267
- const withDisplay = (result: any) => ({ ...mcpTool, ...result, ...(result.argv ? { cliCommand: result.argv.map(shellQuote).join(' ') } : {}) });
267
+ const withDisplay = (result ) => ({ ...mcpTool, ...result, ...(result.argv ? { cliCommand: result.argv.map(shellQuote).join(' ') } : {}) });
268
268
 
269
269
  if (provider.id === 'semble.search') {
270
270
  const content = params.content || 'code';
@@ -338,9 +338,9 @@ class CapabilityRouter {
338
338
  /** The project's own test entrypoint, read from its manifests by the shared command detector —
339
339
  * the same detector `doflow verify` uses, so the two agree. Returns null when no manifest
340
340
  * declares one: a wrong guess here becomes a command the model runs. */
341
- detectTestCommand(): string | null {
341
+ detectTestCommand() {
342
342
  try {
343
- const { detectCommands } = require('./command-detect.ts');
343
+ const { detectCommands } = require('./command-detect.js');
344
344
  const detected = detectCommands({ projectRoot: this.projectRoot });
345
345
  return detected.commands?.test?.command || null;
346
346
  } catch {
@@ -355,7 +355,7 @@ class CapabilityRouter {
355
355
  * @param {Object} [options={}]
356
356
  * @returns {Object} RetrievalPlan
357
357
  */
358
- resolveIntent(intentId: string, params: any = {}, { deepCheck = false }: { deepCheck?: boolean } = {}): any {
358
+ resolveIntent(intentId , params = {}, { deepCheck = false } = {}) {
359
359
  const route = this.routes[intentId];
360
360
  if (!route) {
361
361
  throw new Error(`Unknown route/intent '${intentId}'`);
@@ -372,7 +372,7 @@ class CapabilityRouter {
372
372
  selectedProvider: primaryResolution.provider,
373
373
  status: primaryResolution.status,
374
374
  execution: this.formatExecution(intentId, primaryResolution.provider, params),
375
- fallbackChain: (route.fallback || []).map((fbCap: string) => ({
375
+ fallbackChain: (route.fallback || []).map((fbCap ) => ({
376
376
  capability: fbCap,
377
377
  resolved: this.resolveCapability(fbCap, { deepCheck }),
378
378
  })),
@@ -408,7 +408,7 @@ class CapabilityRouter {
408
408
  selectedProvider: null,
409
409
  status: 'UNAVAILABLE',
410
410
  execution: null,
411
- fallbackChain: (route.fallback || []).map((cap: string) => ({ capability: cap, status: 'UNAVAILABLE' })),
411
+ fallbackChain: (route.fallback || []).map((cap ) => ({ capability: cap, status: 'UNAVAILABLE' })),
412
412
  };
413
413
  }
414
414
 
@@ -417,8 +417,8 @@ class CapabilityRouter {
417
417
  * @param {boolean} [deepCheck=false]
418
418
  * @returns {Array<Object>}
419
419
  */
420
- getAllCapabilitiesHealth(deepCheck: boolean = false): any[] {
421
- const report: any[] = [];
420
+ getAllCapabilitiesHealth(deepCheck = false) {
421
+ const report = [];
422
422
  for (const [capId, cap] of Object.entries(this.capabilities)) {
423
423
  const resolution = this.resolveCapability(capId, { deepCheck });
424
424
  report.push({
@@ -448,16 +448,16 @@ class CapabilityRouter {
448
448
  * @param {string} [options.projectRoot]
449
449
  * @returns {number} exit code
450
450
  */
451
- function handleRouteCommand({ intent, query, check = false, json = false, projectRoot }: any = {}): number {
451
+ function handleRouteCommand({ intent, query, check = false, json = false, projectRoot } = {}) {
452
452
  const router = new CapabilityRouter({ repoRoot: REPO_ROOT, projectRoot });
453
453
  if (typeof intent !== 'string' || intent.trim() === '') {
454
454
  return usageError('route', `--intent is required. Declared intents: ${Object.keys(router.routes).join(', ')}`, json);
455
455
  }
456
456
 
457
- let resolution: any;
457
+ let resolution ;
458
458
  try {
459
459
  resolution = router.resolveIntent(intent, { query, path: projectRoot || '.' }, { deepCheck: check });
460
- } catch (error: any) {
460
+ } catch (error ) {
461
461
  return usageError('route', `${error.message}. Declared intents: ${Object.keys(router.routes).join(', ')}`, json, error);
462
462
  }
463
463
 
@@ -5,7 +5,7 @@
5
5
  const fs = require('node:fs');
6
6
  const path = require('node:path');
7
7
  const { spawnSync } = require('node:child_process');
8
- const { BASE_FILE } = require('./worktree.ts');
8
+ const { BASE_FILE } = require('./worktree.js');
9
9
 
10
10
  // The checkouts of one repository: the main working tree and its linked worktrees.
11
11
  //
@@ -15,9 +15,9 @@ const { BASE_FILE } = require('./worktree.ts');
15
15
  // source that names every checkout, and it is asked once per process.
16
16
 
17
17
  /** realpath(cwd) -> listCheckouts result. */
18
- const cache = new Map<string, any>();
18
+ const cache = new Map ();
19
19
 
20
- function realOrNull(p: string, fsImpl: any): string | null {
20
+ function realOrNull(p , fsImpl ) {
21
21
  try {
22
22
  return fsImpl.realpathSync(p);
23
23
  } catch {
@@ -25,7 +25,7 @@ function realOrNull(p: string, fsImpl: any): string | null {
25
25
  }
26
26
  }
27
27
 
28
- function failed(reason: string, detail: string): any {
28
+ function failed(reason , detail ) {
29
29
  return {
30
30
  ok: false, reason, detail, current: null, main: null, mainReason: null, others: [], isLinked: false, sandbox: false,
31
31
  };
@@ -46,17 +46,17 @@ function failed(reason: string, detail: string): any {
46
46
  * @returns {{ok: boolean, reason: string|null, detail: string|null, current: string|null, main: string|null,
47
47
  * mainReason: string|null, others: Array<string>, isLinked: boolean, sandbox: boolean}}
48
48
  */
49
- function listCheckouts({ cwd, exec = spawnSync, fsImpl = fs }: { cwd: string; exec?: any; fsImpl?: any }): any {
49
+ function listCheckouts({ cwd, exec = spawnSync, fsImpl = fs } ) {
50
50
  const realCwd = realOrNull(cwd, fsImpl) || path.resolve(cwd);
51
51
  if (cache.has(realCwd)) return cache.get(realCwd);
52
52
 
53
- let res: any;
53
+ let res ;
54
54
  try {
55
55
  res = exec('git', ['-C', realCwd, 'worktree', 'list', '--porcelain'], { encoding: 'utf8', timeout: 10000 });
56
- } catch (error: any) {
56
+ } catch (error ) {
57
57
  res = { error };
58
58
  }
59
- let result: any;
59
+ let result ;
60
60
  if (res && res.error) {
61
61
  result = res.error.code === 'ENOENT'
62
62
  ? failed('git-unavailable', String(res.error.message || '').trim().slice(0, 200))
@@ -71,8 +71,8 @@ function listCheckouts({ cwd, exec = spawnSync, fsImpl = fs }: { cwd: string; ex
71
71
  return result;
72
72
  }
73
73
 
74
- function fromPorcelain(stdout: string, realCwd: string, fsImpl: any): any {
75
- const entries: Array<{ real: string | null; bare: boolean; sandbox: boolean }> = [];
74
+ function fromPorcelain(stdout , realCwd , fsImpl ) {
75
+ const entries = [];
76
76
  for (const block of stdout.split(/\n\s*\n/)) {
77
77
  const lines = block.split('\n').filter(Boolean);
78
78
  if (lines.length === 0 || !lines[0].startsWith('worktree ')) continue;
@@ -84,7 +84,7 @@ function fromPorcelain(stdout: string, realCwd: string, fsImpl: any): any {
84
84
  });
85
85
  }
86
86
 
87
- let current: any = null;
87
+ let current = null;
88
88
  for (const e of entries) {
89
89
  if (e.real === null || e.bare) continue;
90
90
  if ((realCwd === e.real || realCwd.startsWith(e.real + path.sep)) && (current === null || e.real.length > current.real.length)) {
@@ -93,8 +93,8 @@ function fromPorcelain(stdout: string, realCwd: string, fsImpl: any): any {
93
93
  }
94
94
  const sandbox = Boolean(current && current.sandbox);
95
95
  const first = entries[0];
96
- let main: string | null = null;
97
- let mainReason: string | null = null;
96
+ let main = null;
97
+ let mainReason = null;
98
98
  if (sandbox) mainReason = 'sandbox';
99
99
  else if (first && first.bare) mainReason = 'bare';
100
100
  else if (!first || first.real === null) mainReason = 'missing';
@@ -102,7 +102,7 @@ function fromPorcelain(stdout: string, realCwd: string, fsImpl: any): any {
102
102
 
103
103
  const others = sandbox ? [] : entries
104
104
  .filter((e) => e.real !== null && !e.bare && !e.sandbox && e !== current)
105
- .map((e) => e.real as string);
105
+ .map((e) => e.real );
106
106
  const currentPath = current ? current.real : null;
107
107
  return {
108
108
  ok: true,
@@ -118,7 +118,7 @@ function fromPorcelain(stdout: string, realCwd: string, fsImpl: any): any {
118
118
  }
119
119
 
120
120
  /** Forgets every memoized `listCheckouts` result (tests that rebuild a repository in place). */
121
- function clearCheckoutCache(): void {
121
+ function clearCheckoutCache() {
122
122
  cache.clear();
123
123
  }
124
124
 
@@ -138,8 +138,8 @@ function clearCheckoutCache(): void {
138
138
  * @returns {{status: 'found'|'missing'|'ambiguous', file: string|null, root: string|null,
139
139
  * origin: 'current'|'other'|null, candidates: Array<string>}}
140
140
  */
141
- function findStateFile({ stateRoot, relPath, exec = spawnSync, fsImpl = fs }: { stateRoot: string; relPath: any; exec?: any; fsImpl?: any }): any {
142
- const at = (root: string, isCurrent: boolean): string | null => {
141
+ function findStateFile({ stateRoot, relPath, exec = spawnSync, fsImpl = fs } ) {
142
+ const at = (root , isCurrent ) => {
143
143
  const rel = typeof relPath === 'function' ? relPath(root, isCurrent) : relPath;
144
144
  for (const candidate of Array.isArray(rel) ? rel : [rel]) {
145
145
  if (typeof candidate !== 'string' || candidate === '') continue;
@@ -148,21 +148,21 @@ function findStateFile({ stateRoot, relPath, exec = spawnSync, fsImpl = fs }: {
148
148
  }
149
149
  return null;
150
150
  };
151
- const missing = { status: 'missing', file: null, root: null, origin: null, candidates: [] as string[] };
151
+ const missing = { status: 'missing', file: null, root: null, origin: null, candidates: [] };
152
152
 
153
153
  const here = at(stateRoot, true);
154
154
  if (here) return { status: 'found', file: here, root: stateRoot, origin: 'current', candidates: [] };
155
155
 
156
156
  const checkouts = listCheckouts({ cwd: stateRoot, exec, fsImpl });
157
157
  if (!checkouts.ok || checkouts.sandbox) return missing;
158
- const matches: Array<{ file: string; root: string }> = [];
159
- for (const root of checkouts.others as string[]) {
158
+ const matches = [];
159
+ for (const root of checkouts.others ) {
160
160
  const file = at(root, false);
161
161
  if (file) matches.push({ file, root });
162
162
  }
163
163
  if (matches.length === 0) return missing;
164
164
  if (matches.length > 1) {
165
- return { status: 'ambiguous', file: null, root: null, origin: null, candidates: matches.map((m: { file: string }) => m.file) };
165
+ return { status: 'ambiguous', file: null, root: null, origin: null, candidates: matches.map((m ) => m.file) };
166
166
  }
167
167
  return { status: 'found', file: matches[0].file, root: matches[0].root, origin: 'other', candidates: [] };
168
168
  }