@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
@@ -23,10 +23,10 @@
23
23
  const fs = require('node:fs');
24
24
  const path = require('node:path');
25
25
 
26
- const { MARKER_START, MARKER_END } = require('../../helper/marker-merge.ts');
27
- const { planTree, applyTree, removeTree, verifyTree, copyTreeAssets, copyTreeDestDir, sharedTreeDestDir, ledgerFileResources, ledgerSiblingFingerprints, siblingReplacedNotices, fingerprint, sourceDirFor } = require('../copy-tree.ts');
28
- const { declaredHarnessPaths, resolveHarnessPaths } = require('../../helper/harness-paths.ts');
29
- const { mcpRows, discoverPiMcp, ownedPiMcpIds, planPiMcp, applyPiMcp, verifyPiMcp } = require('./mcp.ts');
26
+ const { MARKER_START, MARKER_END } = require('../../helper/marker-merge.js');
27
+ const { planTree, applyTree, removeTree, verifyTree, copyTreeAssets, copyTreeDestDir, sharedTreeDestDir, ledgerFileResources, ledgerSiblingFingerprints, siblingReplacedNotices, fingerprint, sourceDirFor } = require('../copy-tree.js');
28
+ const { declaredHarnessPaths, resolveHarnessPaths } = require('../../helper/harness-paths.js');
29
+ const { mcpRows, discoverPiMcp, ownedPiMcpIds, planPiMcp, applyPiMcp, verifyPiMcp } = require('./mcp.js');
30
30
 
31
31
  const HARNESS = 'pi';
32
32
  const AGENT_DIR_NOTICE = 'PI_CODING_AGENT_DIR is set: Pi reads its whole agent dir from it, but DoFlow moves only mcp.json there; skills and AGENTS.md stay in ~/.pi/agent.';
@@ -40,7 +40,7 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
40
40
  // Parity note: Pi's historical nativePaths() derived even its user-scope root from scopeRoot
41
41
  // (the CLI passes $HOME there for -g installs), never from a separate homeDir argument — so the
42
42
  // resolver is fed no homeDir and "root" keeps resolving exactly as before.
43
- function nativePaths({ scope, scopeRoot }: any = {}) {
43
+ function nativePaths({ scope, scopeRoot } = {}) {
44
44
  const paths = resolveHarnessPaths(declaredPaths, { scope, scopeRoot });
45
45
  // Pi's user-scope mcp.json follows $PI_CODING_AGENT_DIR when set. It is not declared in the
46
46
  // registry because the path schema has no environment base (src/helper/harness-paths.js); only
@@ -54,7 +54,7 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
54
54
  return typeof agentDir === 'string' && agentDir.trim() !== '' ? agentDir.trim() : null;
55
55
  }
56
56
 
57
- function discover({ scope, scopeRoot, mcp = [], ledger, context = {}, fsImpl = fs }: any) {
57
+ function discover({ scope, scopeRoot, mcp = [], ledger, context = {}, fsImpl = fs } ) {
58
58
  const paths = nativePaths({ scope, scopeRoot });
59
59
  const instruction = fsImpl.existsSync(paths.instruction) ? fsImpl.readFileSync(paths.instruction, 'utf8') : null;
60
60
  const rows = mcpRows(ledger);
@@ -62,18 +62,18 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
62
62
  // Pi reads mcp.json only for a selection or a row; the names in it are read here regardless.
63
63
  const file = snapshot[paths.mcp] ?? discoverPiMcp({ selected: [true], rows: [], file: paths.mcp, fsImpl })[paths.mcp];
64
64
  const members = file?.exists && file.doc?.ok ? file.doc.servers?.members ?? [] : null;
65
- const mcpConfigured = members && members.map((member: any) => member.key).sort();
65
+ const mcpConfigured = members && members.map((member ) => member.key).sort();
66
66
  return { paths, instruction, mcp: snapshot, mcpOwned: ownedPiMcpIds({ rows, snapshot }), mcpConfigured };
67
67
  }
68
68
 
69
- function render({ content = '' }: any = {}) {
69
+ function render({ content = '' } = {}) {
70
70
  return `${MARKER_START}\n${String(content).trimEnd()}\n${MARKER_END}\n`;
71
71
  }
72
72
 
73
73
  /** Replace only the span between DoFlow's markers. An AGENTS.md with no DoFlow section is refused
74
74
  * rather than appended to — Pi shares AGENTS.md with every other agent that reads it, so where
75
75
  * DoFlow's content belongs is its owner's decision. Add an empty marker pair to opt in. */
76
- function managedInstruction(existing: any, rendered: any) {
76
+ function managedInstruction(existing , rendered ) {
77
77
  if (existing === null) return { ok: true, operation: 'create', content: rendered };
78
78
  const start = existing.indexOf(MARKER_START);
79
79
  const end = existing.indexOf(MARKER_END);
@@ -83,7 +83,7 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
83
83
  return { ok: true, operation: content === existing ? 'none' : 'merge', content };
84
84
  }
85
85
 
86
- function strippedInstruction(existing: any) {
86
+ function strippedInstruction(existing ) {
87
87
  if (typeof existing !== 'string') return null;
88
88
  const start = existing.indexOf(MARKER_START);
89
89
  const end = existing.indexOf(MARKER_END);
@@ -95,7 +95,7 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
95
95
 
96
96
  // ---- copy-tree assets (skills) ----
97
97
 
98
- function planCopyTreeAssets({ assets, scope, scopeRoot, context, ledger, removing, fsImpl = fs }: any) {
98
+ function planCopyTreeAssets({ assets, scope, scopeRoot, context, ledger, removing, fsImpl = fs } ) {
99
99
  const paths = nativePaths({ scope, scopeRoot });
100
100
  const changes = [];
101
101
  const conflicts = [];
@@ -112,10 +112,10 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
112
112
  // is never deleted on removal, forced or not.
113
113
  force: !removing && context?.force === true, });
114
114
  treeResults.push(result);
115
- conflicts.push(...result.conflicts.map((reason: any) => `${asset.id}: ${reason}`));
115
+ conflicts.push(...result.conflicts.map((reason ) => `${asset.id}: ${reason}`));
116
116
  // A hand-edited file at a path DoFlow no longer writes is the user's: it stays, only its
117
117
  // ownership row is released.
118
- notices.push(...result.kept.map((item: any) => `kept hand-edited ${path.relative(paths.root, item.target)}; DoFlow no longer manages it`));
118
+ notices.push(...result.kept.map((item ) => `kept hand-edited ${path.relative(paths.root, item.target)}; DoFlow no longer manages it`));
119
119
  for (const change of result.changes) {
120
120
  changes.push({
121
121
  assetId: asset.id, target: change.target, source: change.source, operation: change.operation,
@@ -130,19 +130,19 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
130
130
  return { changes, conflicts, notices: [...siblingReplacedNotices(treeResults), ...notices] };
131
131
  }
132
132
 
133
- function applyCopyTreeAssets(changes: any, { fsImpl = fs }: any = {}) {
134
- const treeChanges = changes.filter((change: any) => change.projection?.renderer === 'copy-tree' && change.operation !== 'remove')
135
- .map((change: any) => ({ relPath: change.identity, target: change.target, source: change.source, operation: change.operation, fingerprint: change.fingerprint }));
133
+ function applyCopyTreeAssets(changes , { fsImpl = fs } = {}) {
134
+ const treeChanges = changes.filter((change ) => change.projection?.renderer === 'copy-tree' && change.operation !== 'remove')
135
+ .map((change ) => ({ relPath: change.identity, target: change.target, source: change.source, operation: change.operation, fingerprint: change.fingerprint }));
136
136
  return applyTree({ changes: treeChanges, fsImpl }).applied;
137
137
  }
138
138
 
139
- function removeCopyTreeAssets(changes: any, { fsImpl = fs }: any = {}) {
140
- const treeChanges = changes.filter((change: any) => change.kind === 'copy-tree-file' && change.operation === 'remove' && !change.retained)
141
- .map((change: any) => ({ relPath: change.identity, target: change.target, operation: 'remove', fingerprint: change.fingerprint, pruneGuard: change.pruneGuard }));
139
+ function removeCopyTreeAssets(changes , { fsImpl = fs } = {}) {
140
+ const treeChanges = changes.filter((change ) => change.kind === 'copy-tree-file' && change.operation === 'remove' && !change.retained)
141
+ .map((change ) => ({ relPath: change.identity, target: change.target, operation: 'remove', fingerprint: change.fingerprint, pruneGuard: change.pruneGuard }));
142
142
  return removeTree({ changes: treeChanges, fsImpl }).removed;
143
143
  }
144
144
 
145
- function verifyCopyTreeAssets({ assets, scope, scopeRoot, context, fsImpl = fs }: any) {
145
+ function verifyCopyTreeAssets({ assets, scope, scopeRoot, context, fsImpl = fs } ) {
146
146
  const paths = nativePaths({ scope, scopeRoot });
147
147
  const statuses = [];
148
148
  const resources = [];
@@ -151,7 +151,7 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
151
151
  const destDir = sharedTreeDestDir(paths.root, asset.nativeDir) ?? copyTreeDestDir(paths.configDir, asset);
152
152
  const sourceDir = sourceDirFor(asset, context, fsImpl, 'Pi');
153
153
  const result = verifyTree({ sourceDir, destDir, fsImpl, layout: asset.layout, plannedWrites: context?.plannedWrites });
154
- conflicts.push(...result.conflicts.map((reason: any) => `${asset.id}: ${reason}`));
154
+ conflicts.push(...result.conflicts.map((reason ) => `${asset.id}: ${reason}`));
155
155
  for (const resource of result.resources) {
156
156
  resources.push({
157
157
  assetId: asset.id, target: resource.target, ownershipIdentity: `doflow:pi:copy-tree:${asset.id}:${resource.relPath}`,
@@ -167,13 +167,13 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
167
167
 
168
168
  // ---- shared adapter contract ----
169
169
 
170
- function plan({ scope, scopeRoot, assets = [], mcp = [], discovery, context = {}, ledger, fsImpl = fs }: any) {
170
+ function plan({ scope, scopeRoot, assets = [], mcp = [], discovery, context = {}, ledger, fsImpl = fs } ) {
171
171
  const found = discovery || discover({ scope, scopeRoot, mcp, ledger, context, fsImpl });
172
172
  const changes = [];
173
173
  const conflicts = [];
174
174
  const removing = context.operation === 'remove';
175
175
 
176
- const guidance = assets.find((asset: any) => asset.capability === 'instructions');
176
+ const guidance = assets.find((asset ) => asset.capability === 'instructions');
177
177
  if (guidance) {
178
178
  const rendered = render({ content: fsImpl.readFileSync(path.resolve(context.repoRoot, guidance.source), 'utf8') });
179
179
  const outcome = removing
@@ -200,14 +200,14 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
200
200
  return { changes, conflicts, notices, paths: found.paths };
201
201
  }
202
202
 
203
- function writeChange(change: any, fsImpl: any) {
203
+ function writeChange(change , fsImpl ) {
204
204
  fsImpl.mkdirSync(path.dirname(change.target), { recursive: true });
205
205
  fsImpl.writeFileSync(change.target, change.content, 'utf8');
206
206
  }
207
207
 
208
- function isPiMcp(change: any) { return change.projection?.renderer === 'pi-mcp'; }
208
+ function isPiMcp(change ) { return change.projection?.renderer === 'pi-mcp'; }
209
209
 
210
- function apply({ changes = [], fsImpl = fs }: any) {
210
+ function apply({ changes = [], fsImpl = fs } ) {
211
211
  // MCP first: its base-hash check refuses a stale plan before any other Pi file is written.
212
212
  let applied = applyPiMcp(changes.filter(isPiMcp), { fsImpl }).applied;
213
213
  for (const change of changes) {
@@ -222,7 +222,7 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
222
222
  return { applied };
223
223
  }
224
224
 
225
- function remove({ changes = [], fsImpl = fs }: any) {
225
+ function remove({ changes = [], fsImpl = fs } ) {
226
226
  let removed = applyPiMcp(changes.filter(isPiMcp), { fsImpl }).applied;
227
227
  for (const change of changes) {
228
228
  if (change.operation !== 'remove' || change.projection?.renderer === 'copy-tree' || isPiMcp(change)) continue;
@@ -234,12 +234,12 @@ function createPiAdapter({ declaredPaths = declaredHarnessPaths()[HARNESS], env
234
234
  return { removed };
235
235
  }
236
236
 
237
- function verify({ scope, scopeRoot, assets = [], mcp = [], discovery, ledger, context = {}, fsImpl = fs }: any) {
237
+ function verify({ scope, scopeRoot, assets = [], mcp = [], discovery, ledger, context = {}, fsImpl = fs } ) {
238
238
  const found = discover({ scope, scopeRoot, mcp, ledger, context, fsImpl });
239
239
  const statuses = [];
240
240
  const resources = [];
241
241
  const conflicts = [];
242
- const instructionsAssetId = assets.find((asset: any) => asset.capability === 'instructions')?.id ?? assets[0]?.id;
242
+ const instructionsAssetId = assets.find((asset ) => asset.capability === 'instructions')?.id ?? assets[0]?.id;
243
243
 
244
244
  const hasSection = typeof found.instruction === 'string'
245
245
  && found.instruction.includes(MARKER_START) && found.instruction.includes(MARKER_END);
@@ -274,6 +274,6 @@ const singleton = createPiAdapter();
274
274
  module.exports = {
275
275
  HARNESS, nativePaths: singleton.nativePaths, discover: singleton.discover, render: singleton.render,
276
276
  plan: singleton.plan, apply: singleton.apply, remove: singleton.remove, verify: singleton.verify,
277
- managedInstruction: (singleton as any).managedInstruction, strippedInstruction: (singleton as any).strippedInstruction,
277
+ managedInstruction: (singleton ).managedInstruction, strippedInstruction: (singleton ).strippedInstruction,
278
278
  createPiAdapter,
279
279
  };
@@ -10,17 +10,17 @@
10
10
  const SKELETON = '{\n "mcpServers": {}\n}\n';
11
11
  const WHITESPACE = ' \t\n\r';
12
12
 
13
- function isPlainObject(value: any): boolean {
13
+ function isPlainObject(value ) {
14
14
  return value !== null && typeof value === 'object' && !Array.isArray(value);
15
15
  }
16
16
 
17
- function skipWhitespace(text: string, i: number): number {
17
+ function skipWhitespace(text , i ) {
18
18
  while (i < text.length && WHITESPACE.includes(text[i])) i += 1;
19
19
  return i;
20
20
  }
21
21
 
22
22
  /** Index just past the string token that opens at `i`. */
23
- function stringEnd(text: string, i: number): number {
23
+ function stringEnd(text , i ) {
24
24
  for (i += 1; text[i] !== '"'; i += 1) if (text[i] === '\\') i += 1;
25
25
  return i + 1;
26
26
  }
@@ -28,7 +28,7 @@ function stringEnd(text: string, i: number): number {
28
28
  // The text has already passed JSON.parse, so the scanner only has to find spans, never validate.
29
29
  // Only the top-level object and mcpServers need member spans; every other value is skipped by
30
30
  // counting brackets, without recursion, so a deeply nested file cannot exhaust the stack.
31
- function valueEnd(text: string, i: number): number {
31
+ function valueEnd(text , i ) {
32
32
  const ch = text[i];
33
33
  if (ch === '"') return stringEnd(text, i);
34
34
  if (ch !== '{' && ch !== '[') {
@@ -47,8 +47,8 @@ function valueEnd(text: string, i: number): number {
47
47
 
48
48
  /** Member spans of the object opening at `open`; `nested` names the one member whose object value
49
49
  * is scanned for its own members too. */
50
- function scanObject(text: string, open: number, nested: string | null = null): { open: number, close: number, members: any[], [extra: string]: any } {
51
- const members: any[] = [];
50
+ function scanObject(text , open , nested = null) {
51
+ const members = [];
52
52
  let i = skipWhitespace(text, open + 1);
53
53
  while (text[i] !== '}') {
54
54
  const keyStart = i;
@@ -66,7 +66,7 @@ function scanObject(text: string, open: number, nested: string | null = null): {
66
66
 
67
67
  /** JSON.parse's message quotes the text around the error, which may be a token or a password, so
68
68
  * only the position is reported. */
69
- function invalidJsonReason(text: string, error: any): string {
69
+ function invalidJsonReason(text , error ) {
70
70
  const match = /at position (\d+)/.exec(error.message);
71
71
  if (!match) return 'invalid JSON';
72
72
  const before = text.slice(0, Number(match[1]));
@@ -75,14 +75,14 @@ function invalidJsonReason(text: string, error: any): string {
75
75
  }
76
76
 
77
77
  /** The whitespace that starts the line `at` sits on, or null when something else precedes it there. */
78
- function lineIndent(text: string, at: number): string | null {
78
+ function lineIndent(text , at ) {
79
79
  const prefix = text.slice(text.lastIndexOf('\n', at - 1) + 1, at);
80
80
  return /^[ \t]*$/.test(prefix) ? prefix : null;
81
81
  }
82
82
 
83
83
  /** The line ending most of the lines in `[start, end)` use, or `fallback` when the span has none:
84
84
  * one stray CRLF in an LF file does not turn every inserted line into CRLF. */
85
- function lineEnding(text: string, start: number, end: number, fallback: string): string {
85
+ function lineEnding(text , start , end , fallback ) {
86
86
  const span = text.slice(start, end);
87
87
  const lines = span.split('\n').length - 1;
88
88
  if (!lines) return fallback;
@@ -91,7 +91,7 @@ function lineEnding(text: string, start: number, end: number, fallback: string):
91
91
 
92
92
  /** Attach the formatting a container's new members follow: whether it spans lines, its line ending,
93
93
  * the indent of its members and the indent of its closing brace. An empty container takes its parent's. */
94
- function attachLayout(text: string, node: any, parent: any, unit: string, eol: string): void {
94
+ function attachLayout(text , node , parent , unit , eol ) {
95
95
  const parentIndent = parent ? parent.indent : '';
96
96
  const empty = node.members.length === 0;
97
97
  node.multiline = text.slice(node.open, node.close).includes('\n') || (empty && Boolean(parent?.multiline));
@@ -100,8 +100,8 @@ function attachLayout(text: string, node: any, parent: any, unit: string, eol: s
100
100
  node.closeIndent = parentIndent;
101
101
  }
102
102
 
103
- function duplicateKey(node: any): string | null {
104
- const seen = new Set<string>();
103
+ function duplicateKey(node ) {
104
+ const seen = new Set ();
105
105
  for (const member of node.members) {
106
106
  if (seen.has(member.key)) return member.key;
107
107
  seen.add(member.key);
@@ -109,9 +109,9 @@ function duplicateKey(node: any): string | null {
109
109
  return null;
110
110
  }
111
111
 
112
- function readDocument(text: string): any {
112
+ function readDocument(text ) {
113
113
  let parsed;
114
- try { parsed = JSON.parse(text); } catch (error: any) { return { ok: false, reason: invalidJsonReason(text, error) }; }
114
+ try { parsed = JSON.parse(text); } catch (error ) { return { ok: false, reason: invalidJsonReason(text, error) }; }
115
115
  if (!isPlainObject(parsed)) return { ok: false, reason: 'top level is not an object' };
116
116
  if (Object.prototype.hasOwnProperty.call(parsed, 'mcpServers') && !isPlainObject(parsed.mcpServers)) {
117
117
  return { ok: false, reason: 'mcpServers is not an object' };
@@ -120,7 +120,7 @@ function readDocument(text: string): any {
120
120
  try { root = scanObject(text, skipWhitespace(text, 0), 'mcpServers'); } catch { return { ok: false, reason: 'the file could not be scanned' }; }
121
121
  const duplicateTop = duplicateKey(root);
122
122
  if (duplicateTop !== null) return { ok: false, reason: `duplicate key '${duplicateTop}'` };
123
- const servers = root.members.find((member: any) => member.key === 'mcpServers')?.node ?? null;
123
+ const servers = root.members.find((member ) => member.key === 'mcpServers')?.node ?? null;
124
124
  const duplicateServer = servers ? duplicateKey(servers) : null;
125
125
  if (duplicateServer !== null) return { ok: false, reason: `duplicate key '${duplicateServer}'` };
126
126
 
@@ -132,21 +132,21 @@ function readDocument(text: string): any {
132
132
  return { ok: true, root, servers, eol, unit };
133
133
  }
134
134
 
135
- function renderValue(value: any, container: any, layout: any): string {
135
+ function renderValue(value , container , layout ) {
136
136
  if (!container.multiline) return JSON.stringify(value);
137
137
  return JSON.stringify(value, null, layout.unit).split('\n').join(container.eol + container.indent);
138
138
  }
139
139
 
140
- function renderMember(key: string, value: any, container: any, layout: any): string {
140
+ function renderMember(key , value , container , layout ) {
141
141
  return `${JSON.stringify(key)}: ${renderValue(value, container, layout)}`;
142
142
  }
143
143
 
144
- function splice(text: string, start: number, end: number, inserted: string): string {
144
+ function splice(text , start , end , inserted ) {
145
145
  return text.slice(0, start) + inserted + text.slice(end);
146
146
  }
147
147
 
148
148
  /** `layout` is the readDocument result the container or member came from. */
149
- function insertMember(text: string, container: any, key: string, value: any, layout: any): string {
149
+ function insertMember(text , container , key , value , layout ) {
150
150
  const member = renderMember(key, value, container, layout);
151
151
  const last = container.members[container.members.length - 1];
152
152
  if (last) {
@@ -159,12 +159,12 @@ function insertMember(text: string, container: any, key: string, value: any, lay
159
159
  return splice(text, container.open + 1, container.close, inserted);
160
160
  }
161
161
 
162
- function replaceValue(text: string, member: any, value: any, layout: any): string {
162
+ function replaceValue(text , member , value , layout ) {
163
163
  const container = layout.servers?.members.includes(member) ? layout.servers : layout.root;
164
164
  return splice(text, member.valueStart, member.valueEnd, renderValue(value, container, layout));
165
165
  }
166
166
 
167
- function removeMember(text: string, container: any, member: any): string {
167
+ function removeMember(text , container , member ) {
168
168
  const index = container.members.indexOf(member);
169
169
  if (index === -1) throw new Error(`member '${member.key}' is not in this container`);
170
170
  if (container.members.length === 1) return splice(text, container.open + 1, container.close, '');
@@ -173,12 +173,12 @@ function removeMember(text: string, container: any, member: any): string {
173
173
  }
174
174
 
175
175
  /** Set the text between an empty container's braces, which a removal of its only member drops. */
176
- function replaceInner(text: string, container: any, inner: string): string {
176
+ function replaceInner(text , container , inner ) {
177
177
  if (container.members.length) throw new Error('only an empty container\'s inner text can be replaced');
178
178
  return splice(text, container.open + 1, container.close, inner);
179
179
  }
180
180
 
181
- function renderNewDocument(entries: any): string {
181
+ function renderNewDocument(entries ) {
182
182
  return `${JSON.stringify({ mcpServers: Object.fromEntries(entries) }, null, 2)}\n`;
183
183
  }
184
184