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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/bin/doflow.js +2 -2
  2. package/core/.antigravity-plugin/plugin.json +0 -1
  3. package/core/.claude-plugin/plugin.json +1 -1
  4. package/core/.codex-plugin/plugin.json +1 -1
  5. package/core/.plugin/plugin.json +1 -1
  6. package/core/harnesses/claude/hooks/mcp-tool-guard.sh +7 -17
  7. package/core/harnesses/claude/hooks/pre-bash-guard.sh +7 -17
  8. package/core/harnesses/claude/hooks/pre-implement-gate.sh +7 -18
  9. package/core/harnesses/claude/hooks/session-start.sh +5 -3
  10. package/core/harnesses/claude/hooks/stop-check.sh +5 -3
  11. package/core/harnesses/claude/hooks/subagent-audit.sh +5 -5
  12. package/core/harnesses/claude/hooks/user-prompt-submit.sh +5 -3
  13. package/core/harnesses/codex/hooks/mcp-tool-guard.sh +7 -15
  14. package/core/harnesses/codex/hooks/pre-bash-guard.sh +7 -15
  15. package/core/harnesses/codex/hooks/pre-implement-gate.sh +7 -16
  16. package/core/harnesses/codex/hooks/session-start.sh +5 -3
  17. package/core/harnesses/codex/hooks/stop-check.sh +6 -5
  18. package/core/harnesses/codex/hooks/subagent-audit.sh +17 -6
  19. package/core/harnesses/codex/hooks/user-prompt-submit.sh +5 -4
  20. package/core/harnesses/gemini/hooks/mcp-tool-guard.sh +7 -18
  21. package/core/harnesses/gemini/hooks/pre-bash-guard.sh +7 -18
  22. package/core/harnesses/gemini/hooks/pre-implement-gate.sh +7 -19
  23. package/core/harnesses/gemini/hooks/session-start.sh +5 -3
  24. package/core/harnesses/kiro/hooks/mcp-tool-guard.sh +20 -5
  25. package/core/harnesses/kiro/hooks/pre-bash-guard.sh +20 -5
  26. package/core/harnesses/kiro/hooks/pre-implement-gate.sh +20 -5
  27. package/core/harnesses/kiro/hooks/session-start.sh +11 -5
  28. package/core/harnesses/kiro/hooks/stop-check.sh +21 -30
  29. package/core/harnesses/pi/extensions/doflow-guard.js +159 -0
  30. package/core/harnesses/shared/hooks/ENVELOPE_MIGRATION.md +27 -11
  31. package/core/harnesses/shared/hooks/adapters/antigravity.js +14 -57
  32. package/core/harnesses/shared/hooks/bridge/bridge.sh +184 -0
  33. package/core/harnesses/shared/hooks/bridge/envelope.jq +60 -0
  34. package/core/harnesses/shared/hooks/bridge/respond.sh +62 -0
  35. package/core/harnesses/shared/hooks/policies/capture-failure.sh +4 -2
  36. package/core/harnesses/shared/hooks/policies/contract.sh +75 -0
  37. package/core/harnesses/shared/hooks/policies/deny-json.sh +39 -4
  38. package/core/harnesses/shared/hooks/policies/lib.sh +4 -2
  39. package/core/harnesses/shared/hooks/policies/mcp-tool-guard.sh +46 -34
  40. package/core/harnesses/shared/hooks/policies/pre-bash-guard.sh +75 -25
  41. package/core/harnesses/shared/hooks/policies/pre-implementation-gate.sh +67 -73
  42. package/core/harnesses/shared/hooks/policies/session-context.sh +37 -7
  43. package/core/harnesses/shared/hooks/policies/stop-check.sh +42 -15
  44. package/core/harnesses/shared/hooks/policies/subagent-audit.sh +35 -5
  45. package/core/harnesses/shared/hooks/policies/user-prompt-submit.sh +40 -7
  46. package/core/harnesses/shared/hooks/stream-hook-runner.js +69 -181
  47. package/core/registry/assets.json +19 -0
  48. package/core/registry/contracts.json +2 -2
  49. package/core/registry/harnesses.json +196 -10
  50. package/core/registry/lifecycle.json +2626 -7
  51. package/core/registry/storage.json +110 -83
  52. package/core/registry/verification.json +1 -1
  53. package/core/shared/scripts/doflow/bash/render-puml.sh +2 -2
  54. package/core/shared/scripts/doflow/bin/doflow-run +10 -6
  55. package/core/shared/skills/do-design/SKILL.md +6 -6
  56. package/core/shared/skills/do-execute-plan/SKILL.md +11 -10
  57. package/core/shared/skills/do-execute-plan/references/readiness_gate.md +2 -0
  58. package/core/shared/skills/do-execute-plan/references/scaffold.md +2 -2
  59. package/core/shared/skills/do-implement/SKILL.md +3 -2
  60. package/core/shared/skills/do-plan/SKILL.md +7 -8
  61. package/package.json +4 -2
  62. package/src/adapters/antigravity/{index.ts → index.js} +141 -105
  63. package/src/adapters/claude/{index.ts → index.js} +63 -49
  64. package/src/adapters/claude/{mcp.ts → mcp.js} +16 -16
  65. package/src/adapters/codex/{agents.ts → agents.js} +24 -24
  66. package/src/adapters/codex/{config.ts → config.js} +49 -49
  67. package/src/adapters/codex/{hooks.ts → hooks.js} +62 -27
  68. package/src/adapters/codex/{index.ts → index.js} +148 -105
  69. package/src/adapters/codex/{mcp.ts → mcp.js} +38 -38
  70. package/src/adapters/codex/{native-projection.ts → native-projection.js} +5 -5
  71. package/src/adapters/copilot/{index.ts → index.js} +42 -42
  72. package/src/adapters/{copy-tree.ts → copy-tree.js} +74 -74
  73. package/src/adapters/gemini/{hooks.ts → hooks.js} +78 -37
  74. package/src/adapters/gemini/{index.ts → index.js} +96 -57
  75. package/src/adapters/{hook-commands.ts → hook-commands.js} +8 -8
  76. package/src/adapters/{index.ts → index.js} +13 -13
  77. package/src/adapters/kiro/{index.ts → index.js} +49 -35
  78. package/src/adapters/{mcp-entries.ts → mcp-entries.js} +55 -55
  79. package/src/adapters/opencode/{index.ts → index.js} +52 -52
  80. package/src/adapters/pi/hooks.js +119 -0
  81. package/src/adapters/pi/{index.ts → index.js} +64 -39
  82. package/src/adapters/pi/{json-members.ts → json-members.js} +23 -23
  83. package/src/adapters/pi/{mcp.ts → mcp.js} +70 -70
  84. package/src/adapters/{resolve-source.ts → resolve-source.js} +1 -1
  85. package/src/cli/commands/{install.ts → install.js} +25 -25
  86. package/src/cli/commands/{list-backups.ts → list-backups.js} +4 -4
  87. package/src/cli/commands/{reconcile.ts → reconcile.js} +19 -19
  88. package/src/cli/commands/{remove.ts → remove.js} +10 -10
  89. package/src/cli/commands/{rollback.ts → rollback.js} +17 -17
  90. package/src/cli/commands/{self-update.ts → self-update.js} +3 -3
  91. package/src/cli/commands/{status.ts → status.js} +24 -24
  92. package/src/cli/commands/{tools.ts → tools.js} +16 -16
  93. package/src/cli/commands/{update.ts → update.js} +20 -20
  94. package/src/cli/{index.ts → index.js} +43 -31
  95. package/src/cli/{runtime-commands.ts → runtime-commands.js} +97 -58
  96. package/src/cli/{shared.ts → shared.js} +40 -40
  97. package/src/helper/{bash-helper.ts → bash-helper.js} +7 -7
  98. package/src/helper/{git.ts → git.js} +2 -2
  99. package/src/helper/{guardrails.ts → guardrails.js} +10 -10
  100. package/src/helper/{harness-paths.ts → harness-paths.js} +24 -24
  101. package/src/helper/{marker-merge.ts → marker-merge.js} +4 -4
  102. package/src/helper/{prompt.ts → prompt.js} +5 -5
  103. package/src/helper/{repo-root.ts → repo-root.js} +2 -2
  104. package/src/helper/{settings-merge.ts → settings-merge.js} +27 -27
  105. package/src/helper/{settings-scope.ts → settings-scope.js} +3 -3
  106. package/src/helper/{toml.ts → toml.js} +48 -48
  107. package/src/install/{backup-set.ts → backup-set.js} +16 -16
  108. package/src/install/{backup.ts → backup.js} +65 -65
  109. package/src/install/{context.ts → context.js} +15 -15
  110. package/src/install/{manifest.ts → manifest.js} +27 -27
  111. package/src/install/{mcp.ts → mcp.js} +30 -30
  112. package/src/install/{paths.ts → paths.js} +15 -15
  113. package/src/install/{targets.ts → targets.js} +10 -10
  114. package/src/install/{tool-lifecycle.ts → tool-lifecycle.js} +20 -20
  115. package/src/lifecycle/{bash-availability.ts → bash-availability.js} +1 -1
  116. package/src/lifecycle/coverage.js +57 -0
  117. package/src/lifecycle/hook-step.js +61 -0
  118. package/src/lifecycle/{index.ts → index.js} +160 -146
  119. package/src/lifecycle/{mcp-index.ts → mcp-index.js} +1 -1
  120. package/src/lifecycle/{policies.ts → policies.js} +11 -11
  121. package/src/lifecycle/{view.ts → view.js} +28 -28
  122. package/src/registry/{index.ts → index.js} +195 -66
  123. package/src/release/build-package.js +91 -0
  124. package/src/release/changelog-section.js +70 -0
  125. package/src/release/{sync-plugin-versions.ts → sync-plugin-versions.js} +4 -4
  126. package/src/runtime/advice/{cli.ts → cli.js} +31 -31
  127. package/src/runtime/advice/{client.ts → client.js} +44 -44
  128. package/src/runtime/advice/{config.ts → config.js} +16 -16
  129. package/src/runtime/advice/{doctor.ts → doctor.js} +32 -32
  130. package/src/runtime/advice/{endpoint-guard.ts → endpoint-guard.js} +20 -20
  131. package/src/runtime/advice/{kinds.ts → kinds.js} +16 -16
  132. package/src/runtime/advice/providers/{ollama-systemone.ts → ollama-systemone.js} +21 -21
  133. package/src/runtime/advice/{record.ts → record.js} +19 -19
  134. package/src/runtime/advice/{registry.ts → registry.js} +16 -16
  135. package/src/runtime/advice/{strength.ts → strength.js} +7 -7
  136. package/src/runtime/{brief-tools.ts → brief-tools.js} +50 -50
  137. package/src/runtime/{c4-project.ts → c4-project.js} +27 -27
  138. package/src/runtime/candidate.js +505 -0
  139. package/src/runtime/{capability-router.ts → capability-router.js} +39 -39
  140. package/src/runtime/{checkouts.ts → checkouts.js} +21 -21
  141. package/src/runtime/{claims.ts → claims.js} +44 -35
  142. package/src/runtime/{cli-result.ts → cli-result.js} +15 -8
  143. package/src/runtime/{cli.ts → cli.js} +59 -292
  144. package/src/runtime/{command-detect.ts → command-detect.js} +47 -47
  145. package/src/runtime/context/budget.js +203 -0
  146. package/src/runtime/context/compose.js +1367 -0
  147. package/src/runtime/context/delivery-store.js +102 -0
  148. package/src/runtime/context/mandatory.js +594 -0
  149. package/src/runtime/context/pointer.js +142 -0
  150. package/src/runtime/context-pack.js +1277 -0
  151. package/src/runtime/{decision-register.ts → decision-register.js} +67 -67
  152. package/src/runtime/evidence-fields.js +39 -0
  153. package/src/runtime/{evidence-ledger.ts → evidence-ledger.js} +32 -25
  154. package/src/runtime/failure/{capture.ts → capture.js} +29 -29
  155. package/src/runtime/failure/{classifier.ts → classifier.js} +4 -4
  156. package/src/runtime/failure/{cli.ts → cli.js} +30 -30
  157. package/src/runtime/failure/{home.ts → home.js} +6 -6
  158. package/src/runtime/failure/{store.ts → store.js} +32 -32
  159. package/src/runtime/{feature-resolve.ts → feature-resolve.js} +6 -6
  160. package/src/runtime/{freshness.ts → freshness.js} +59 -22
  161. package/src/runtime/{health.ts → health.js} +72 -72
  162. package/src/runtime/{history-compactor.ts → history-compactor.js} +25 -25
  163. package/src/runtime/{implementation-gate.ts → implementation-gate.js} +30 -30
  164. package/src/runtime/inventory/{coverage.ts → coverage.js} +10 -10
  165. package/src/runtime/inventory/{identity.ts → identity.js} +2 -2
  166. package/src/runtime/inventory/{index.ts → index.js} +36 -36
  167. package/src/runtime/inventory/{precedence.ts → precedence.js} +2 -2
  168. package/src/runtime/inventory/{read-scopes.ts → read-scopes.js} +9 -9
  169. package/src/runtime/inventory/{siblings.ts → siblings.js} +15 -15
  170. package/src/runtime/knowledge/{chunker.ts → chunker.js} +12 -12
  171. package/src/runtime/knowledge/{hybrid.ts → hybrid.js} +17 -17
  172. package/src/runtime/knowledge/{index-store.ts → index-store.js} +23 -23
  173. package/src/runtime/knowledge/{retrieval.ts → retrieval.js} +27 -27
  174. package/src/runtime/{leak-scan.ts → leak-scan.js} +12 -12
  175. package/src/runtime/lifecycle/{cli.ts → cli.js} +32 -32
  176. package/src/runtime/lifecycle/{event-store.ts → event-store.js} +48 -48
  177. package/src/runtime/lifecycle/{fold.ts → fold.js} +41 -41
  178. package/src/runtime/lifecycle/{followup.ts → followup.js} +54 -54
  179. package/src/runtime/lifecycle/{goal.ts → goal.js} +50 -50
  180. package/src/runtime/lifecycle/{intent-writer.ts → intent-writer.js} +5 -5
  181. package/src/runtime/lifecycle/{overview.ts → overview.js} +47 -47
  182. package/src/runtime/lifecycle/{release.ts → release.js} +29 -29
  183. package/src/runtime/lifecycle/{report-store.ts → report-store.js} +25 -25
  184. package/src/runtime/lifecycle/{retention.ts → retention.js} +37 -37
  185. package/src/runtime/lifecycle/{root.ts → root.js} +9 -9
  186. package/src/runtime/lifecycle/{status.ts → status.js} +64 -64
  187. package/src/runtime/lifecycle/{store-upkeep.ts → store-upkeep.js} +46 -46
  188. package/src/runtime/{locator-resolve.ts → locator-resolve.js} +7 -7
  189. package/src/runtime/{mask.ts → mask.js} +22 -22
  190. package/src/runtime/{mcp-consultations.ts → mcp-consultations.js} +54 -54
  191. package/src/runtime/{mcp-reach.ts → mcp-reach.js} +24 -24
  192. package/src/runtime/{model-router.ts → model-router.js} +20 -20
  193. package/src/runtime/{outcome.ts → outcome.js} +27 -27
  194. package/src/runtime/{reach.ts → reach.js} +21 -21
  195. package/src/runtime/{readiness-record.ts → readiness-record.js} +12 -12
  196. package/src/runtime/{readiness.ts → readiness.js} +113 -43
  197. package/src/runtime/{recovery.ts → recovery.js} +15 -15
  198. package/src/runtime/{research-request.ts → research-request.js} +34 -34
  199. package/src/runtime/{retrieval-plan.ts → retrieval-plan.js} +453 -104
  200. package/src/runtime/retrieval-record.js +223 -0
  201. package/src/runtime/scaffold/{artifacts.ts → artifacts.js} +22 -19
  202. package/src/runtime/scaffold/{fingerprint.ts → fingerprint.js} +3 -3
  203. package/src/runtime/scaffold/{generate.ts → generate.js} +109 -109
  204. package/src/runtime/scaffold/{languages.ts → languages.js} +34 -34
  205. package/src/runtime/source-version.js +289 -0
  206. package/src/runtime/storage/{cli.ts → cli.js} +9 -9
  207. package/src/runtime/storage/{engine.ts → engine.js} +37 -37
  208. package/src/runtime/storage/{registry.ts → registry.js} +19 -19
  209. package/src/runtime/storage/{roots.ts → roots.js} +8 -8
  210. package/src/runtime/storage/{rules.ts → rules.js} +26 -26
  211. package/src/runtime/storage/{upkeep.ts → upkeep.js} +35 -35
  212. package/src/runtime/storage/{work-status.ts → work-status.js} +39 -39
  213. package/src/runtime/{task-attempts.ts → task-attempts.js} +62 -62
  214. package/src/runtime/{task-classifier.ts → task-classifier.js} +34 -34
  215. package/src/runtime/{task-scope.ts → task-scope.js} +40 -15
  216. package/src/runtime/{task-state.ts → task-state.js} +86 -21
  217. package/src/runtime/trace/{indicators.ts → indicators.js} +22 -22
  218. package/src/runtime/trace/{ledger.ts → ledger.js} +42 -42
  219. package/src/runtime/trace/{render.ts → render.js} +7 -7
  220. package/src/runtime/trace/{views.ts → views.js} +40 -40
  221. package/src/runtime/verification/{contract-runner.ts → contract-runner.js} +23 -23
  222. package/src/runtime/verification/{engine.ts → engine.js} +143 -143
  223. package/src/runtime/verification/{registry.ts → registry.js} +6 -6
  224. package/src/runtime/verification/{scope-bound.ts → scope-bound.js} +50 -50
  225. package/src/runtime/verification/{test-selection.ts → test-selection.js} +28 -28
  226. package/src/runtime/{workflow-engine.ts → workflow-engine.js} +50 -50
  227. package/src/runtime/{workflow-orchestrator.ts → workflow-orchestrator.js} +91 -91
  228. package/src/runtime/{worktree.ts → worktree.js} +31 -31
  229. package/src/state/{index.ts → index.js} +26 -26
  230. package/src/state/{lockfile.ts → lockfile.js} +20 -20
  231. package/src/state/{run-lock.ts → run-lock.js} +44 -44
  232. package/core/.antigravity-plugin/hooks.json +0 -39
  233. package/core/harnesses/shared/hooks/adapters/arg-fields.js +0 -19
  234. package/core/harnesses/shared/hooks/adapters/gemini.js +0 -114
  235. package/core/harnesses/shared/hooks/hooks.json +0 -47
  236. package/src/runtime/context-pack.ts +0 -492
@@ -15,8 +15,8 @@ const fs = require('node:fs');
15
15
  const path = require('node:path');
16
16
  const crypto = require('node:crypto');
17
17
 
18
- const { fingerprint } = require('../copy-tree.ts');
19
- const { SKELETON, readDocument, insertMember, replaceValue, removeMember, replaceInner, renderNewDocument } = require('./json-members.ts');
18
+ const { fingerprint } = require('../copy-tree.js');
19
+ const { SKELETON, readDocument, insertMember, replaceValue, removeMember, replaceInner, renderNewDocument } = require('./json-members.js');
20
20
 
21
21
  const HARNESS = 'pi';
22
22
  const ASSET_ID = 'guidance.codex-pointer';
@@ -30,47 +30,47 @@ const NOTICES = Object.freeze({
30
30
  trust: 'MCP: Pi reads .pi/mcp.json only after this project is trusted (/trust or --approve); DoFlow does not grant trust.',
31
31
  });
32
32
 
33
- function sha256(text: any): string { return crypto.createHash('sha256').update(text).digest('hex'); }
33
+ function sha256(text ) { return crypto.createHash('sha256').update(text).digest('hex'); }
34
34
 
35
- function shorten(name: string): string { return name.length > 40 ? `${name.slice(0, 37)}...` : name; }
35
+ function shorten(name ) { return name.length > 40 ? `${name.slice(0, 37)}...` : name; }
36
36
 
37
- function collisionNotice(key: string, id: string): string {
37
+ function collisionNotice(key , id ) {
38
38
  return `MCP: kept your own entry '${shorten(key)}' and did not register DoFlow's '${shorten(id)}'; rename or remove yours to let DoFlow manage it.`;
39
39
  }
40
40
 
41
- function releasedNotice(id: string): string {
41
+ function releasedNotice(id ) {
42
42
  return `MCP: entry '${shorten(id)}' was changed outside DoFlow; it is yours now and DoFlow no longer updates or removes it.`;
43
43
  }
44
44
 
45
45
  /** Pi treats two server names that differ only in `-` versus `_` as one server. */
46
- function piServerKey(name: string): string { return name.replace(/_/g, '-'); }
46
+ function piServerKey(name ) { return name.replace(/_/g, '-'); }
47
47
 
48
- function refusalFor(file: string, reason: string): string { return `Pi MCP: ${file}: ${reason}; DoFlow did not change the file`; }
48
+ function refusalFor(file , reason ) { return `Pi MCP: ${file}: ${reason}; DoFlow did not change the file`; }
49
49
 
50
- function untouchedNotice(file: string): string {
50
+ function untouchedNotice(file ) {
51
51
  const shown = file.length > 80 ? `...${file.slice(-77)}` : file;
52
52
  return `MCP: left ${shown} untouched because it cannot be edited safely; DoFlow no longer manages the entries in it.`;
53
53
  }
54
54
 
55
55
  /** DoFlow's entry for one catalog server, or the reason Pi cannot take it. */
56
- function renderPiEntry(server: any): any {
56
+ function renderPiEntry(server ) {
57
57
  if (server.transport !== 'stdio' || typeof server.command !== 'string' || !server.command) {
58
58
  return { refusal: `Pi MCP: server '${server.id}' is not a stdio server; DoFlow writes only stdio entries for Pi` };
59
59
  }
60
60
  if (typeof server.id !== 'string' || !SERVER_NAME.test(server.id)) {
61
61
  return { refusal: `Pi MCP: server id '${server.id}' is not a valid Pi server name` };
62
62
  }
63
- const entry: any = { command: server.command };
63
+ const entry = { command: server.command };
64
64
  if (Array.isArray(server.args) && server.args.length) entry.args = [...server.args];
65
65
  if (server.env && typeof server.env === 'object' && Object.keys(server.env).length) entry.env = { ...server.env };
66
66
  return { entry };
67
67
  }
68
68
 
69
- function mcpRows(ledger: any): any[] {
70
- return (ledger?.resources || []).filter((row: any) => row.harness === HARNESS && row.kind === 'mcp-server');
69
+ function mcpRows(ledger ) {
70
+ return (ledger?.resources || []).filter((row ) => row.harness === HARNESS && row.kind === 'mcp-server');
71
71
  }
72
72
 
73
- function readSnapshotFile(file: string, fsImpl: any): any {
73
+ function readSnapshotFile(file , fsImpl ) {
74
74
  if (!fsImpl.existsSync(file)) return { exists: false, text: '', hash: sha256(''), doc: ABSENT_DOCUMENT };
75
75
  const bytes = fsImpl.readFileSync(file);
76
76
  const text = bytes.toString('utf8');
@@ -82,31 +82,31 @@ function readSnapshotFile(file: string, fsImpl: any): any {
82
82
 
83
83
  /** Read the selected server file and every file a ledger row names. Nothing is read when there is
84
84
  * neither a selection nor a row, so a run with no Pi MCP work touches no MCP file. */
85
- function discoverPiMcp({ selected = [], rows = [], file, fsImpl = fs }: any): any {
86
- const files = new Set<string>(rows.map((row: any) => row.target));
85
+ function discoverPiMcp({ selected = [], rows = [], file, fsImpl = fs } ) {
86
+ const files = new Set (rows.map((row ) => row.target));
87
87
  if (selected.length) files.add(file);
88
88
  return Object.fromEntries([...files].map((target) => [target, readSnapshotFile(target, fsImpl)]));
89
89
  }
90
90
 
91
- function memberOf(doc: any, key: string): any { return doc.servers?.members.find((member: any) => member.key === key) ?? null; }
91
+ function memberOf(doc , key ) { return doc.servers?.members.find((member ) => member.key === key) ?? null; }
92
92
 
93
93
  /** The servers DoFlow owns in Pi's mcp.json now: rows whose entry still holds the value they record. */
94
- function ownedPiMcpIds({ rows = [], snapshot = {} }: any): string[] {
95
- const owned = rows.filter((row: any) => {
94
+ function ownedPiMcpIds({ rows = [], snapshot = {} } ) {
95
+ const owned = rows.filter((row ) => {
96
96
  const doc = snapshot[row.target]?.doc;
97
97
  const member = doc?.ok ? memberOf(doc, row.identity) : null;
98
98
  return member !== null && fingerprint(member.value) === row.fingerprint;
99
99
  });
100
- return [...new Set<string>(owned.map((row: any) => row.identity))];
100
+ return [...new Set (owned.map((row ) => row.identity))];
101
101
  }
102
102
 
103
- function twinOf(doc: any, key: string): any {
104
- return doc.servers?.members.find((member: any) => member.key !== key && piServerKey(member.key) === piServerKey(key)) ?? null;
103
+ function twinOf(doc , key ) {
104
+ return doc.servers?.members.find((member ) => member.key !== key && piServerKey(member.key) === piServerKey(key)) ?? null;
105
105
  }
106
106
 
107
- function sameValue(a: any, b: any): boolean { return JSON.stringify(a) === JSON.stringify(b); }
107
+ function sameValue(a , b ) { return JSON.stringify(a) === JSON.stringify(b); }
108
108
 
109
- function baseChange({ target, operation, id, snapshot }: any): any {
109
+ function baseChange({ target, operation, id, snapshot } ) {
110
110
  return {
111
111
  assetId: ASSET_ID, target, operation,
112
112
  ownershipIdentity: `doflow:${HARNESS}:mcp-server:${id}`,
@@ -115,36 +115,36 @@ function baseChange({ target, operation, id, snapshot }: any): any {
115
115
  };
116
116
  }
117
117
 
118
- function writeChange({ target, operation, id, entry, snapshot }: any): any {
118
+ function writeChange({ target, operation, id, entry, snapshot } ) {
119
119
  return { ...baseChange({ target, operation, id, snapshot }), entry, fingerprint: fingerprint(entry), afterFingerprint: fingerprint(entry) };
120
120
  }
121
121
 
122
- function releaseChange({ row, snapshot }: any): any {
122
+ function releaseChange({ row, snapshot } ) {
123
123
  const id = row.identity;
124
124
  return { ...baseChange({ target: row.target, operation: 'remove', id, snapshot }), release: true, fingerprint: row.fingerprint };
125
125
  }
126
126
 
127
- function planPiMcp({ selected = [], rows = [], file, scope, removing = false, snapshot = {}, assets = [] }: any): any {
128
- const changes: any[] = [];
129
- const conflicts: string[] = [];
130
- const notices: string[] = [];
127
+ function planPiMcp({ selected = [], rows = [], file, scope, removing = false, snapshot = {}, assets = [] } ) {
128
+ const changes = [];
129
+ const conflicts = [];
130
+ const notices = [];
131
131
  if (!removing && !selected.length && !rows.length) return { changes, conflicts, notices };
132
132
  if (removing && !rows.length) return { changes, conflicts, notices };
133
- if (!assets.some((asset: any) => asset.id === ASSET_ID)) {
133
+ if (!assets.some((asset ) => asset.id === ASSET_ID)) {
134
134
  return { changes, conflicts: [`Pi MCP needs the ${ASSET_ID} asset to record ownership`], notices };
135
135
  }
136
136
 
137
137
  // An install or update refuses a file it cannot edit; a removal must still uninstall everything
138
138
  // else, so it releases the rows for that file and leaves the file as it is.
139
- const refused = new Set<string>();
140
- for (const [target, entry] of Object.entries(snapshot) as [string, any][]) {
139
+ const refused = new Set ();
140
+ for (const [target, entry] of Object.entries(snapshot) ) {
141
141
  if (entry.doc.ok) continue;
142
142
  refused.add(target);
143
143
  if (removing) notices.push(untouchedNotice(target));
144
144
  else conflicts.push(refusalFor(target, entry.doc.reason));
145
145
  }
146
146
 
147
- const matched = new Set<any>();
147
+ const matched = new Set ();
148
148
  if (!removing) {
149
149
  if (selected.length) {
150
150
  notices.push(NOTICES.surface, NOTICES.extension);
@@ -154,7 +154,7 @@ function planPiMcp({ selected = [], rows = [], file, scope, removing = false, sn
154
154
  for (const server of selected) {
155
155
  const { entry: desired, refusal } = renderPiEntry(server);
156
156
  if (refusal) { conflicts.push(refusal); continue; }
157
- const row = rows.find((item: any) => item.identity === server.id && item.target === file);
157
+ const row = rows.find((item ) => item.identity === server.id && item.target === file);
158
158
  if (row) matched.add(row);
159
159
  const member = memberOf(doc, server.id);
160
160
  const twin = twinOf(doc, server.id);
@@ -189,21 +189,21 @@ function planPiMcp({ selected = [], rows = [], file, scope, removing = false, sn
189
189
  }
190
190
  }
191
191
 
192
- return { changes: changes.filter((change: any) => !refused.has(change.target) || (removing && change.release)), conflicts, notices };
192
+ return { changes: changes.filter((change ) => !refused.has(change.target) || (removing && change.release)), conflicts, notices };
193
193
  }
194
194
 
195
- function isSymlink(file: string, fsImpl: any): boolean {
195
+ function isSymlink(file , fsImpl ) {
196
196
  try { return fsImpl.lstatSync(file).isSymbolicLink(); } catch { return false; }
197
197
  }
198
198
 
199
199
  /** Where a write to `file` lands: a symlinked mcp.json is written through to the file it points at,
200
200
  * so the link stays a link and its target receives the entries. */
201
- function writePath(file: string, fsImpl: any): string {
201
+ function writePath(file , fsImpl ) {
202
202
  if (!isSymlink(file, fsImpl)) return file;
203
203
  try { return fsImpl.realpathSync(file); } catch { return path.resolve(path.dirname(file), fsImpl.readlinkSync(file)); }
204
204
  }
205
205
 
206
- function atomicWrite(file: string, content: string, fsImpl: any): void {
206
+ function atomicWrite(file , content , fsImpl ) {
207
207
  const dest = writePath(file, fsImpl);
208
208
  fsImpl.mkdirSync(path.dirname(dest), { recursive: true });
209
209
  // The rename gives the file the temp file's mode; an mcp.json kept private for its tokens stays so.
@@ -219,28 +219,28 @@ function atomicWrite(file: string, content: string, fsImpl: any): void {
219
219
  }
220
220
 
221
221
  /** Replay one file's edits against the text read now, each against a fresh parse of the last result. */
222
- function editedText(text: string, group: any[]): string {
223
- const parse = (current: string) => {
222
+ function editedText(text , group ) {
223
+ const parse = (current ) => {
224
224
  const doc = readDocument(current);
225
225
  if (!doc.ok) throw new Error(`Pi MCP: cannot edit the planned file: ${doc.reason}`);
226
226
  return doc;
227
227
  };
228
228
  let next = text;
229
- for (const change of group.filter((item: any) => item.operation === 'remove')) {
229
+ for (const change of group.filter((item ) => item.operation === 'remove')) {
230
230
  const doc = parse(next);
231
231
  const member = memberOf(doc, change.identity);
232
232
  if (member) next = removeMember(next, doc.servers, member);
233
233
  }
234
- for (const change of group.filter((item: any) => item.operation === 'update')) {
234
+ for (const change of group.filter((item ) => item.operation === 'update')) {
235
235
  const doc = parse(next);
236
236
  const member = memberOf(doc, change.identity);
237
237
  if (member) next = replaceValue(next, member, change.entry, doc);
238
238
  }
239
- const creates = group.filter((item: any) => item.operation === 'create');
239
+ const creates = group.filter((item ) => item.operation === 'create');
240
240
  for (const [index, change] of creates.entries()) {
241
241
  const doc = parse(next);
242
242
  if (!doc.servers) {
243
- const entries = Object.fromEntries(creates.slice(index).map((item: any) => [item.identity, item.entry]));
243
+ const entries = Object.fromEntries(creates.slice(index).map((item ) => [item.identity, item.entry]));
244
244
  return insertMember(next, doc.root, 'mcpServers', entries, doc);
245
245
  }
246
246
  next = insertMember(next, doc.servers, change.identity, change.entry, doc);
@@ -251,33 +251,33 @@ function editedText(text: string, group: any[]): string {
251
251
  /** Undo what DoFlow added around its entries once the last of them is gone: the mcpServers member
252
252
  * it inserted, or the inner whitespace of the container it first wrote into. `origin` is recorded
253
253
  * on the ledger rows (see originFor); without it the emptied container is left as it is. */
254
- function restoredText(text: string, origin: any): string {
254
+ function restoredText(text , origin ) {
255
255
  const doc = readDocument(text);
256
256
  if (!doc.ok || !doc.servers || doc.servers.members.length) return text;
257
257
  if (origin.created === 'member') return replaceInner(text, doc.servers, origin.inner);
258
- const next = removeMember(text, doc.root, doc.root.members.find((member: any) => member.key === 'mcpServers'));
258
+ const next = removeMember(text, doc.root, doc.root.members.find((member ) => member.key === 'mcpServers'));
259
259
  if (origin.inner === undefined) return next;
260
260
  const after = readDocument(next);
261
261
  return after.root.members.length ? next : replaceInner(next, after.root, origin.inner);
262
262
  }
263
263
 
264
- function applyPiMcp(changes: any[], { fsImpl = fs }: { fsImpl?: any } = {}): { applied: number } {
265
- const groups = new Map<string, any[]>();
264
+ function applyPiMcp(changes , { fsImpl = fs } = {}) {
265
+ const groups = new Map ();
266
266
  for (const change of changes) {
267
267
  if (!groups.has(change.target)) groups.set(change.target, []);
268
- groups.get(change.target)!.push(change);
268
+ groups.get(change.target) .push(change);
269
269
  }
270
270
  let applied = 0;
271
271
  for (const [target, all] of groups) {
272
- const group = all.filter((change: any) => !change.release);
272
+ const group = all.filter((change ) => !change.release);
273
273
  if (!group.length) continue;
274
274
  const exists = fsImpl.existsSync(target);
275
275
  const bytes = exists ? fsImpl.readFileSync(target) : Buffer.alloc(0);
276
276
  if (sha256(bytes) !== group[0].baseHash) throw new Error(`Pi MCP: ${target} changed after planning; nothing was written, re-run the command`);
277
277
  const text = bytes.toString('utf8');
278
- const creates = group.filter((change: any) => change.operation === 'create');
279
- const origin = group.find((change: any) => change.origin)?.origin;
280
- let next = exists ? editedText(text, group) : renderNewDocument(creates.map((change: any) => [change.identity, change.entry]));
278
+ const creates = group.filter((change ) => change.operation === 'create');
279
+ const origin = group.find((change ) => change.origin)?.origin;
280
+ let next = exists ? editedText(text, group) : renderNewDocument(creates.map((change ) => [change.identity, change.entry]));
281
281
  // Only a file DoFlow created is deleted, and never through a symlink; a user's own file that
282
282
  // happens to equal the skeleton stays.
283
283
  if (exists && origin?.created === 'file' && next === SKELETON) {
@@ -291,12 +291,12 @@ function applyPiMcp(changes: any[], { fsImpl = fs }: { fsImpl?: any } = {}): { a
291
291
  return { applied };
292
292
  }
293
293
 
294
- function statusFor({ id, target, status }: { id: string, target: string, status: string }): any {
294
+ function statusFor({ id, target, status } ) {
295
295
  return { harness: HARNESS, assetId: ASSET_ID, capability: 'mcp', identity: id, target,
296
296
  ownershipIdentity: `doflow:${HARNESS}:mcp-server:${id}`, status };
297
297
  }
298
298
 
299
- function resourceFor({ id, target, value, origin }: { id: string, target: string, value: any, origin?: any }): any {
299
+ function resourceFor({ id, target, value, origin } ) {
300
300
  return { assetId: ASSET_ID, target, ownershipIdentity: `doflow:${HARNESS}:mcp-server:${id}`, kind: 'mcp-server', identity: id,
301
301
  fingerprint: fingerprint(value), sourceVersion: 'registry-v1', projection: { renderer: RENDERER }, ...(origin ? { origin } : {}) };
302
302
  }
@@ -305,15 +305,15 @@ function resourceFor({ id, target, value, origin }: { id: string, target: string
305
305
  * the whole file, the mcpServers member, or the first member of an empty mcpServers (with the
306
306
  * container's original inner whitespace). A row already carrying it passes it on; otherwise it is
307
307
  * read from the file as plan saw it. Only whitespace is recorded, never file content. */
308
- function originFor(target: string, rows: any[], snapshot: any): any {
309
- const carried = rows.find((row: any) => row.target === target && row.origin)?.origin;
308
+ function originFor(target , rows , snapshot ) {
309
+ const carried = rows.find((row ) => row.target === target && row.origin)?.origin;
310
310
  if (carried) return carried;
311
311
  const before = snapshot[target];
312
312
  if (!before) return undefined;
313
313
  if (!before.exists) return { created: 'file' };
314
314
  const { doc, text } = before;
315
315
  if (!doc.ok) return undefined;
316
- const inner = (node: any) => text.slice(node.open + 1, node.close);
316
+ const inner = (node ) => text.slice(node.open + 1, node.close);
317
317
  if (!doc.servers) return doc.root.members.length ? { created: 'key' } : { created: 'key', inner: inner(doc.root) };
318
318
  return doc.servers.members.length ? undefined : { created: 'member', inner: inner(doc.servers) };
319
319
  }
@@ -321,26 +321,26 @@ function originFor(target: string, rows: any[], snapshot: any): any {
321
321
  /** Statuses and ledger resources for the Pi MCP entries. `snapshot` is what plan read before apply:
322
322
  * an entry it held that DoFlow did not own then, or held with a value its row no longer matched, is
323
323
  * the user's, whatever it holds now. */
324
- function verifyPiMcp({ selected = [], rows = [], file, snapshot = {}, removing = false, fsImpl = fs }: any): any {
325
- const statuses: any[] = [];
326
- const resources: any[] = [];
327
- const conflicts: string[] = [];
328
- const current: Record<string, any> = {};
329
- for (const target of new Set<string>([...(selected.length ? [file] : []), ...rows.map((row: any) => row.target)])) {
324
+ function verifyPiMcp({ selected = [], rows = [], file, snapshot = {}, removing = false, fsImpl = fs } ) {
325
+ const statuses = [];
326
+ const resources = [];
327
+ const conflicts = [];
328
+ const current = {};
329
+ for (const target of new Set ([...(selected.length ? [file] : []), ...rows.map((row ) => row.target)])) {
330
330
  current[target] = readSnapshotFile(target, fsImpl).doc;
331
331
  if (!current[target].ok && !removing) conflicts.push(refusalFor(target, current[target].reason));
332
332
  }
333
- const memberNow = (target: string, id: string) => (current[target]?.ok ? memberOf(current[target], id) : null);
334
- const foreign = (target: string, id: string) => {
333
+ const memberNow = (target , id ) => (current[target]?.ok ? memberOf(current[target], id) : null);
334
+ const foreign = (target , id ) => {
335
335
  const before = snapshot[target]?.doc;
336
336
  if (!before?.ok) return false;
337
- const row = rows.find((item: any) => item.identity === id && item.target === target);
337
+ const row = rows.find((item ) => item.identity === id && item.target === target);
338
338
  const member = memberOf(before, id);
339
339
  if (!member) return Boolean(twinOf(before, id));
340
340
  return !row || fingerprint(member.value) !== row.fingerprint;
341
341
  };
342
342
 
343
- const verified = new Set<string>();
343
+ const verified = new Set ();
344
344
  if (!removing) {
345
345
  for (const server of selected) {
346
346
  const { entry: desired } = renderPiEntry(server);
@@ -359,7 +359,7 @@ function verifyPiMcp({ selected = [], rows = [], file, snapshot = {}, removing =
359
359
  const id = row.identity;
360
360
  if (verified.has(`${row.target}\u0000${id}`)) continue;
361
361
  const member = memberNow(row.target, id);
362
- let status: string;
362
+ let status ;
363
363
  if (!current[row.target].ok) status = 'not-managed';
364
364
  else if (!member) status = 'absent';
365
365
  else if (foreign(row.target, id) || fingerprint(member.value) !== row.fingerprint) status = 'not-managed';
@@ -7,7 +7,7 @@ const path = require('node:path');
7
7
  /** Resolve a registry-declared source path against the repo root, refusing escapes. Shared by the
8
8
  * common projection module and by per-adapter native-projection normalizers, which is why it lives
9
9
  * in its own module rather than in index.js — a normalizer importing index.js would be a cycle. */
10
- function resolveRegistrySource(registry: any, source: any, label: string): string {
10
+ function resolveRegistrySource(registry , source , label ) {
11
11
  if (typeof registry.repoRoot !== 'string' || !registry.repoRoot) throw new Error(`Registry repoRoot is required for ${label}`);
12
12
  if (typeof source !== 'string' || !source) throw new Error(`Registry ${label} source is required`);
13
13
  const root = path.resolve(registry.repoRoot);
@@ -4,31 +4,31 @@
4
4
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
5
5
  const os = require('node:os');
6
6
  const path = require('node:path');
7
- const { resolveTargets, toolDirs } = require('../../install/targets.ts');
8
- const { resolveContext, printContext } = require('../../install/context.ts');
7
+ const { resolveTargets, toolDirs } = require('../../install/targets.js');
8
+ const { resolveContext, printContext } = require('../../install/context.js');
9
9
  const {
10
10
  BackupError, DEFAULT_BACKUP_RETENTION, createFileBackup, applyRetention, formatBytes, retentionNote,
11
- } = require('../../install/backup.ts');
12
- const { backupSetFromPlan } = require('../../install/backup-set.ts');
13
- const { ledgerPath } = require('../../state/index.ts');
14
- const { writeManifest, readInstallManifest } = require('../../install/manifest.ts');
15
- const { confirm } = require('../../helper/prompt.ts');
16
- const { sourceCommit } = require('../../helper/git.ts');
17
- const { chmodHooksExecutable } = require('../../helper/settings-scope.ts');
18
- const { promptMcpCheckbox, resolveMcpSelections } = require('../../install/mcp.ts');
19
- const { loadRegistry } = require('../../registry/index.ts');
20
- const { storageAfterInstall } = require('../../runtime/storage/upkeep.ts');
21
- const { applyLifecycle, applyMcpIndex, recordMcpOwnership } = require('../../lifecycle/index.ts');
11
+ } = require('../../install/backup.js');
12
+ const { backupSetFromPlan } = require('../../install/backup-set.js');
13
+ const { ledgerPath } = require('../../state/index.js');
14
+ const { writeManifest, readInstallManifest } = require('../../install/manifest.js');
15
+ const { confirm } = require('../../helper/prompt.js');
16
+ const { sourceCommit } = require('../../helper/git.js');
17
+ const { chmodHooksExecutable } = require('../../helper/settings-scope.js');
18
+ const { promptMcpCheckbox, resolveMcpSelections } = require('../../install/mcp.js');
19
+ const { loadRegistry } = require('../../registry/index.js');
20
+ const { storageAfterInstall } = require('../../runtime/storage/upkeep.js');
21
+ const { applyLifecycle, applyMcpIndex, recordMcpOwnership } = require('../../lifecycle/index.js');
22
22
  const {
23
23
  codexScope, registryLifecycleView, printRegistryLifecycle, printPlanNotices, assertSafeRegistryPlan,
24
24
  lockDocument, recordLock,
25
- } = require('../../lifecycle/view.ts');
25
+ } = require('../../lifecycle/view.js');
26
26
  const {
27
27
  REPO_ROOT, SCRIPT_DIR, pkg, scopeOf, installPaths, reportRetiredMcp, scopeSelectionState, printMcpSelection, plannedMcpSelections,
28
28
  printRecordedMcpOwnership, buildAdapterRegistry, refuseHomeRootedProject, holdRunLock, checkpointRunLock,
29
- } = require('../shared.ts');
29
+ } = require('../shared.js');
30
30
 
31
- function cmdInstall(o: any): void {
31
+ function cmdInstall(o ) {
32
32
  refuseHomeRootedProject(o, 'install');
33
33
  const targets = resolveTargets(o.targets);
34
34
  const scope = scopeOf(o);
@@ -55,7 +55,7 @@ function cmdInstall(o: any): void {
55
55
  // One lifecycle view across every requested target — computed unconditionally (not only under
56
56
  // --dry-run) so its safety gate and its plan are the exact same object the real apply below uses.
57
57
  const lifecycleView = registryLifecycleView({ registry, repoRoot: REPO_ROOT, scope, dirs, targets,
58
- mcpSelections: selection.selections, mcpAdoptable: selection.adoptable, retainedMcpIds: selection.retainedMcpIds,
58
+ mcpSelections: selection.selections, mcpAdoptable: selection.adoptable, retainedMcpIds: selection.retainedMcpIds, operation: 'install',
59
59
  force: o.force, adopt: o.adopt === true, permissions: o.permissions === true, statusline: o.statusline === true });
60
60
  if (!lifecycleView.plan.safe) { assertSafeRegistryPlan(lifecycleView); return; }
61
61
 
@@ -117,7 +117,7 @@ function cmdInstall(o: any): void {
117
117
  stateRoot: lifecycleView.stateRoot, ledger: lifecycleView.ledger });
118
118
  for (const target of lifecycleView.plan.targets) {
119
119
  if (target.skipped || !target.changes.length) continue;
120
- const owned = result.ledger.resources.filter((resource: any) => resource.harness === target.harness).length;
120
+ const owned = result.ledger.resources.filter((resource ) => resource.harness === target.harness).length;
121
121
  console.log(`[INFO] ${target.harness}: lifecycle verified (${owned} owned resource(s))`);
122
122
  }
123
123
  ledgerAfter = result.ledger;
@@ -167,10 +167,10 @@ function cmdInstall(o: any): void {
167
167
  }
168
168
 
169
169
  /** Run a backup step; a BackupError stops the command before anything is changed. */
170
- function backupStep(step: () => any): any {
170
+ function backupStep(step ) {
171
171
  try {
172
172
  return step();
173
- } catch (error: any) {
173
+ } catch (error ) {
174
174
  if (!(error instanceof BackupError)) throw error;
175
175
  console.error(`[ERROR] Backup failed, nothing was changed: ${error.message}`);
176
176
  process.exit(1);
@@ -178,7 +178,7 @@ function backupStep(step: () => any): any {
178
178
  }
179
179
 
180
180
  /** Print what a backup step wrote and return its id ('' when there was nothing to back up). */
181
- function reportBackup(backup: any): string {
181
+ function reportBackup(backup ) {
182
182
  if (!backup) {
183
183
  console.error('[INFO] Backup: nothing to back up (no file changes)');
184
184
  return '';
@@ -188,22 +188,22 @@ function reportBackup(backup: any): string {
188
188
  }
189
189
 
190
190
  /** The dry-run backup lines for a set the real run would back up. */
191
- function printBackupDryRun(set: any, destination: string): void {
191
+ function printBackupDryRun(set , destination ) {
192
192
  if (set.count === 0) {
193
193
  console.log('[DRY] Backup: nothing to back up (no file changes)');
194
194
  } else {
195
195
  console.log(`[DRY] Would back up ${set.count} file(s), ${formatBytes(set.bytes)} (${set.bytes} bytes; ${set.absent} not present yet) to ${destination}`);
196
196
  }
197
- const mcpOnly = set.excluded.filter((item: any) => item.reason === 'mcp-entries-only').length;
197
+ const mcpOnly = set.excluded.filter((item ) => item.reason === 'mcp-entries-only').length;
198
198
  if (mcpOnly > 0) console.log(`[DRY] Not backed up: ${mcpOnly} file(s) holding only MCP entries`);
199
199
  }
200
200
 
201
201
  /** Keep the newest backups after a run that changed files; never changes the exit code. */
202
- function applyBackupRetention({ backupRoot, prune, keep, bid }: any): void {
202
+ function applyBackupRetention({ backupRoot, prune, keep, bid } ) {
203
203
  let retention;
204
204
  try {
205
205
  retention = applyRetention({ backupRoot, keep, protect: bid ? [bid] : [] });
206
- } catch (error: any) {
206
+ } catch (error ) {
207
207
  console.error(`[WARN] Backups: could not apply retention: ${error.message}`);
208
208
  return;
209
209
  }
@@ -2,10 +2,10 @@
2
2
  // `doflow list-backups` — the backup table for this scope. Takes no project-path positional
3
3
  // (rollback's one positional slot is the backup id); scope is -g/--global vs cwd-rooted project.
4
4
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
5
- const { listBackups } = require('../../install/backup.ts');
6
- const { installPaths, printBackupTable } = require('../shared.ts');
5
+ const { listBackups } = require('../../install/backup.js');
6
+ const { installPaths, printBackupTable } = require('../shared.js');
7
7
 
8
- function cmdListBackups(o: any): void {
8
+ function cmdListBackups(o ) {
9
9
  // rollback/list-backups don't take a project-path positional (their one positional slot is the
10
10
  // backup id for rollback) — scope is -g/--global vs default project rooted at cwd.
11
11
  const scope = { global: o.global, projectRoot: '.' };
@@ -14,7 +14,7 @@ function cmdListBackups(o: any): void {
14
14
  // listBackups now reads the canonical root AND the legacy pre-.doflow one, so the footer must name
15
15
  // the roots the rows actually came from: reporting restore points as living in a directory that
16
16
  // does not exist on this machine sends a user looking for recovery material to the wrong place.
17
- const roots = [...new Set(rows.map((r: any) => r.backupRoot))];
17
+ const roots = [...new Set(rows.map((r ) => r.backupRoot))];
18
18
  printBackupTable(rows, roots.length ? roots.join(', ') : lifecyclePaths.backupRoot);
19
19
  }
20
20
 
@@ -2,31 +2,31 @@
2
2
  // `doflow reconcile` — converge observed state onto the doflow.lock pin: report drift, then heal
3
3
  // it on confirmation. Never re-prompts for MCP; selections ride exactly as pinned.
4
4
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
5
- const { toolDirs } = require('../../install/targets.ts');
6
- const { resolveContext, printContext } = require('../../install/context.ts');
7
- const { writeManifest } = require('../../install/manifest.ts');
8
- const { confirm } = require('../../helper/prompt.ts');
9
- const { sourceCommit } = require('../../helper/git.ts');
10
- const { loadRegistry } = require('../../registry/index.ts');
11
- const { applyLifecycle, recordMcpOwnership } = require('../../lifecycle/index.ts');
5
+ const { toolDirs } = require('../../install/targets.js');
6
+ const { resolveContext, printContext } = require('../../install/context.js');
7
+ const { writeManifest } = require('../../install/manifest.js');
8
+ const { confirm } = require('../../helper/prompt.js');
9
+ const { sourceCommit } = require('../../helper/git.js');
10
+ const { loadRegistry } = require('../../registry/index.js');
11
+ const { applyLifecycle, recordMcpOwnership } = require('../../lifecycle/index.js');
12
12
  const {
13
13
  registryLifecycleView, assertSafeRegistryPlan,
14
- } = require('../../lifecycle/view.ts');
15
- const { recordedMcpSelections } = require('../../install/mcp.ts');
14
+ } = require('../../lifecycle/view.js');
15
+ const { recordedMcpSelections } = require('../../install/mcp.js');
16
16
  const {
17
17
  REPO_ROOT, SCRIPT_DIR, pkg, scopeOf, installPaths, scopeSelectionState, printRecordedMcpOwnership, buildAdapterRegistry,
18
18
  refuseHomeRootedProject, holdRunLock, checkpointRunLock,
19
- } = require('../shared.ts');
19
+ } = require('../shared.js');
20
20
 
21
21
  /** Classify desired-vs-observed drift for one lifecycle view. The plan IS the diff: its changes
22
22
  * are the operations needed to converge, its conflicts and prerequisites are the drift that must
23
23
  * not be silently healed. */
24
- function reconcileReport(view: any): any {
24
+ function reconcileReport(view ) {
25
25
  const drifts = [];
26
26
  const perHarness = new Map();
27
27
  for (const target of view.plan.targets) {
28
28
  if (target.skipped) continue;
29
- const entry: any = { create: 0, update: 0, remove: 0 };
29
+ const entry = { create: 0, update: 0, remove: 0 };
30
30
  for (const change of target.changes) {
31
31
  if (entry[change.operation] !== undefined) entry[change.operation] += 1;
32
32
  drifts.push({ harness: target.harness, operation: change.operation, assetId: change.assetId, target: change.target });
@@ -42,9 +42,9 @@ function reconcileReport(view: any): any {
42
42
  };
43
43
  }
44
44
 
45
- function printReconcileReport(report: any, lock: any): void {
45
+ function printReconcileReport(report , lock ) {
46
46
  console.log(`[INFO] Reconciling against doflow.lock (sourceVersion ${lock.sourceVersion ?? 'unknown'})`);
47
- for (const [harness, counts] of Object.entries<any>(report.perHarness)) {
47
+ for (const [harness, counts] of Object.entries (report.perHarness)) {
48
48
  const total = counts.create + counts.update + counts.remove;
49
49
  console.log(`[INFO] ${harness}: ${total === 0 ? 'clean' : `${total} drift(s) (${counts.create} create, ${counts.update} update, ${counts.remove} remove)`}`);
50
50
  }
@@ -53,7 +53,7 @@ function printReconcileReport(report: any, lock: any): void {
53
53
  if (report.clean) console.log('[OK] Observed state matches doflow.lock.');
54
54
  }
55
55
 
56
- function cmdReconcile(o: any): void {
56
+ function cmdReconcile(o ) {
57
57
  refuseHomeRootedProject(o, 'reconcile');
58
58
  const scope = scopeOf(o);
59
59
  const hold = holdRunLock(o, scope, 'reconcile');
@@ -63,10 +63,10 @@ function cmdReconcile(o: any): void {
63
63
  const { lock, ledger, manifestServers } = scopeSelectionState(scope);
64
64
  // A harness the ledger holds but the lock does not pin is installed and outside reconcile's reach.
65
65
  // Said, not converged: the lock records choices, and reconcile has no choice to record for it.
66
- const pinned = new Set((lock?.targets ?? []).map((entry: any) => entry.harness));
67
- const unpinned = [...new Set((ledger?.resources ?? []).map((resource: any) => resource.harness))].filter((harness) => !pinned.has(harness)).sort();
66
+ const pinned = new Set((lock?.targets ?? []).map((entry ) => entry.harness));
67
+ const unpinned = [...new Set((ledger?.resources ?? []).map((resource ) => resource.harness))].filter((harness) => !pinned.has(harness)).sort();
68
68
  for (const harness of unpinned) {
69
- const count = ledger.resources.filter((resource: any) => resource.harness === harness).length;
69
+ const count = ledger.resources.filter((resource ) => resource.harness === harness).length;
70
70
  console.log(`[WARN] ${harness}: installed (ledger holds ${count} resource(s)) but absent from doflow.lock; reconcile does not converge it.`);
71
71
  }
72
72
  if (!lock || !lock.targets.length) {
@@ -76,7 +76,7 @@ function cmdReconcile(o: any): void {
76
76
  console.log('[INFO] No doflow.lock in this scope — nothing pinned to reconcile against. Run `doflow install` first.');
77
77
  return;
78
78
  }
79
- const targets = lock.targets.map((entry: any) => entry.harness);
79
+ const targets = lock.targets.map((entry ) => entry.harness);
80
80
  const registry = loadRegistry({ repoRoot: REPO_ROOT });
81
81
  printContext(resolveContext({ repoRoot: REPO_ROOT, targets, dirs, sourceCommit: sourceCommit(SCRIPT_DIR), ...scope }));
82
82
  // Each harness converges onto its own pinned selection — reconcile never re-prompts and never
@@ -4,28 +4,28 @@
4
4
  // TypeScript migration (agent-docs/BRIEF_GOAL_DOFLOW.md): run directly by Node native type-stripping.
5
5
  const os = require('node:os');
6
6
  const path = require('node:path');
7
- const { resolveTargets, toolDirs } = require('../../install/targets.ts');
8
- const { confirm } = require('../../helper/prompt.ts');
9
- const { loadRegistry } = require('../../registry/index.ts');
10
- const { storageForgetScope } = require('../../runtime/storage/upkeep.ts');
11
- const { removeLifecycle, retentionSummary } = require('../../lifecycle/index.ts');
7
+ const { resolveTargets, toolDirs } = require('../../install/targets.js');
8
+ const { confirm } = require('../../helper/prompt.js');
9
+ const { loadRegistry } = require('../../registry/index.js');
10
+ const { storageForgetScope } = require('../../runtime/storage/upkeep.js');
11
+ const { removeLifecycle, retentionSummary } = require('../../lifecycle/index.js');
12
12
  const {
13
13
  codexScope, registryLifecycleView, printRegistryLifecycle, LIFECYCLE_HARNESSES,
14
14
  assertSafeRegistryPlan, lockDocument, recordLock,
15
- } = require('../../lifecycle/view.ts');
16
- const { recordedMcpSelections } = require('../../install/mcp.ts');
15
+ } = require('../../lifecycle/view.js');
16
+ const { recordedMcpSelections } = require('../../install/mcp.js');
17
17
  const {
18
18
  REPO_ROOT, scopeOf, scopeSelectionState, buildAdapterRegistry, refuseHomeRootedProject, holdRunLock, checkpointRunLock,
19
- } = require('../shared.ts');
19
+ } = require('../shared.js');
20
20
 
21
- function cmdRemove(o: any): void {
21
+ function cmdRemove(o ) {
22
22
  refuseHomeRootedProject(o, 'remove');
23
23
  const targets = resolveTargets(o.targets);
24
24
  const scope = scopeOf(o);
25
25
  const hold = holdRunLock(o, scope, 'remove');
26
26
  try {
27
27
  const dirs = toolDirs(scope);
28
- const lifecycleTargets = targets.filter((t: string) => LIFECYCLE_HARNESSES.includes(t));
28
+ const lifecycleTargets = targets.filter((t ) => LIFECYCLE_HARNESSES.includes(t));
29
29
  if (!lifecycleTargets.length) {
30
30
  console.log('[INFO] No lifecycle-owned native resources selected; legacy compatibility assets are never broadly removed.');
31
31
  return;