@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
@@ -5,24 +5,24 @@
5
5
  //
6
6
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): authored as `.ts`, run directly by Node
7
7
  // native type-stripping — no build step, no runtime dependency. Body stays CommonJS so a `.js`
8
- // caller's `require('../install/mcp.ts')` keeps working while the tree is still `.js`. The
8
+ // caller's `require('../install/mcp.js')` keeps working while the tree is still `.js`. The
9
9
  // `../registry` and `../state/lockfile` requires stay bare while those modules are still `.js`.
10
- const { readSyncBlocking } = require('../helper/prompt.ts');
11
- const { selectMcpServers, nativeMcpCatalog, mcpCapable } = require('../registry/index.ts');
12
- const { pinnedSelections } = require('../state/lockfile.ts');
10
+ const { readSyncBlocking } = require('../helper/prompt.js');
11
+ const { selectMcpServers, nativeMcpCatalog, mcpCapable } = require('../registry/index.js');
12
+ const { pinnedSelections } = require('../state/lockfile.js');
13
13
 
14
14
  const ESC = String.fromCharCode(27);
15
15
  const CTRL_C = String.fromCharCode(3);
16
16
 
17
17
  /** `registry` is a loaded registry (src/registry#loadRegistry); returns server names in registry
18
18
  * declaration order. */
19
- function readAllServers(registry: any): string[] {
19
+ function readAllServers(registry ) {
20
20
  return nativeMcpCatalog(selectMcpServers(registry)).allServers;
21
21
  }
22
22
 
23
23
  /** Parse `--mcp`: `all` and `none` are keywords that cannot be mixed with names or each other, an
24
24
  * empty list and an unknown name are errors, names are deduplicated. `null` when the flag is absent. */
25
- function parseMcpFlag(requested: string[] | undefined, catalogIds: string[]): string[] | null {
25
+ function parseMcpFlag(requested , catalogIds ) {
26
26
  if (!requested) return null;
27
27
  const keywords = requested.filter((s) => s === 'all' || s === 'none');
28
28
  if (keywords.length) {
@@ -44,27 +44,27 @@ function parseMcpFlag(requested: string[] | undefined, catalogIds: string[]): st
44
44
  return [...new Set(requested)];
45
45
  }
46
46
 
47
- const holdsRows = (ledger: any, harness: string) => (ledger?.resources ?? []).some((row: any) => row.harness === harness);
47
+ const holdsRows = (ledger , harness ) => (ledger?.resources ?? []).some((row ) => row.harness === harness);
48
48
 
49
49
  /** Ids of `lists` that the catalog still declares, as one union in registry order. */
50
- const catalogUnion = (catalogIds: string[], lists: string[][]) => catalogIds.filter((id) => lists.some((ids) => ids.includes(id)));
50
+ const catalogUnion = (catalogIds , lists ) => catalogIds.filter((id) => lists.some((ids) => ids.includes(id)));
51
51
 
52
52
  /** 1.18.0 wrote lock rows only for claude and codex, and only non-empty ones. Any other row was
53
53
  * written by a later run, which already settled which of that harness's entries are DoFlow's. */
54
54
  const LEGACY_LOCK_HARNESSES = ['claude', 'codex'];
55
55
 
56
- function settledByLaterRun(rows: Record<string, string[]>, harness: string): boolean {
56
+ function settledByLaterRun(rows , harness ) {
57
57
  return harness in rows && (!LEGACY_LOCK_HARNESSES.includes(harness) || rows[harness].length === 0);
58
58
  }
59
59
 
60
60
  /** The servers a 1.18.0 install recorded writing for this harness, from state no later run writes:
61
61
  * the manifest's MCP list, Antigravity's rows that carry no fingerprint, and Copilot's whole-map
62
62
  * registration row, which covers the manifest's list or, with none, the catalog 1.18.0 wrote. */
63
- function legacyRecordedIds({ catalogIds, ledger, harness, manifestServers }: { catalogIds: string[]; ledger: any; harness: string; manifestServers: string[] | null | undefined }): string[] {
64
- const rows = (ledger?.resources ?? []).filter((row: any) => row.harness === harness);
63
+ function legacyRecordedIds({ catalogIds, ledger, harness, manifestServers } ) {
64
+ const rows = (ledger?.resources ?? []).filter((row ) => row.harness === harness);
65
65
  const ids = [...(manifestServers ?? [])];
66
66
  for (const row of rows) if (row.kind === 'mcp-server' && (row.fingerprint ?? null) === null) ids.push(row.identity);
67
- if (!manifestServers && rows.some((row: any) => row.ownershipIdentity === `${harness}:mcp:registration`)) ids.push(...catalogIds);
67
+ if (!manifestServers && rows.some((row ) => row.ownershipIdentity === `${harness}:mcp:registration`)) ids.push(...catalogIds);
68
68
  return catalogUnion(catalogIds, [ids]);
69
69
  }
70
70
 
@@ -72,7 +72,7 @@ function legacyRecordedIds({ catalogIds, ledger, harness, manifestServers }: { c
72
72
  * only what a 1.18.0 install recorded for a harness the ledger holds, and only until a later run
73
73
  * has recorded the harness's own selection. An entry a user wrote is never adoptable merely because
74
74
  * DoFlow installed something else for that harness. Retired ids are dropped. */
75
- function adoptableMcpIds({ registry, lock, ledger, harnesses, manifestServers = null }: { registry: any; lock: any; ledger: any; harnesses: string[]; manifestServers?: string[] | null }): Record<string, string[]> {
75
+ function adoptableMcpIds({ registry, lock, ledger, harnesses, manifestServers = null } ) {
76
76
  const catalogIds = readAllServers(registry);
77
77
  const rows = pinnedSelections(lock);
78
78
  return Object.fromEntries(harnesses.filter((harness) => mcpCapable(registry, harness)).map((harness) => {
@@ -83,7 +83,7 @@ function adoptableMcpIds({ registry, lock, ledger, harnesses, manifestServers =
83
83
 
84
84
  /** Servers another harness of this scope still has recorded: the union of the lock rows of the lock's
85
85
  * harnesses that are not targeted, registry order. */
86
- function retainedMcpIds(catalogIds: string[], rows: Record<string, string[]>, targets: string[]): string[] {
86
+ function retainedMcpIds(catalogIds , rows , targets ) {
87
87
  return catalogUnion(catalogIds, Object.entries(rows).filter(([harness]) => !targets.includes(harness)).map(([, ids]) => ids));
88
88
  }
89
89
 
@@ -100,26 +100,26 @@ function retainedMcpIds(catalogIds: string[], rows: Record<string, string[]>, ta
100
100
  */
101
101
  function resolveMcpSelections({
102
102
  cmd, requested, targets, registry, lock, ledger, manifestServers = null, interactive = false, promptFn, onStale,
103
- }: any): any {
103
+ } ) {
104
104
  const catalogIds = readAllServers(registry);
105
105
  const flagged = parseMcpFlag(requested, catalogIds);
106
106
  const rows = pinnedSelections(lock);
107
- const capable = targets.filter((harness: string) => mcpCapable(registry, harness));
108
- const retired = new Set<string>();
109
- const known = (ids: string[]) => {
107
+ const capable = targets.filter((harness ) => mcpCapable(registry, harness));
108
+ const retired = new Set ();
109
+ const known = (ids ) => {
110
110
  for (const id of ids) if (!catalogIds.includes(id)) retired.add(id);
111
111
  return catalogUnion(catalogIds, [ids]);
112
112
  };
113
113
 
114
- let prompted: string[] | null = null;
114
+ let prompted = null;
115
115
  if (!flagged && cmd === 'install' && interactive && capable.length) {
116
- const recorded = capable.filter((harness: string) => harness in rows).map((harness: string) => rows[harness]);
116
+ const recorded = capable.filter((harness ) => harness in rows).map((harness ) => rows[harness]);
117
117
  const seed = recorded.length ? catalogUnion(catalogIds, recorded.map(known))
118
118
  : manifestServers ? known(manifestServers) : [...catalogIds];
119
119
  prompted = promptFn(catalogIds, seed);
120
120
  }
121
121
 
122
- const pick = (harness: string): [string[] | string, string] => {
122
+ const pick = (harness ) => {
123
123
  if (flagged) return [flagged, 'flag'];
124
124
  if (prompted !== null) return [prompted, 'prompt'];
125
125
  if (harness in rows) return [known(rows[harness]), 'recorded'];
@@ -127,10 +127,10 @@ function resolveMcpSelections({
127
127
  if (manifestServers) return [known(manifestServers), 'manifest'];
128
128
  return [[], 'default'];
129
129
  };
130
- const selections: Record<string, string[] | string> = {};
131
- const sources: Record<string, string> = {};
130
+ const selections = {};
131
+ const sources = {};
132
132
  for (const harness of capable) [selections[harness], sources[harness]] = pick(harness);
133
- for (const [harness, ids] of Object.entries(rows)) if (!targets.includes(harness)) known(ids as string[]);
133
+ for (const [harness, ids] of Object.entries(rows)) if (!targets.includes(harness)) known(ids );
134
134
  if (retired.size && onStale) onStale([...retired].sort());
135
135
 
136
136
  return {
@@ -144,12 +144,12 @@ function resolveMcpSelections({
144
144
  /** The selections a scope has recorded, for readers that never prompt (reconcile, status, inventory):
145
145
  * each targeted MCP-capable harness's lock row, or 'keep' when the lock has none. Retired ids are
146
146
  * dropped silently. */
147
- function recordedMcpSelections({ registry, lock, ledger, targets, manifestServers = null }: any): any {
147
+ function recordedMcpSelections({ registry, lock, ledger, targets, manifestServers = null } ) {
148
148
  const catalogIds = readAllServers(registry);
149
149
  const rows = pinnedSelections(lock);
150
- const capable = targets.filter((harness: string) => mcpCapable(registry, harness));
150
+ const capable = targets.filter((harness ) => mcpCapable(registry, harness));
151
151
  return {
152
- selections: Object.fromEntries(capable.map((harness: string) => [harness,
152
+ selections: Object.fromEntries(capable.map((harness ) => [harness,
153
153
  harness in rows ? catalogUnion(catalogIds, [rows[harness]]) : 'keep'])),
154
154
  adoptable: adoptableMcpIds({ registry, lock, ledger, harnesses: capable, manifestServers }),
155
155
  retainedMcpIds: retainedMcpIds(catalogIds, rows, targets),
@@ -171,7 +171,7 @@ const KEY = {
171
171
  * case, bounded by a deadline for a genuinely unusable fd). Returns the decoded chunk, or null if
172
172
  * the fd is unusable.
173
173
  */
174
- function readKeypress(buf: Buffer): string | null {
174
+ function readKeypress(buf ) {
175
175
  try {
176
176
  const n = readSyncBlocking(0, buf);
177
177
  return buf.toString('utf8', 0, n);
@@ -187,7 +187,7 @@ function readKeypress(buf: Buffer): string | null {
187
187
  * the same primitive confirm()/promptLine() already use.
188
188
  * Returns selected server names, or null if no usable TTY (caller falls back).
189
189
  */
190
- function promptMcpCheckbox(servers: string[], initialSelected: string[], message = 'Select MCP servers to install:'): string[] | null {
190
+ function promptMcpCheckbox(servers , initialSelected , message = 'Select MCP servers to install:') {
191
191
  if (!process.stdin.isTTY || !process.stdout.isTTY) return null;
192
192
  if (servers.length === 0) return [];
193
193
 
@@ -195,7 +195,7 @@ function promptMcpCheckbox(servers: string[], initialSelected: string[], message
195
195
  let cursor = 0;
196
196
  const help = ' (up/down or j/k move, space toggle, a toggle-all, enter confirm)';
197
197
 
198
- const render = (first: boolean) => {
198
+ const render = (first ) => {
199
199
  if (!first) process.stdout.write(`${ESC}[${servers.length + 2}A`);
200
200
  console.log(message);
201
201
  console.log(help);
@@ -2,7 +2,7 @@
2
2
 
3
3
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): authored as `.ts`, run directly by Node
4
4
  // native type-stripping — no build step, no runtime dependency. Body stays CommonJS so a `.js`
5
- // caller's `require('../install/paths.ts')` keeps working while the rest of the tree is still `.js`.
5
+ // caller's `require('../install/paths.js')` keeps working while the rest of the tree is still `.js`.
6
6
  const path = require('node:path');
7
7
 
8
8
  const DOFLOW_DIR_NAME = '.doflow';
@@ -19,26 +19,26 @@ const INSTALL_MANIFEST_FILE_NAME = '.install-manifest.json';
19
19
  // material and DoFlow no longer owns their lifecycle.
20
20
  const LEGACY_BACKUP_ANCHOR_DIR_NAME = '.claude';
21
21
 
22
- interface ScopeInput {
23
- scopeRoot: string;
24
- }
22
+
23
+
24
+
25
25
 
26
- interface DoflowPaths {
27
- scopeRoot: string;
28
- doflowRoot: string;
29
- backupRoot: string;
30
- legacyBackupReadRoot: string;
31
- manifestPath: string;
32
- }
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
33
 
34
34
  /** Read-only legacy backup location for a scope. Never a write or prune target — see the note above. */
35
- function legacyBackupReadRoot({ scopeRoot }: ScopeInput): string {
35
+ function legacyBackupReadRoot({ scopeRoot } ) {
36
36
  if (typeof scopeRoot !== 'string' || !scopeRoot) throw new Error('scopeRoot is required');
37
37
  return path.join(path.resolve(scopeRoot), LEGACY_BACKUP_ANCHOR_DIR_NAME, BACKUP_DIR_NAME);
38
38
  }
39
39
 
40
40
  /** True for `<anything>/.claude/backups` — used to refuse writes/prunes against the legacy root. */
41
- function isLegacyBackupReadRoot(candidate: unknown): boolean {
41
+ function isLegacyBackupReadRoot(candidate ) {
42
42
  if (typeof candidate !== 'string' || !candidate) return false;
43
43
  const resolved = path.resolve(candidate);
44
44
  return path.basename(resolved) === BACKUP_DIR_NAME
@@ -49,7 +49,7 @@ function isLegacyBackupReadRoot(candidate: unknown): boolean {
49
49
  * read path handed only that root can still derive the legacy one. Returns null for any path that
50
50
  * is not shaped `<scopeRoot>/.doflow/backups` (a test fixture, a hand-passed directory) — the
51
51
  * bridge then stays inert rather than inventing a sibling `.claude` next to an arbitrary path. */
52
- function scopeRootFromCanonicalBackupRoot(backupRoot: unknown): string | null {
52
+ function scopeRootFromCanonicalBackupRoot(backupRoot ) {
53
53
  if (typeof backupRoot !== 'string' || !backupRoot) return null;
54
54
  const resolved = path.resolve(backupRoot);
55
55
  if (path.basename(resolved) !== BACKUP_DIR_NAME) return null;
@@ -59,7 +59,7 @@ function scopeRootFromCanonicalBackupRoot(backupRoot: unknown): string | null {
59
59
  }
60
60
 
61
61
  /** Resolve DoFlow-owned lifecycle metadata without anchoring it to a harness directory. */
62
- function doflowPaths({ scopeRoot }: ScopeInput): DoflowPaths {
62
+ function doflowPaths({ scopeRoot } ) {
63
63
  if (typeof scopeRoot !== 'string' || !scopeRoot) throw new Error('scopeRoot is required');
64
64
  const root = path.resolve(scopeRoot);
65
65
  const doflowRoot = path.join(root, DOFLOW_DIR_NAME);
@@ -11,7 +11,7 @@
11
11
  //
12
12
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): authored as `.ts`, run directly by Node
13
13
  // native type-stripping — no build step, no runtime dependency. Body stays CommonJS so a `.js`
14
- // caller's `require('../install/targets.ts')` keeps working while the rest of the tree is still `.js`.
14
+ // caller's `require('../install/targets.js')` keeps working while the rest of the tree is still `.js`.
15
15
  const os = require('node:os');
16
16
  const path = require('node:path');
17
17
 
@@ -24,12 +24,12 @@ const VALID = ['claude', 'codex', 'gemini', 'copilot', 'kiro', 'opencode', 'pi',
24
24
  * rest explicitly with `--target claude,codex,gemini`. */
25
25
  const DEFAULT_TARGETS = ['claude'];
26
26
 
27
- const TARGET_ALIASES: Record<string, string> = {
27
+ const TARGET_ALIASES = {
28
28
  agy: 'antigravity',
29
29
  };
30
30
 
31
31
  /** Default to DEFAULT_TARGETS; validate any explicitly requested. */
32
- function resolveTargets(requested: string[] | undefined): string[] {
32
+ function resolveTargets(requested ) {
33
33
  const rawTargets = requested && requested.length ? requested : [...DEFAULT_TARGETS];
34
34
  const targets = rawTargets.map((t) => TARGET_ALIASES[t] || t);
35
35
  for (const t of targets) {
@@ -40,10 +40,10 @@ function resolveTargets(requested: string[] | undefined): string[] {
40
40
  return [...new Set(targets)];
41
41
  }
42
42
 
43
- interface ToolDirsOptions {
44
- global?: boolean;
45
- projectRoot?: string;
46
- }
43
+
44
+
45
+
46
+
47
47
 
48
48
  /**
49
49
  * Map tool -> install root.
@@ -66,14 +66,14 @@ interface ToolDirsOptions {
66
66
  * reads (steering, agents, hooks, settings/mcp.json), so — unlike copilot — this is
67
67
  * the clean, symmetric case.
68
68
  * opencode -> Global config is `~/.config/opencode`, NOT `~/.opencode/` — a path DoFlow's own
69
- * docs asserted incorrectly for several releases (see src/adapters/opencode/index.ts).
69
+ * docs asserted incorrectly for several releases (see src/adapters/opencode/index.js).
70
70
  * Project scope is `.opencode`, asymmetric with the global path the same way gemini's
71
71
  * is.
72
72
  * pi -> Global config is `~/.pi/agent` — note the `agent/` segment; `~/.pi/settings.json`
73
73
  * is not a location Pi reads. Project scope is `.pi` (see
74
- * src/adapters/pi/index.ts's own `nativePaths()`, which this mirrors exactly).
74
+ * src/adapters/pi/index.js's own `nativePaths()`, which this mirrors exactly).
75
75
  */
76
- function toolDirs(opts: ToolDirsOptions = {}): Record<string, string> {
76
+ function toolDirs(opts = {}) {
77
77
  const { global = false, projectRoot = '.' } = opts;
78
78
  const root = global ? os.homedir() : path.resolve(projectRoot);
79
79
  return {
@@ -6,30 +6,30 @@
6
6
  //
7
7
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): authored as `.ts`, run directly by Node
8
8
  // native type-stripping — no build step, no runtime dependency. Body stays CommonJS so a `.js`
9
- // caller's `require('../install/tool-lifecycle.ts')` keeps working while the tree is still `.js`.
9
+ // caller's `require('../install/tool-lifecycle.js')` keeps working while the tree is still `.js`.
10
10
  const { execFileSync } = require('node:child_process');
11
11
 
12
12
  const SUPPORTED_PLATFORMS = new Set(['darwin', 'linux']);
13
13
 
14
- type ExecFileSyncImpl = (file: string, args: string[], opts: any) => any;
14
+
15
15
 
16
- function isSupportedPlatform(platform: string = process.platform): boolean {
16
+ function isSupportedPlatform(platform = process.platform) {
17
17
  return SUPPORTED_PLATFORMS.has(platform);
18
18
  }
19
19
 
20
- function commandText(command: string[]): string {
20
+ function commandText(command ) {
21
21
  return command.map((part) => JSON.stringify(part)).join(' ');
22
22
  }
23
23
 
24
- function failureKind(error: any): 'absent' | 'failed' {
24
+ function failureKind(error ) {
25
25
  return error?.code === 'ENOENT' ? 'absent' : 'failed';
26
26
  }
27
27
 
28
- function runInspection(command: string[], execFileSyncImpl: ExecFileSyncImpl): any {
28
+ function runInspection(command , execFileSyncImpl ) {
29
29
  try {
30
30
  const output = execFileSyncImpl(command[0], command.slice(1), { encoding: 'utf8', stdio: 'pipe' });
31
31
  return { command: [...command], result: 'succeeded', output: output == null ? '' : String(output) };
32
- } catch (error: any) {
32
+ } catch (error ) {
33
33
  return {
34
34
  command: [...command], result: failureKind(error),
35
35
  error: error?.message || String(error),
@@ -38,26 +38,26 @@ function runInspection(command: string[], execFileSyncImpl: ExecFileSyncImpl): a
38
38
  }
39
39
 
40
40
  /** Reduce every status command result to a safe tool state. */
41
- function normalizeToolState(inspections: any[]): string {
41
+ function normalizeToolState(inspections ) {
42
42
  if (inspections.every((inspection) => inspection.result === 'succeeded')) return 'installed';
43
43
  if (inspections.every((inspection) => inspection.result === 'absent')) return 'absent';
44
44
  if (inspections.some((inspection) => inspection.result === 'succeeded')) return 'unknown';
45
45
  return 'inspection-failed';
46
46
  }
47
47
 
48
- function inspectTool(tool: any, { execFileSyncImpl = execFileSync }: { execFileSyncImpl?: ExecFileSyncImpl } = {}): any {
49
- const inspections = tool.status.commands.map((command: string[]) => runInspection(command, execFileSyncImpl));
48
+ function inspectTool(tool , { execFileSyncImpl = execFileSync } = {}) {
49
+ const inspections = tool.status.commands.map((command ) => runInspection(command, execFileSyncImpl));
50
50
  return { state: normalizeToolState(inspections), inspections };
51
51
  }
52
52
 
53
- function inspectPrerequisites(tool: any, { execFileSyncImpl = execFileSync }: { execFileSyncImpl?: ExecFileSyncImpl } = {}): any[] {
54
- return (tool.prerequisites || []).map((name: string) => {
53
+ function inspectPrerequisites(tool , { execFileSyncImpl = execFileSync } = {}) {
54
+ return (tool.prerequisites || []).map((name ) => {
55
55
  const inspection = runInspection([name, '--version'], execFileSyncImpl);
56
56
  return { name, available: inspection.result === 'succeeded', inspection };
57
57
  });
58
58
  }
59
59
 
60
- function actionEligibility(tool: any, state: string, action: string, prerequisites: any[]): any {
60
+ function actionEligibility(tool , state , action , prerequisites ) {
61
61
  if (action === 'status') return { applicable: false, reason: 'status inspection only' };
62
62
  const contract = tool[action];
63
63
  if (!contract) return { applicable: false, reason: `no verified ${action} command is registered` };
@@ -79,12 +79,12 @@ function actionEligibility(tool: any, state: string, action: string, prerequisit
79
79
  * Inspect all status command vectors, then create a non-mutating action plan.
80
80
  * The registry can be the loaded registry or an { externalTools } fixture.
81
81
  */
82
- function planToolLifecycle({ registry, action = 'status', platform = process.platform, execFileSyncImpl = execFileSync }: { registry?: any; action?: string; platform?: string; execFileSyncImpl?: ExecFileSyncImpl } = {}): any {
82
+ function planToolLifecycle({ registry, action = 'status', platform = process.platform, execFileSyncImpl = execFileSync } = {}) {
83
83
  if (!['install', 'update', 'uninstall', 'status'].includes(action)) {
84
84
  throw new Error(`Unsupported external-tool action '${action}'`);
85
85
  }
86
86
  const supported = isSupportedPlatform(platform);
87
- const tools = (registry?.externalTools || []).map((tool: any) => {
87
+ const tools = (registry?.externalTools || []).map((tool ) => {
88
88
  if (!supported) {
89
89
  return {
90
90
  tool, state: 'unknown', inspections: [], prerequisites: [],
@@ -98,19 +98,19 @@ function planToolLifecycle({ registry, action = 'status', platform = process.pla
98
98
  return { action, platform, supported, tools };
99
99
  }
100
100
 
101
- function defaultDisplay(command: string[]): void { console.error(`[INFO] ${commandText(command)}`); }
101
+ function defaultDisplay(command ) { console.error(`[INFO] ${commandText(command)}`); }
102
102
 
103
103
  /**
104
104
  * Display and separately confirm every planned mutation. A failed command never prevents later
105
105
  * commands from being independently offered and executed.
106
106
  */
107
- function executeToolLifecycle({ plan, execFileSyncImpl = execFileSync, displayCommand = defaultDisplay, confirmCommand }: { plan?: any; execFileSyncImpl?: ExecFileSyncImpl; displayCommand?: (command: string[], tool?: any, action?: string) => void; confirmCommand?: (command: string[], tool?: any, action?: string) => boolean } = {}): any {
107
+ function executeToolLifecycle({ plan, execFileSyncImpl = execFileSync, displayCommand = defaultDisplay, confirmCommand } = {}) {
108
108
  if (!plan) throw new Error('executeToolLifecycle requires a plan');
109
109
  if (typeof confirmCommand !== 'function') throw new Error('executeToolLifecycle requires confirmCommand');
110
110
 
111
111
  const notAttempted = plan.tools
112
- .filter((item: any) => item.action.applicable)
113
- .map((item: any) => ({ tool: item.tool.id, status: 'not-attempted', command: [...item.action.command] }));
112
+ .filter((item ) => item.action.applicable)
113
+ .map((item ) => ({ tool: item.tool.id, status: 'not-attempted', command: [...item.action.command] }));
114
114
  const results = [];
115
115
  for (const item of plan.tools) {
116
116
  const action = item.action;
@@ -127,7 +127,7 @@ function executeToolLifecycle({ plan, execFileSyncImpl = execFileSync, displayCo
127
127
  try {
128
128
  const output = execFileSyncImpl(command[0], command.slice(1), { encoding: 'utf8', stdio: 'pipe' });
129
129
  results.push({ tool: item.tool.id, status: 'succeeded', command: [...command], output: output == null ? '' : String(output) });
130
- } catch (error: any) {
130
+ } catch (error ) {
131
131
  results.push({ tool: item.tool.id, status: 'failed', command: [...command], error: error?.message || String(error) });
132
132
  }
133
133
  }
@@ -13,7 +13,7 @@ const { execFileSync } = require('node:child_process');
13
13
  * unrelated binary could satisfy a mere PATH check, but only a real bash exits cleanly
14
14
  * on `--version`. ENOENT, a non-zero exit, or any other spawn error are all treated as
15
15
  * "not available"; the caller does not need to distinguish the reason. */
16
- function hasBashCapableShell(execFileSyncImpl: any = execFileSync): boolean {
16
+ function hasBashCapableShell(execFileSyncImpl = execFileSync) {
17
17
  try {
18
18
  execFileSyncImpl('bash', ['--version'], { stdio: 'ignore' });
19
19
  return true;