@automaton-labs/aib 0.0.7 → 0.0.8

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 (477) hide show
  1. package/README.md +36 -257
  2. package/config/agent-dx-policy.default.json +31 -0
  3. package/config/control-plane-client.default.json +3 -0
  4. package/dist/agent-dx/agent-dx.js +805 -0
  5. package/dist/agent-dx/presentation.js +32 -0
  6. package/dist/alias-advisor/analyze.js +982 -0
  7. package/dist/alias-advisor/exact-text-cost.js +74 -0
  8. package/dist/alias-advisor/lexical.js +240 -0
  9. package/dist/alias-advisor/model.js +2 -0
  10. package/dist/alias-advisor/path-identity.js +49 -0
  11. package/dist/alias-advisor/ranking.js +171 -0
  12. package/dist/alias-advisor/token-estimator.js +85 -0
  13. package/dist/bin/aib.js +5 -1
  14. package/dist/bin/cli.js +811 -4
  15. package/dist/commands/add-missing-imports-preview-cache.js +99 -2
  16. package/dist/commands/add-missing-imports.js +241 -2
  17. package/dist/commands/apply-module-plan.js +1319 -3
  18. package/dist/commands/background-command.js +378 -2
  19. package/dist/commands/captured-input.js +74 -1
  20. package/dist/commands/config-command.js +314 -2
  21. package/dist/commands/config-output.js +357 -10
  22. package/dist/commands/control-plane-command.js +183 -1
  23. package/dist/commands/declaration-command.js +1209 -7
  24. package/dist/commands/declaration-execution-cache.js +79 -1
  25. package/dist/commands/declaration-format.js +221 -1
  26. package/dist/commands/declaration-preview-cache.js +114 -2
  27. package/dist/commands/diagnostics-command.js +70 -3
  28. package/dist/commands/doctor.js +137 -3
  29. package/dist/commands/execution-command.js +117 -1
  30. package/dist/commands/exports-star-collapse-command.js +178 -0
  31. package/dist/commands/exports-star-command.js +252 -0
  32. package/dist/commands/exports-star-preview-cache.js +84 -0
  33. package/dist/commands/feedback-command.js +176 -3
  34. package/dist/commands/file-move-to-dir-execution-cache.js +92 -1
  35. package/dist/commands/file-move-to-dir-preview-cache.js +125 -2
  36. package/dist/commands/file-move-to-dir-worker.js +54 -0
  37. package/dist/commands/file-move-to-dir.js +1073 -5
  38. package/dist/commands/file-mutation-runtime.js +102 -1
  39. package/dist/commands/file-mutation-worker-apply.js +180 -0
  40. package/dist/commands/file-refactor-batch-execution-cache.js +90 -1
  41. package/dist/commands/file-refactor-batch-preview-cache.js +125 -2
  42. package/dist/commands/file-refactor-batch-worker.js +54 -0
  43. package/dist/commands/file-refactor-batch.js +1154 -5
  44. package/dist/commands/file-rename-execution-cache.js +92 -1
  45. package/dist/commands/file-rename-preview-cache.js +125 -2
  46. package/dist/commands/file-rename-worker.js +54 -0
  47. package/dist/commands/file-rename.js +1053 -5
  48. package/dist/commands/file-text-edit-executor.js +205 -0
  49. package/dist/commands/find-importers.js +52 -1
  50. package/dist/commands/find-unused-imports.js +55 -1
  51. package/dist/commands/generate-docs-command.js +244 -6
  52. package/dist/commands/help-command.js +460 -7
  53. package/dist/commands/import-specifier-policy.js +391 -0
  54. package/dist/commands/imports-command.js +68 -1
  55. package/dist/commands/imports-rebase.js +1138 -0
  56. package/dist/commands/init-skill-usage.js +92 -3
  57. package/dist/commands/init-workspace.js +30 -1
  58. package/dist/commands/inspect-alias-candidates.js +413 -0
  59. package/dist/commands/inspect-cycles.js +811 -5
  60. package/dist/commands/inspect-direct-usages.js +98 -0
  61. package/dist/commands/inspect-duplicates-format.js +229 -0
  62. package/dist/commands/inspect-format-primitives.js +127 -0
  63. package/dist/commands/inspect-format.js +1590 -18
  64. package/dist/commands/inspect-graph.js +1553 -9
  65. package/dist/commands/inspect-imports.js +339 -2
  66. package/dist/commands/inspect-mixed-format.js +524 -0
  67. package/dist/commands/inspect-module-plan-format.js +216 -0
  68. package/dist/commands/inspect-module-plan-serialization.js +402 -0
  69. package/dist/commands/inspect-reference-path-format.js +157 -0
  70. package/dist/commands/inspect-request-values.js +599 -0
  71. package/dist/commands/inspect-selector-kind.js +21 -0
  72. package/dist/commands/inspect-selector.js +50 -0
  73. package/dist/commands/inspect-symbol-format.js +90 -0
  74. package/dist/commands/inspect-topology.js +435 -0
  75. package/dist/commands/inspect-tree.js +827 -5
  76. package/dist/commands/inspect-usages-detail.js +793 -0
  77. package/dist/commands/inspect-usages-evidence.js +31 -0
  78. package/dist/commands/inspect-usages-format.js +367 -0
  79. package/dist/commands/inspect.js +1450 -16
  80. package/dist/commands/internal-command.js +64 -0
  81. package/dist/commands/json-file-input.js +60 -1
  82. package/dist/commands/module-plan-cache.js +156 -2
  83. package/dist/commands/module-plan-standalone.js +208 -0
  84. package/dist/commands/module-plan-timeout.js +77 -1
  85. package/dist/commands/move-preview-cache.js +101 -2
  86. package/dist/commands/mutate-aggregate-output.js +996 -0
  87. package/dist/commands/mutate-child-execution.js +374 -0
  88. package/dist/commands/mutate-command.js +1394 -0
  89. package/dist/commands/mutate-declaration-output.js +313 -0
  90. package/dist/commands/mutate-domain-adapters.js +638 -0
  91. package/dist/commands/mutate-execution-cache.js +114 -0
  92. package/dist/commands/mutate-execution-status.js +598 -0
  93. package/dist/commands/mutate-failure-output.js +531 -0
  94. package/dist/commands/mutate-file-view.js +151 -0
  95. package/dist/commands/mutate-object-output.js +91 -0
  96. package/dist/commands/mutate-output-values.js +97 -0
  97. package/dist/commands/mutate-preview-cache.js +86 -0
  98. package/dist/commands/mutate-response-replay.js +153 -0
  99. package/dist/commands/mutate-result-projection.js +818 -0
  100. package/dist/commands/mutation-eta.js +28 -0
  101. package/dist/commands/mutation-execution-cache.js +140 -3
  102. package/dist/commands/mutation-recovery-journal.js +195 -0
  103. package/dist/commands/normalize-imports.js +1120 -4
  104. package/dist/commands/object-pack-command.js +546 -0
  105. package/dist/commands/object-pack-preview-cache.js +88 -0
  106. package/dist/commands/observability-command.js +47 -3
  107. package/dist/commands/ota-command.js +403 -2
  108. package/dist/commands/print-config.js +10 -1
  109. package/dist/commands/quick-read.js +1113 -11
  110. package/dist/commands/refactor-batch-builder.js +265 -1
  111. package/dist/commands/refactor-batch-execution-cache.js +85 -1
  112. package/dist/commands/refactor-batch-preview-cache.js +96 -2
  113. package/dist/commands/refactor-batch.js +461 -4
  114. package/dist/commands/rename-entities.js +794 -4
  115. package/dist/commands/rename-execution-cache.js +49 -1
  116. package/dist/commands/rename-input.js +22 -1
  117. package/dist/commands/rename-polling-policy.js +68 -0
  118. package/dist/commands/rename-preview-cache.js +96 -2
  119. package/dist/commands/result-view.js +993 -7
  120. package/dist/commands/reveal-command.js +445 -5
  121. package/dist/commands/selector-suggestions.js +93 -0
  122. package/dist/commands/session-workspace.js +1836 -31
  123. package/dist/commands/shared.js +2 -1
  124. package/dist/commands/skills-command.js +315 -0
  125. package/dist/commands/sync-command.js +59 -2
  126. package/dist/commands/worker-command.js +173 -1
  127. package/dist/commands/workspace-cache.js +55 -1
  128. package/dist/config/defaults.js +26 -1
  129. package/dist/config/env-vars.js +77 -1
  130. package/dist/config/glob-match.js +44 -1
  131. package/dist/config/import-rules.js +165 -1
  132. package/dist/config/local-config.js +293 -3
  133. package/dist/config/mutation-comments.js +51 -1
  134. package/dist/config/path-aliases.js +165 -1
  135. package/dist/config/path-display.js +84 -1
  136. package/dist/config/product-storage.js +37 -1
  137. package/dist/config/request-env.js +21 -0
  138. package/dist/config/request-routing-context.js +23 -0
  139. package/dist/config/resolve-command-alias.js +74 -1
  140. package/dist/config/resolve.js +24 -1
  141. package/dist/config/tsconfig-discovery.js +113 -1
  142. package/dist/config/typescript-preferences.js +131 -0
  143. package/dist/config/workspace-root.js +310 -3
  144. package/dist/config/workspace-state.js +254 -1
  145. package/dist/content/content-bundle.js +88 -1
  146. package/dist/diagnostics/module-plan-timeline.js +75 -2
  147. package/dist/diagnostics/readiness-text.js +45 -8
  148. package/dist/dsl/aib-dsl.js +838 -1
  149. package/dist/dsl/declaration-dsl.js +264 -1
  150. package/dist/dsl/file-move-to-dir-dsl.js +123 -1
  151. package/dist/dsl/file-refactor-batch-dsl.js +203 -1
  152. package/dist/dsl/file-rename-dsl.js +135 -1
  153. package/dist/dsl/mutate-dsl.js +746 -0
  154. package/dist/help/bootstrap.bash.md +176 -341
  155. package/dist/help/bootstrap.md +175 -340
  156. package/dist/help/bootstrap.pwsh.md +176 -341
  157. package/dist/help/docs/basics.md +1 -1
  158. package/dist/help/docs/config-setup.import-normalize.md +65 -65
  159. package/dist/help/docs/config-setup.import-rules.md +6 -5
  160. package/dist/help/docs/first-setup.md +6 -5
  161. package/dist/help/docs/help-protocol.md +4 -3
  162. package/dist/help/docs/import.base.md +38 -0
  163. package/dist/help/docs/import.rebase.md +85 -0
  164. package/dist/help/docs/inspect.aliasCandidates.md +39 -0
  165. package/dist/help/docs/inspect.code.md +1 -7
  166. package/dist/help/docs/inspect.file.md +10 -19
  167. package/dist/help/docs/inspect.graph.md +3 -17
  168. package/dist/help/{dsl/docs/inspect.md → docs/inspect.shared.md} +13 -12
  169. package/dist/help/docs/modulePlan.md +24 -28
  170. package/dist/help/docs/move.md +19 -22
  171. package/dist/help/{dsl/topics/file.move.md → docs/moveToDir.md} +36 -34
  172. package/dist/help/docs/mutate.mixed.md +34 -0
  173. package/dist/help/docs/mutation.shared.md +55 -0
  174. package/dist/help/docs/patterns.md +3 -12
  175. package/dist/help/docs/qr.md +12 -6
  176. package/dist/help/docs/quick-map.md +36 -24
  177. package/dist/help/docs/recipe.file-layout.md +10 -10
  178. package/dist/help/docs/recipe.import-boundary.md +92 -0
  179. package/dist/help/docs/recipe.safe-artifact-probing.md +68 -0
  180. package/dist/help/docs/recipe.unfamiliar-area.md +64 -0
  181. package/dist/help/docs/recipes.md +20 -0
  182. package/dist/help/docs/rename.md +19 -27
  183. package/dist/help/docs/renameFile.md +36 -0
  184. package/dist/help/docs/rules.md +26 -0
  185. package/dist/help/dsl/bootstrap.bash.md +176 -341
  186. package/dist/help/dsl/bootstrap.md +175 -340
  187. package/dist/help/dsl/bootstrap.pwsh.md +176 -341
  188. package/dist/help/dsl/docs/basics.md +1 -1
  189. package/dist/help/dsl/docs/config-setup.import-normalize.md +65 -65
  190. package/dist/help/dsl/docs/config-setup.import-rules.md +6 -5
  191. package/dist/help/dsl/docs/first-setup.md +6 -5
  192. package/dist/help/dsl/docs/help-protocol.md +4 -3
  193. package/dist/help/dsl/docs/import.base.md +38 -0
  194. package/dist/help/dsl/docs/import.rebase.md +85 -0
  195. package/dist/help/dsl/docs/inspect.aliasCandidates.md +39 -0
  196. package/dist/help/dsl/docs/inspect.code.md +1 -7
  197. package/dist/help/dsl/docs/inspect.file.md +10 -19
  198. package/dist/help/dsl/docs/inspect.graph.md +3 -17
  199. package/dist/help/{docs/inspect.md → dsl/docs/inspect.shared.md} +13 -12
  200. package/dist/help/dsl/docs/modulePlan.md +24 -28
  201. package/dist/help/dsl/docs/move.md +19 -22
  202. package/dist/help/{topics/file.move.md → dsl/docs/moveToDir.md} +36 -34
  203. package/dist/help/dsl/docs/mutate.mixed.md +34 -0
  204. package/dist/help/dsl/docs/mutation.shared.md +55 -0
  205. package/dist/help/dsl/docs/patterns.md +3 -12
  206. package/dist/help/dsl/docs/qr.md +12 -6
  207. package/dist/help/dsl/docs/quick-map.md +36 -24
  208. package/dist/help/dsl/docs/recipe.file-layout.md +10 -10
  209. package/dist/help/dsl/docs/recipe.import-boundary.md +92 -0
  210. package/dist/help/dsl/docs/recipe.safe-artifact-probing.md +68 -0
  211. package/dist/help/dsl/docs/recipe.unfamiliar-area.md +64 -0
  212. package/dist/help/dsl/docs/recipes.md +20 -0
  213. package/dist/help/dsl/docs/rename.md +19 -27
  214. package/dist/help/dsl/docs/renameFile.md +36 -0
  215. package/dist/help/dsl/docs/rules.md +26 -0
  216. package/dist/help/dsl/full.md +175 -340
  217. package/dist/help/dsl/help-index.md +48 -43
  218. package/dist/help/dsl/snippets/agents.md +2 -2
  219. package/dist/help/dsl/tokens/qr.inline.examples.md +1 -1
  220. package/dist/help/dsl/topics/basics.md +1 -1
  221. package/dist/help/dsl/topics/config-setup.import-normalize.md +65 -65
  222. package/dist/help/dsl/topics/config-setup.import-rules.md +6 -5
  223. package/dist/help/dsl/topics/first-setup.md +6 -5
  224. package/dist/help/dsl/topics/help-protocol.md +4 -3
  225. package/dist/help/dsl/topics/import.base.md +36 -0
  226. package/dist/help/dsl/topics/import.rebase.md +83 -0
  227. package/dist/help/dsl/topics/inspect.aliasCandidates.md +37 -0
  228. package/dist/help/dsl/topics/inspect.code.md +1 -7
  229. package/dist/help/dsl/topics/inspect.file.md +10 -19
  230. package/dist/help/dsl/topics/inspect.graph.md +3 -17
  231. package/dist/help/dsl/topics/{inspect.md → inspect.shared.md} +13 -12
  232. package/dist/help/dsl/topics/modulePlan.md +21 -26
  233. package/dist/help/dsl/topics/move.md +17 -18
  234. package/dist/help/{docs/file.move.md → dsl/topics/moveToDir.md} +33 -35
  235. package/dist/help/dsl/topics/mutate.mixed.md +32 -0
  236. package/dist/help/dsl/topics/mutation.shared.md +53 -0
  237. package/dist/help/dsl/topics/patterns.md +3 -12
  238. package/dist/help/dsl/topics/qr.md +12 -6
  239. package/dist/help/dsl/topics/quick-map.md +36 -24
  240. package/dist/help/dsl/topics/recipe.file-layout.md +10 -10
  241. package/dist/help/dsl/topics/recipe.import-boundary.md +90 -0
  242. package/dist/help/dsl/topics/recipe.safe-artifact-probing.md +66 -0
  243. package/dist/help/dsl/topics/recipe.unfamiliar-area.md +62 -0
  244. package/dist/help/dsl/topics/recipes.md +18 -0
  245. package/dist/help/dsl/topics/rename.md +15 -15
  246. package/dist/help/dsl/topics/renameFile.md +34 -0
  247. package/dist/help/dsl/topics/rules.md +24 -0
  248. package/dist/help/full.md +175 -340
  249. package/dist/help/help-index.md +48 -43
  250. package/dist/help/help-meta.json +98 -48
  251. package/dist/help/index.md +52 -20
  252. package/dist/help/snippets/agents.md +2 -2
  253. package/dist/help/tokens/qr.inline.examples.md +1 -1
  254. package/dist/help/topics/basics.md +1 -1
  255. package/dist/help/topics/config-setup.import-normalize.md +65 -65
  256. package/dist/help/topics/config-setup.import-rules.md +6 -5
  257. package/dist/help/topics/first-setup.md +6 -5
  258. package/dist/help/topics/help-protocol.md +4 -3
  259. package/dist/help/topics/import.base.md +36 -0
  260. package/dist/help/topics/import.rebase.md +83 -0
  261. package/dist/help/topics/inspect.aliasCandidates.md +37 -0
  262. package/dist/help/topics/inspect.code.md +1 -7
  263. package/dist/help/topics/inspect.file.md +10 -19
  264. package/dist/help/topics/inspect.graph.md +3 -17
  265. package/dist/help/topics/{inspect.md → inspect.shared.md} +13 -12
  266. package/dist/help/topics/modulePlan.md +21 -26
  267. package/dist/help/topics/move.md +17 -18
  268. package/dist/help/{dsl/docs/file.move.md → topics/moveToDir.md} +33 -35
  269. package/dist/help/topics/mutate.mixed.md +32 -0
  270. package/dist/help/topics/mutation.shared.md +53 -0
  271. package/dist/help/topics/patterns.md +3 -12
  272. package/dist/help/topics/qr.md +12 -6
  273. package/dist/help/topics/quick-map.md +36 -24
  274. package/dist/help/topics/recipe.file-layout.md +10 -10
  275. package/dist/help/topics/recipe.import-boundary.md +90 -0
  276. package/dist/help/topics/recipe.safe-artifact-probing.md +66 -0
  277. package/dist/help/topics/recipe.unfamiliar-area.md +62 -0
  278. package/dist/help/topics/recipes.md +18 -0
  279. package/dist/help/topics/rename.md +15 -15
  280. package/dist/help/topics/renameFile.md +34 -0
  281. package/dist/help/topics/rules.md +24 -0
  282. package/dist/host/capabilities.js +56 -1
  283. package/dist/imports/standalone-import-analysis.js +602 -0
  284. package/dist/imports/standalone-import-model.js +2 -0
  285. package/dist/imports/standalone-import-process.js +66 -0
  286. package/dist/imports/standalone-import-worker.js +27 -0
  287. package/dist/imports/standalone-ts-project.js +147 -0
  288. package/dist/inspect/inspect-duplicates-service.js +526 -0
  289. package/dist/inspect/inspect-reverse-module-closure.js +338 -0
  290. package/dist/inspect/inspect-source-ranges.js +82 -0
  291. package/dist/inspect/inspect-source-shape.js +649 -0
  292. package/dist/inspect/standalone-inspect-analysis.js +319 -0
  293. package/dist/inspect/standalone-inspect-model.js +9 -0
  294. package/dist/inspect/standalone-inspect-process.js +55 -0
  295. package/dist/inspect/standalone-inspect-usages.js +274 -0
  296. package/dist/inspect/standalone-inspect-worker.js +13 -0
  297. package/dist/metrics/central-metrics.js +101 -2
  298. package/dist/mutation/concrete-edit-plan.js +157 -0
  299. package/dist/mutation/exports-star-collapse-preview.js +361 -0
  300. package/dist/mutation/exports-star-expand-apply.js +373 -0
  301. package/dist/mutation/exports-star-expand-preview.js +807 -0
  302. package/dist/mutation/file-impact-scan.js +182 -0
  303. package/dist/mutation/file-mutation-discovery.js +674 -0
  304. package/dist/mutation/file-mutation-eta.js +99 -0
  305. package/dist/mutation/file-mutation-standalone-apply.js +584 -0
  306. package/dist/mutation/file-mutation-standalone-planner.js +500 -0
  307. package/dist/mutation/file-mutation-tsserver-session.js +473 -0
  308. package/dist/mutation/mutation-estimate.js +45 -0
  309. package/dist/mutation/mutation-plan.js +467 -0
  310. package/dist/mutation/object-mutation-foundation.js +2 -0
  311. package/dist/mutation/object-mutation-partition.js +148 -0
  312. package/dist/mutation/object-pack-semantic-apply.js +507 -0
  313. package/dist/mutation/object-pack-semantic-preview.js +984 -0
  314. package/dist/mutation/object-unpack-semantic-preview.js +993 -0
  315. package/dist/mutation/package-manifest-impact.js +176 -0
  316. package/dist/mutation/rename-owner-worker-child.js +37 -0
  317. package/dist/mutation/rename-owner-worker.js +122 -0
  318. package/dist/mutation/runtime-cycle-query.js +66 -0
  319. package/dist/mutation/semantic-execution-progress.js +63 -0
  320. package/dist/mutation/semantic-export-index.js +474 -0
  321. package/dist/mutation/semantic-impact-scan.js +434 -0
  322. package/dist/mutation/semantic-model.js +2 -0
  323. package/dist/mutation/semantic-move-best-effort-planner.js +209 -0
  324. package/dist/mutation/semantic-move-config-worker-child.js +61 -0
  325. package/dist/mutation/semantic-move-config-worker.js +449 -0
  326. package/dist/mutation/semantic-move-declarations.js +94 -0
  327. package/dist/mutation/semantic-move-metrics.js +119 -0
  328. package/dist/mutation/semantic-move-model.js +2 -0
  329. package/dist/mutation/semantic-move-owner-authority.js +122 -0
  330. package/dist/mutation/semantic-move-owner-candidates.js +300 -0
  331. package/dist/mutation/semantic-move-owner-divergence-harness.js +474 -0
  332. package/dist/mutation/semantic-move-owner-divergence-runner.js +162 -0
  333. package/dist/mutation/semantic-move-plan-hash.js +56 -0
  334. package/dist/mutation/semantic-move-policy.js +360 -0
  335. package/dist/mutation/semantic-move-process.js +218 -0
  336. package/dist/mutation/semantic-move-provider-diagnostics.js +27 -0
  337. package/dist/mutation/semantic-move-standalone-engine.js +919 -0
  338. package/dist/mutation/semantic-move-standalone-planner.js +1553 -0
  339. package/dist/mutation/semantic-move-transaction.js +639 -0
  340. package/dist/mutation/semantic-mutation-engine.js +478 -0
  341. package/dist/mutation/semantic-mutation-runtime.js +521 -0
  342. package/dist/mutation/semantic-planner-retry.js +26 -0
  343. package/dist/mutation/semantic-program-roots.js +69 -0
  344. package/dist/mutation/semantic-rename-commonjs.js +229 -0
  345. package/dist/mutation/semantic-rename-config-worker-child.js +46 -0
  346. package/dist/mutation/semantic-rename-config-worker.js +498 -0
  347. package/dist/mutation/semantic-rename-locations.js +192 -0
  348. package/dist/mutation/semantic-rename-model.js +2 -0
  349. package/dist/mutation/semantic-rename-process.js +210 -0
  350. package/dist/mutation/semantic-rename-standalone-engine.js +302 -0
  351. package/dist/mutation/semantic-rename-standalone-planner.js +567 -0
  352. package/dist/mutation/semantic-rename-transaction.js +333 -0
  353. package/dist/mutation/semantic-unused-import-cleanup.js +248 -0
  354. package/dist/mutation/semantic-worker-retry.js +40 -0
  355. package/dist/mutation/semantic-workspace.js +804 -0
  356. package/dist/mutation/targeted-import-canonicalizer.js +359 -0
  357. package/dist/observability/config.js +206 -1
  358. package/dist/observability/context.js +59 -1
  359. package/dist/observability/failure-snapshot.js +124 -2
  360. package/dist/observability/recent.js +63 -2
  361. package/dist/payloads/read-stdin-json.js +212 -1
  362. package/dist/rg-wrapper/core.js +714 -6
  363. package/dist/rg-wrapper/options.js +125 -1
  364. package/dist/rtk-wrapper/core.js +144 -2
  365. package/dist/rtk-wrapper/git-safety.js +203 -0
  366. package/dist/rtk-wrapper/output-adapter.js +106 -0
  367. package/dist/runtime/buffered-process.js +114 -0
  368. package/dist/runtime/bundled-node.js +97 -1
  369. package/dist/runtime/command-lifecycle.js +2 -0
  370. package/dist/runtime/input-source.js +238 -1
  371. package/dist/runtime/node-cli-identity.js +37 -0
  372. package/dist/runtime/run-command.js +191 -1
  373. package/dist/selectors/parse-entities.js +84 -1
  374. package/dist/semantic/semantic-context-pool.js +830 -0
  375. package/dist/semantic/semantic-context-provider.js +416 -0
  376. package/dist/semantic/semantic-resident-admission.js +38 -0
  377. package/dist/semantic/semantic-worker-child.js +40 -0
  378. package/dist/semantic/semantic-worker-manager.js +460 -0
  379. package/dist/semantic/semantic-worker-protocol.js +2 -0
  380. package/dist/semantic/semantic-worker-runtime.js +38 -0
  381. package/dist/semantic/workspace-semantic-context-pools.js +136 -0
  382. package/dist/session/client.js +359 -1
  383. package/dist/session/daemon-state.js +185 -2
  384. package/dist/session/external-tool-coordinator.js +88 -0
  385. package/dist/session/external-tool-request.js +52 -0
  386. package/dist/session/lane-owner.js +116 -0
  387. package/dist/session/paths.js +71 -1
  388. package/dist/session/runtime-lifecycle.js +225 -0
  389. package/dist/session/runtime-shutdown.js +95 -0
  390. package/dist/session/server.js +1194 -7
  391. package/dist/session/session-health.js +27 -0
  392. package/dist/shared/agent-text.js +29 -1
  393. package/dist/shared/errors.js +496 -30
  394. package/dist/shared/event-loop.js +6 -1
  395. package/dist/shared/hints.js +37 -1
  396. package/dist/shared/metrics.js +43 -1
  397. package/dist/shared/presentation.js +69 -4
  398. package/dist/shared/stdin-examples.js +77 -1
  399. package/dist/shared/stdout.js +6 -2
  400. package/dist/shared/types.js +23 -1
  401. package/dist/tool-runtime/runtime-tools.js +120 -1
  402. package/dist/topology/availability.js +663 -0
  403. package/dist/topology/cache.js +130 -0
  404. package/dist/topology/candidates.js +372 -0
  405. package/dist/topology/core.js +903 -0
  406. package/dist/topology/dependency-snapshot.js +189 -0
  407. package/dist/topology/model.js +2 -0
  408. package/dist/topology/scope.js +100 -0
  409. package/dist/topology/ts-oracle-batch.js +529 -0
  410. package/dist/topology/ts-oracle-host.js +69 -0
  411. package/dist/topology/ts-oracle-model.js +2 -0
  412. package/dist/topology/ts-oracle.js +224 -0
  413. package/dist/topology/tsconfig-loader.js +105 -0
  414. package/dist/topology/workspace-project-index.js +542 -0
  415. package/dist/tracing/config.js +192 -2
  416. package/dist/tracing/failure-summary.js +100 -0
  417. package/dist/tracing/trace.js +318 -5
  418. package/dist/tsc-wrapper/core.js +697 -0
  419. package/dist/workers/control-plane/aib-control-plane-worker.cjs +32 -32
  420. package/dist/workers/control-plane/client-config.default.json +3 -3
  421. package/dist/workers/lexical-worker-child.js +27 -0
  422. package/dist/workers/lexical-worker-manager.js +394 -0
  423. package/dist/workers/lexical-worker-protocol.js +2 -0
  424. package/dist/workers/lexical-worker-runtime.js +25 -0
  425. package/dist/workers/owned-one-shot-process.js +115 -0
  426. package/dist/workers/product-storage.js +23 -1
  427. package/dist/workers/registry.js +241 -1
  428. package/package.json +8 -13
  429. package/scripts/postinstall.cjs +29 -29
  430. package/scripts/provision-runtime.cjs +411 -459
  431. package/dist/client/http-client.js +0 -1
  432. package/dist/client/transport-options.js +0 -1
  433. package/dist/client/websocket-client.js +0 -1
  434. package/dist/commands/entity-resolution.js +0 -1
  435. package/dist/commands/file-command.js +0 -1
  436. package/dist/commands/host-command.js +0 -1
  437. package/dist/commands/inspect-symbol-query.js +0 -1
  438. package/dist/commands/list-instances.js +0 -1
  439. package/dist/commands/module-plan-command.js +0 -1
  440. package/dist/commands/move-command.js +0 -1
  441. package/dist/commands/move-to-file.js +0 -2
  442. package/dist/commands/ping.js +0 -1
  443. package/dist/commands/refactor-command.js +0 -1
  444. package/dist/commands/rename-command.js +0 -1
  445. package/dist/commands/runtime-command.js +0 -4
  446. package/dist/commands/runtime-info.js +0 -1
  447. package/dist/commands/validate-module-plan.js +0 -2
  448. package/dist/compatibility/policy.js +0 -1
  449. package/dist/config/auto-start-ide.js +0 -1
  450. package/dist/discovery/registry.js +0 -1
  451. package/dist/discovery/select-instance.js +0 -1
  452. package/dist/help/docs/file.rename.md +0 -35
  453. package/dist/help/docs/mutation.md +0 -60
  454. package/dist/help/docs/refactor.batch.md +0 -44
  455. package/dist/help/dsl/docs/file.rename.md +0 -35
  456. package/dist/help/dsl/docs/mutation.md +0 -60
  457. package/dist/help/dsl/docs/refactor.batch.md +0 -44
  458. package/dist/help/dsl/topics/file.rename.md +0 -33
  459. package/dist/help/dsl/topics/mutation.md +0 -58
  460. package/dist/help/dsl/topics/refactor.batch.md +0 -33
  461. package/dist/help/topics/file.rename.md +0 -33
  462. package/dist/help/topics/mutation.md +0 -58
  463. package/dist/help/topics/refactor.batch.md +0 -33
  464. package/dist/ide-launch/common.cjs +0 -162
  465. package/dist/managed-host/extension-vsix-resolver.js +0 -1
  466. package/dist/managed-host/manage-serve-web-host.cjs +0 -141
  467. package/dist/managed-host/serve-web-autostart.js +0 -1
  468. package/dist/managed-host/serve-web-host.cjs +0 -2115
  469. package/dist/runtime/managed-runtime-provisioning.js +0 -1
  470. package/dist/shared/diagnostic-catalog.js +0 -1
  471. package/dist/shared/diagnostics.js +0 -1
  472. package/dist/shared/operations.js +0 -1
  473. package/dist/shared/protocol.js +0 -1
  474. package/dist/shared/routes.js +0 -1
  475. package/extension/vscode-refactor-bridge-extension.vsix +0 -0
  476. package/runtimes/launcher/linux-x64/aib +0 -0
  477. package/runtimes/launcher/win-x64/aib.exe +0 -0
@@ -0,0 +1,1553 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.planStandaloneSemanticMove = planStandaloneSemanticMove;
40
+ const crypto = __importStar(require("node:crypto"));
41
+ const fs = __importStar(require("node:fs"));
42
+ const path = __importStar(require("node:path"));
43
+ const typescript_1 = __importDefault(require("typescript"));
44
+ const file_mutation_discovery_1 = require("./file-mutation-discovery");
45
+ const semantic_move_plan_hash_1 = require("./semantic-move-plan-hash");
46
+ const package_manifest_impact_1 = require("./package-manifest-impact");
47
+ const semantic_move_process_1 = require("./semantic-move-process");
48
+ const semantic_move_declarations_1 = require("./semantic-move-declarations");
49
+ const import_rules_1 = require("../config/import-rules");
50
+ const import_specifier_policy_1 = require("../commands/import-specifier-policy");
51
+ const mutation_comments_1 = require("../config/mutation-comments");
52
+ const typescript_preferences_1 = require("../config/typescript-preferences");
53
+ const semantic_move_policy_1 = require("./semantic-move-policy");
54
+ const semantic_program_roots_1 = require("./semantic-program-roots");
55
+ const semantic_move_owner_authority_1 = require("./semantic-move-owner-authority");
56
+ const semantic_move_owner_candidates_1 = require("./semantic-move-owner-candidates");
57
+ const DEFAULT_DEADLINE_MS = 120_000;
58
+ const MAX_CONFIGS = 32;
59
+ async function planStandaloneSemanticMove(input, dependencies = {
60
+ discover: file_mutation_discovery_1.discoverFileMutationConsumers,
61
+ fingerprint: file_mutation_discovery_1.computeFileMutationWorkspaceFingerprint,
62
+ runConfig: semantic_move_process_1.runSemanticMoveConfigWorker
63
+ }) {
64
+ const startedAt = Date.now();
65
+ const root = path.resolve(input.workspaceRoot);
66
+ const discover = input.semanticContextPool
67
+ ? (request) => (0, file_mutation_discovery_1.discoverFileMutationConsumersWithProjectIndexLease)(input.semanticContextPool, request)
68
+ : dependencies.discover;
69
+ const fingerprint = input.semanticContextPool
70
+ ? (workspaceRoot) => input.semanticContextPool.withWorkspaceProjectIndex((index) => (0, file_mutation_discovery_1.computeFileMutationWorkspaceFingerprintWithProjectIndex)(index, workspaceRoot))
71
+ : dependencies.fingerprint;
72
+ const sourceFile = path.resolve(root, input.sourceFile);
73
+ const targetFile = path.resolve(root, input.targetFile);
74
+ const workspacePreferences = input.importRules?.length
75
+ ? undefined
76
+ : (0, typescript_preferences_1.readWorkspaceTypeScriptPreferences)(root);
77
+ const emptyDiscovery = discoverySummary(null);
78
+ if (!isInside(root, sourceFile) || !isRegularFile(sourceFile)) {
79
+ return incomplete("SEMANTIC_MOVE_SOURCE_INVALID", "Move source is missing or outside the workspace.", root, sourceFile, targetFile, emptyDiscovery, startedAt);
80
+ }
81
+ if (!isInside(root, targetFile) || samePath(sourceFile, targetFile) || (fs.existsSync(targetFile) && !isRegularFile(targetFile))) {
82
+ return incomplete("SEMANTIC_MOVE_TARGET_INVALID", "Move target must be a regular file or an absent file inside the workspace.", root, sourceFile, targetFile, emptyDiscovery, startedAt);
83
+ }
84
+ let sourceBytes;
85
+ try {
86
+ sourceBytes = fs.readFileSync(sourceFile);
87
+ }
88
+ catch (error) {
89
+ return incomplete("SEMANTIC_MOVE_SOURCE_UNREADABLE", errorMessage(error), root, sourceFile, targetFile, emptyDiscovery, startedAt);
90
+ }
91
+ const sourceText = sourceBytes.toString("utf8");
92
+ const targetExisted = fs.existsSync(targetFile);
93
+ let targetBytes;
94
+ try {
95
+ targetBytes = targetExisted ? fs.readFileSync(targetFile) : Buffer.alloc(0);
96
+ }
97
+ catch (error) {
98
+ return incomplete("SEMANTIC_MOVE_TARGET_UNREADABLE", errorMessage(error), root, sourceFile, targetFile, emptyDiscovery, startedAt);
99
+ }
100
+ const targetText = targetBytes.toString("utf8");
101
+ const selection = buildSelection(sourceFile, sourceText, input.entities);
102
+ if (!selection.ok) {
103
+ return {
104
+ ...incomplete(selection.code, selection.error, root, sourceFile, targetFile, emptyDiscovery, startedAt),
105
+ ...(selection.ambiguities ? { ambiguities: selection.ambiguities } : {}),
106
+ ...(selection.contiguousEntityGroups ? { contiguousEntityGroups: selection.contiguousEntityGroups } : {})
107
+ };
108
+ }
109
+ const targetDeclarations = (0, semantic_move_declarations_1.collectSemanticMoveDeclarations)(targetFile, targetText);
110
+ const duplicateTarget = selection.entities.find((entity) => targetDeclarations.some((candidate) => candidate.name === entity.name && (!entity.kind || candidate.kind === entity.kind)));
111
+ if (duplicateTarget) {
112
+ return incomplete("TARGET_SYMBOL_ALREADY_EXISTS", `Target already declares moved symbol: ${duplicateTarget.name}`, root, sourceFile, targetFile, emptyDiscovery, startedAt);
113
+ }
114
+ const mutationComments = input.mutationComments ?? mutation_comments_1.DEFAULT_MUTATION_COMMENTS_POLICY;
115
+ const topFileHeader = (0, semantic_move_policy_1.findDetachedTopFileHeader)(sourceFile, sourceText, selection.firstSelectedName);
116
+ if (topFileHeader && mutationComments.topFileHeader === "fail") {
117
+ return incomplete("TS_MOVE_TO_FILE_TOP_FILE_HEADER_BLOCKED", "Detached top-of-file header policy is configured to fail instead of preserving the header in source.", root, sourceFile, targetFile, emptyDiscovery, startedAt);
118
+ }
119
+ const preservedHeader = topFileHeader && mutationComments.topFileHeader === "preserveInSource" ? topFileHeader : null;
120
+ const workerSourceText = preservedHeader ? sourceText.slice(preservedHeader.end) : sourceText;
121
+ const workerSelection = preservedHeader ? buildSelection(sourceFile, workerSourceText, input.entities) : selection;
122
+ if (!workerSelection.ok) {
123
+ return {
124
+ ...incomplete(workerSelection.code, workerSelection.error, root, sourceFile, targetFile, emptyDiscovery, startedAt),
125
+ ...(workerSelection.ambiguities ? { ambiguities: workerSelection.ambiguities } : {})
126
+ };
127
+ }
128
+ let discovery;
129
+ const discoveryStartedAt = input.metrics?.start();
130
+ try {
131
+ discovery = input.discovery ?? discover({ workspaceRoot: root, sourceFiles: [sourceFile] });
132
+ }
133
+ catch (error) {
134
+ if (discoveryStartedAt !== undefined)
135
+ input.metrics?.end("planner.discovery", discoveryStartedAt);
136
+ return incomplete("SEMANTIC_MOVE_DISCOVERY_FAILED", errorMessage(error), root, sourceFile, targetFile, emptyDiscovery, startedAt);
137
+ }
138
+ if (discoveryStartedAt !== undefined)
139
+ input.metrics?.end("planner.discovery", discoveryStartedAt);
140
+ const summary = discoverySummary(discovery);
141
+ if (!discovery.complete || !discovery.sourceFiles.some((file) => samePath(file, sourceFile))) {
142
+ return incomplete("SEMANTIC_MOVE_DISCOVERY_INCOMPLETE", discovery.uncertainties.map((item) => `${item.kind}:${item.file}:${item.moduleSpecifier}`).join("; ") || "Neutral module discovery is incomplete.", root, sourceFile, targetFile, summary, startedAt);
143
+ }
144
+ if (discovery.ownerConfigs.length === 0 || discovery.ownerConfigs.length > MAX_CONFIGS) {
145
+ return incomplete("SEMANTIC_MOVE_OWNER_SET_UNSUPPORTED", `Expected 1-${MAX_CONFIGS} exact owner configs, found ${discovery.ownerConfigs.length}.`, root, sourceFile, targetFile, summary, startedAt);
146
+ }
147
+ const sourceOwners = ownersForFile(discovery, sourceFile);
148
+ if (sourceOwners.length === 0) {
149
+ return incomplete("SEMANTIC_MOVE_SOURCE_OWNER_MISSING", "Neutral discovery did not provide an exact source owner.", root, sourceFile, targetFile, summary, startedAt);
150
+ }
151
+ const snapshotStartedAt = input.metrics?.start();
152
+ let initialFingerprint;
153
+ try {
154
+ initialFingerprint = fingerprint(root);
155
+ }
156
+ catch (error) {
157
+ if (snapshotStartedAt !== undefined)
158
+ input.metrics?.end("planner.snapshot", snapshotStartedAt);
159
+ return incomplete("SEMANTIC_MOVE_SNAPSHOT_UNREADABLE", errorMessage(error), root, sourceFile, targetFile, summary, startedAt);
160
+ }
161
+ if (initialFingerprint !== discovery.workspaceFingerprint) {
162
+ if (snapshotStartedAt !== undefined)
163
+ input.metrics?.end("planner.snapshot", snapshotStartedAt);
164
+ return incomplete("SEMANTIC_MOVE_DISCOVERY_STALE", "Workspace changed after neutral discovery.", root, sourceFile, targetFile, summary, startedAt);
165
+ }
166
+ let acceptedSourceBytes;
167
+ try {
168
+ acceptedSourceBytes = fs.readFileSync(sourceFile);
169
+ }
170
+ catch (error) {
171
+ if (snapshotStartedAt !== undefined)
172
+ input.metrics?.end("planner.snapshot", snapshotStartedAt);
173
+ return incomplete("SEMANTIC_MOVE_SOURCE_SNAPSHOT_CHANGED", errorMessage(error), root, sourceFile, targetFile, summary, startedAt);
174
+ }
175
+ if (!acceptedSourceBytes.equals(sourceBytes)) {
176
+ if (snapshotStartedAt !== undefined)
177
+ input.metrics?.end("planner.snapshot", snapshotStartedAt);
178
+ return incomplete("SEMANTIC_MOVE_SOURCE_SNAPSHOT_CHANGED", "Move source changed while neutral discovery was being computed.", root, sourceFile, targetFile, summary, startedAt);
179
+ }
180
+ const evidenceFiles = uniquePaths([sourceFile, ...(targetExisted ? [targetFile] : []), ...discovery.consumerFiles]);
181
+ const snapshotHash = hashFiles(evidenceFiles);
182
+ if (snapshotStartedAt !== undefined)
183
+ input.metrics?.end("planner.snapshot", snapshotStartedAt);
184
+ const workerPath = input.testing?.configWorkerPath ?? path.join(__dirname, "semantic-move-config-worker-child.js");
185
+ const results = [];
186
+ const workerEvidence = [];
187
+ const workersStartedAt = input.metrics?.start();
188
+ for (const configFilePath of discovery.ownerConfigs) {
189
+ const exportStarCandidates = discovery.edges
190
+ .filter((edge) => edge.kind === "exportStar" && samePath(edge.targetFile, sourceFile) &&
191
+ !samePath(edge.fromFile, sourceFile) && ownersForFile(discovery, edge.fromFile).some((owner) => samePath(owner, configFilePath)))
192
+ .map((edge) => ({
193
+ barrelFile: edge.fromFile,
194
+ moduleSpecifier: edge.moduleSpecifier,
195
+ specifierStart: edge.specifierStart,
196
+ entities: selection.entities.map((entity) => ({
197
+ name: entity.name,
198
+ ...(entity.kind ? { kind: entity.kind } : {})
199
+ }))
200
+ }));
201
+ const request = {
202
+ type: "semanticMoveConfig",
203
+ id: crypto.randomUUID(),
204
+ workspaceRoot: root,
205
+ configFilePath: path.normalize(configFilePath),
206
+ sourceFile,
207
+ sourceText: workerSourceText,
208
+ targetFile,
209
+ targetText,
210
+ selection: workerSelection.selection,
211
+ preferences: (0, semantic_move_policy_1.semanticMovePreferences)(targetFile, input.importRules ?? [], input.preferences, workspacePreferences),
212
+ programRootFiles: (0, semantic_program_roots_1.focusedSemanticProgramRootFiles)({
213
+ discovery,
214
+ configFilePath,
215
+ requiredFiles: [sourceFile, targetFile]
216
+ }),
217
+ ...(exportStarCandidates.length > 0 ? { exportStarCandidates } : {}),
218
+ ...(import_rules_1.SEMANTIC_MOVE_UNUSED_IMPORT_CLEANUP_ENABLED && input.importRules?.some((rule) => rule.unusedImports === "remove")
219
+ ? { unusedImportCleanupRules: [...input.importRules] }
220
+ : {}),
221
+ ...(input.metrics ? { metricsEnabled: true } : {})
222
+ };
223
+ let outcome;
224
+ try {
225
+ outcome = await dependencies.runConfig({
226
+ modulePath: workerPath,
227
+ request,
228
+ deadlineMs: input.deadlineMs ?? DEFAULT_DEADLINE_MS
229
+ });
230
+ }
231
+ catch (error) {
232
+ if (workersStartedAt !== undefined)
233
+ input.metrics?.end("planner.ownerWorkers", workersStartedAt);
234
+ return incomplete(readErrorCode(error) ?? "SEMANTIC_MOVE_CONFIG_WORKER_FAILED", errorMessage(error), root, sourceFile, targetFile, summary, startedAt, snapshotHash, workerEvidence);
235
+ }
236
+ workerEvidence.push({
237
+ configFilePath: outcome.result.configFilePath,
238
+ pid: outcome.result.pid,
239
+ rssMiB: outcome.result.rssMiB,
240
+ durationMs: outcome.durationMs,
241
+ terminationConfirmed: outcome.terminationConfirmed,
242
+ fileEditCount: outcome.result.edits.length,
243
+ textChangeCount: outcome.result.edits.reduce((sum, edit) => sum + edit.textChanges.length, 0)
244
+ });
245
+ input.metrics?.observeWorker({
246
+ ...(outcome.metrics ?? {}),
247
+ ...(outcome.result.metrics ?? {})
248
+ });
249
+ const acceptedResult = rebasePreservedHeaderResult(outcome.result, sourceFile, sourceText, workerSourceText, preservedHeader);
250
+ dependencies.observeConfigResult?.(acceptedResult);
251
+ if (!outcome.terminationConfirmed || !outcome.result.ok || !outcome.result.containsSource) {
252
+ if (workersStartedAt !== undefined)
253
+ input.metrics?.end("planner.ownerWorkers", workersStartedAt);
254
+ return incomplete(outcome.result.failureKind === "provider-unsupported"
255
+ ? "SEMANTIC_MOVE_PROVIDER_UNSUPPORTED"
256
+ : outcome.result.failureKind === "changes-overlap"
257
+ ? "SEMANTIC_MOVE_CHANGES_OVERLAP"
258
+ : outcome.result.failureKind === "provider-failed"
259
+ ? "SEMANTIC_MOVE_PROVIDER_FAILED"
260
+ : "SEMANTIC_MOVE_OWNER_PROOF_FAILED", outcome.result.error ?? `Exact owner projection ${configFilePath} did not provide a move plan.`, root, sourceFile, targetFile, summary, startedAt, snapshotHash, workerEvidence);
261
+ }
262
+ results.push(acceptedResult);
263
+ }
264
+ if (workersStartedAt !== undefined)
265
+ input.metrics?.end("planner.ownerWorkers", workersStartedAt);
266
+ const mergeStartedAt = input.metrics?.start();
267
+ const moduleSpecifierResolver = (0, semantic_move_owner_candidates_1.createSemanticMoveModuleSpecifierResolver)();
268
+ const canonicalModuleResolver = (0, semantic_move_owner_candidates_1.createSemanticMoveCanonicalModuleResolver)();
269
+ const merged = mergeOwnerEvidence({
270
+ root,
271
+ sourceFile,
272
+ targetFile,
273
+ sourceOwners,
274
+ targetExisted,
275
+ discovery,
276
+ results,
277
+ importRules: input.importRules ?? [],
278
+ moduleSpecifierResolver,
279
+ canonicalModuleResolver,
280
+ ...(workspacePreferences ? { workspacePreferences } : {}),
281
+ ...(input.metrics ? { metrics: input.metrics } : {})
282
+ });
283
+ if (mergeStartedAt !== undefined)
284
+ input.metrics?.end("planner.merge", mergeStartedAt);
285
+ if (!merged.ok) {
286
+ return incomplete(merged.code, merged.error, root, sourceFile, targetFile, summary, startedAt, snapshotHash, workerEvidence, merged.divergence ? [merged.divergence] : []);
287
+ }
288
+ const validationStartedAt = input.metrics?.start();
289
+ let validationEnded = false;
290
+ const endValidation = () => {
291
+ if (validationEnded || validationStartedAt === undefined)
292
+ return;
293
+ validationEnded = true;
294
+ input.metrics?.end("planner.validation", validationStartedAt);
295
+ };
296
+ const policyEdits = (0, semantic_move_policy_1.applySemanticMoveImportPolicies)({
297
+ workspaceRoot: root,
298
+ edits: merged.edits,
299
+ importRules: input.importRules ?? [],
300
+ ...(workspacePreferences ? { workspacePreferences } : {}),
301
+ acceptsModuleSpecifier: ({ fileName, specifier, targetFile: resolvedTarget }) => {
302
+ const ownerConfigs = merged.moduleSpecifierOwners.get(pathKey(fileName));
303
+ return Boolean(ownerConfigs?.length && moduleSpecifierResolver({
304
+ specifier,
305
+ containingFile: fileName,
306
+ targetFile: resolvedTarget,
307
+ ownerConfigs
308
+ }));
309
+ },
310
+ resolveVirtualModuleTarget: ({ fileName, specifier }) => {
311
+ const ownerConfigs = merged.moduleSpecifierOwners.get(pathKey(fileName));
312
+ return ownerConfigs?.length && moduleSpecifierResolver({
313
+ specifier,
314
+ containingFile: fileName,
315
+ targetFile,
316
+ ownerConfigs
317
+ })
318
+ ? targetFile
319
+ : null;
320
+ }
321
+ });
322
+ const semanticEdits = applySafeDynamicImportMoveEdits({
323
+ workspaceRoot: root,
324
+ sourceFile,
325
+ targetFile,
326
+ entities: selection.entities,
327
+ discovery,
328
+ edits: policyEdits,
329
+ importRules: input.importRules ?? [],
330
+ ...(workspacePreferences ? { workspacePreferences } : {}),
331
+ moduleSpecifierResolver
332
+ });
333
+ const namedReexportEdits = applySafeNamedReexportMoveEdits({
334
+ workspaceRoot: root,
335
+ sourceFile,
336
+ targetFile,
337
+ entities: selection.entities,
338
+ discovery,
339
+ edits: semanticEdits,
340
+ importRules: input.importRules ?? [],
341
+ ...(workspacePreferences ? { workspacePreferences } : {}),
342
+ moduleSpecifierResolver
343
+ });
344
+ const structure = verifyMoveStructure(sourceFile, targetFile, sourceText, selection.entities, namedReexportEdits);
345
+ if (!structure.ok) {
346
+ endValidation();
347
+ return incomplete(structure.code, structure.error, root, sourceFile, targetFile, summary, startedAt, snapshotHash, workerEvidence);
348
+ }
349
+ const exportStarCompletion = applySafeExportStarMoveEdits({
350
+ workspaceRoot: root,
351
+ sourceFile,
352
+ targetFile,
353
+ entities: selection.entities,
354
+ discovery,
355
+ edits: namedReexportEdits,
356
+ results,
357
+ importRules: input.importRules ?? [],
358
+ ...(workspacePreferences ? { workspacePreferences } : {}),
359
+ moduleSpecifierResolver
360
+ });
361
+ const completeEdits = exportStarCompletion.edits;
362
+ const edgeCoverage = verifyMovedEntityEdgeCoverage(sourceFile, selection.entities, discovery, completeEdits, exportStarCompletion.coveredEdges);
363
+ if (!edgeCoverage.ok) {
364
+ endValidation();
365
+ return incomplete(edgeCoverage.code, edgeCoverage.error, root, sourceFile, targetFile, summary, startedAt, snapshotHash, workerEvidence);
366
+ }
367
+ const synthesizedEditFiles = new Set(completeEdits
368
+ .filter((edit) => !policyEdits.some((candidate) => samePath(candidate.fileName, edit.fileName)))
369
+ .map((edit) => pathKey(edit.fileName)));
370
+ if (!verifyBeforeHashes(results, completeEdits, synthesizedEditFiles)) {
371
+ endValidation();
372
+ return incomplete("SEMANTIC_MOVE_EDIT_SNAPSHOT_CHANGED", "A config or edited file changed during planning.", root, sourceFile, targetFile, summary, startedAt, snapshotHash, workerEvidence);
373
+ }
374
+ let finalFingerprint;
375
+ try {
376
+ finalFingerprint = fingerprint(root);
377
+ }
378
+ catch (error) {
379
+ endValidation();
380
+ return incomplete("SEMANTIC_MOVE_SNAPSHOT_UNREADABLE", errorMessage(error), root, sourceFile, targetFile, summary, startedAt, snapshotHash, workerEvidence);
381
+ }
382
+ const finalTargetMatches = fs.existsSync(targetFile) === targetExisted &&
383
+ (!targetExisted || fs.readFileSync(targetFile).equals(targetBytes));
384
+ if (finalFingerprint !== discovery.workspaceFingerprint || hashFiles(evidenceFiles) !== snapshotHash || !finalTargetMatches) {
385
+ endValidation();
386
+ return incomplete("SEMANTIC_MOVE_SNAPSHOT_CHANGED", "Workspace files, configs, packages, consumers, or target existence changed during planning.", root, sourceFile, targetFile, summary, startedAt, snapshotHash, workerEvidence);
387
+ }
388
+ endValidation();
389
+ const completePlan = {
390
+ complete: true,
391
+ code: "SEMANTIC_MOVE_PLAN_COMPLETE",
392
+ workspaceRoot: root,
393
+ sourceFile,
394
+ targetFile,
395
+ targetExisted,
396
+ entities: selection.entities,
397
+ edits: completeEdits,
398
+ discovery: summary,
399
+ configWorkers: workerEvidence,
400
+ snapshotHash,
401
+ planHash: "",
402
+ totalMs: Date.now() - startedAt,
403
+ packageManifestImpacts: (0, package_manifest_impact_1.collectMutationPackageManifestImpacts)({
404
+ mutationKind: "declaration-move",
405
+ sourceFile,
406
+ targetFile,
407
+ changedFiles: completeEdits.map((edit) => edit.fileName),
408
+ packageManifests: discovery.packageManifests
409
+ })
410
+ };
411
+ completePlan.planHash = (0, semantic_move_plan_hash_1.computeSemanticMovePlanHash)(completePlan);
412
+ return completePlan;
413
+ }
414
+ function buildSelection(sourceFile, sourceText, rawEntities) {
415
+ if (rawEntities.length === 0)
416
+ return { ok: false, code: "SEMANTIC_MOVE_ENTITY_REQUIRED", error: "At least one top-level entity is required." };
417
+ const candidates = (0, semantic_move_declarations_1.collectSemanticMoveDeclarations)(sourceFile, sourceText);
418
+ const seenCandidates = new Set();
419
+ const selected = [];
420
+ const entities = [];
421
+ const entityStatementRanges = [];
422
+ for (const [index, item] of rawEntities.entries()) {
423
+ if (!isValidIdentifierName(item.name)) {
424
+ return { ok: false, code: "SEMANTIC_MOVE_ENTITY_INVALID", error: `Invalid or duplicate entity: ${item.name}` };
425
+ }
426
+ const matches = candidates.filter((candidate) => candidate.name === item.name && (!item.kind || candidate.kind === item.kind));
427
+ if (matches.length === 0) {
428
+ return { ok: false, code: "SEMANTIC_MOVE_ENTITY_NOT_FOUND", error: `Top-level entity not found: ${item.kind ? `${item.kind}:` : ""}${item.name}` };
429
+ }
430
+ const matchedKinds = [...new Set(matches.map((candidate) => candidate.kind))];
431
+ if (!item.kind && matchedKinds.length > 1) {
432
+ return {
433
+ ok: false,
434
+ code: "SEMANTIC_MOVE_ENTITY_AMBIGUOUS",
435
+ error: `Top-level entity matches multiple declaration kinds: ${item.name} (${matchedKinds.join(", ")}). Specify the declaration kind.`,
436
+ ambiguities: [{ entity: item.name, kinds: matchedKinds }]
437
+ };
438
+ }
439
+ if (matches.some((candidate) => seenCandidates.has(candidateKey(candidate)))) {
440
+ return { ok: false, code: "SEMANTIC_MOVE_ENTITY_INVALID", error: `Invalid or duplicate entity: ${item.name}` };
441
+ }
442
+ const indexes = [...new Set(matches.map((candidate) => candidate.statementIndex))].sort((left, right) => left - right);
443
+ if (indexes.some((value, candidateIndex) => candidateIndex > 0 && value !== indexes[candidateIndex - 1] + 1)) {
444
+ return { ok: false, code: "SEMANTIC_MOVE_ENTITY_AMBIGUOUS", error: `Non-contiguous declarations found for: ${item.name}` };
445
+ }
446
+ for (const match of matches)
447
+ seenCandidates.add(candidateKey(match));
448
+ selected.push(...matches);
449
+ entityStatementRanges.push({
450
+ id: item.id ?? item.name,
451
+ first: indexes[0],
452
+ last: indexes[indexes.length - 1]
453
+ });
454
+ entities.push({
455
+ id: item.id ?? `entity-${index + 1}`,
456
+ name: item.name,
457
+ ...(item.kind ?? (new Set(matches.map((candidate) => candidate.kind)).size === 1 ? matches[0].kind : null)
458
+ ? { kind: item.kind ?? matches[0].kind }
459
+ : {}),
460
+ declarationStarts: matches.map((candidate) => candidate.nameStart)
461
+ });
462
+ }
463
+ const statementIndexes = [...new Set(selected.map((candidate) => candidate.statementIndex))].sort((left, right) => left - right);
464
+ for (const statementIndex of statementIndexes) {
465
+ const unrequested = candidates.find((candidate) => candidate.statementIndex === statementIndex && !seenCandidates.has(candidateKey(candidate)));
466
+ if (unrequested) {
467
+ return {
468
+ ok: false,
469
+ code: "SEMANTIC_MOVE_DECLARATION_GROUP_INCOMPLETE",
470
+ error: `Moving this declaration would also move unrequested top-level entity: ${unrequested.name}`
471
+ };
472
+ }
473
+ }
474
+ if (statementIndexes.some((value, index) => index > 0 && value !== statementIndexes[index - 1] + 1)) {
475
+ return {
476
+ ok: false,
477
+ code: "SEMANTIC_MOVE_ENTITIES_NOT_CONTIGUOUS",
478
+ error: "Requested top-level entities are not contiguous.",
479
+ contiguousEntityGroups: groupContiguousEntityRanges(entityStatementRanges)
480
+ };
481
+ }
482
+ const ordered = [...selected].sort((left, right) => left.statementStart - right.statementStart || left.nameStart - right.nameStart);
483
+ const selection = ordered.length === 1
484
+ ? { pos: ordered[0].nameStart, end: ordered[0].nameEnd }
485
+ : { pos: ordered[0].statementStart, end: ordered[ordered.length - 1].statementEnd };
486
+ return { ok: true, entities, selection, firstSelectedName: ordered[0].name };
487
+ }
488
+ function candidateKey(candidate) {
489
+ return `${candidate.statementIndex}:${candidate.nameStart}:${candidate.kind}`;
490
+ }
491
+ function rebasePreservedHeaderResult(result, sourceFile, sourceText, workerSourceText, header) {
492
+ if (!header || !result.ok)
493
+ return result;
494
+ return {
495
+ ...result,
496
+ edits: result.edits.map((edit) => {
497
+ if (!samePath(edit.fileName, sourceFile))
498
+ return edit;
499
+ const rendered = applyTextChanges(workerSourceText, edit.textChanges);
500
+ return {
501
+ ...edit,
502
+ isNewFile: false,
503
+ textChanges: [{
504
+ span: { start: 0, length: sourceText.length },
505
+ newText: `${header.text}${rendered}`
506
+ }]
507
+ };
508
+ })
509
+ };
510
+ }
511
+ function mergeOwnerEvidence(input) {
512
+ const resultMap = new Map(input.results.map((result) => [pathKey(result.configFilePath), result]));
513
+ const ownerAuthority = (0, semantic_move_owner_authority_1.createSemanticMoveOwnerAuthority)(input.discovery);
514
+ const observations = new Map();
515
+ const allowed = new Set(uniquePaths([input.sourceFile, input.targetFile, ...input.discovery.consumerFiles]).map(pathKey));
516
+ for (const result of input.results) {
517
+ const config = pathKey(result.configFilePath);
518
+ const perFile = new Map();
519
+ for (const rawEdit of result.edits) {
520
+ const edit = normalizeFileEdit(rawEdit);
521
+ const file = pathKey(edit.fileName);
522
+ if (!isInside(input.root, edit.fileName) || !allowed.has(file) || perFile.has(file)) {
523
+ return { ok: false, code: "SEMANTIC_MOVE_EDIT_SCOPE_INVALID", error: `Unexpected or duplicate edit from ${result.configFilePath}: ${edit.fileName}` };
524
+ }
525
+ perFile.set(file, edit);
526
+ const fileObservations = observations.get(file) ?? new Map();
527
+ fileObservations.set(config, edit);
528
+ observations.set(file, fileObservations);
529
+ }
530
+ }
531
+ const requiredFiles = [pathKey(input.sourceFile), pathKey(input.targetFile)];
532
+ if (requiredFiles.some((file) => !observations.has(file))) {
533
+ return { ok: false, code: "SEMANTIC_MOVE_REQUIRED_EDIT_MISSING", error: "Move plan did not contain both source and target edits." };
534
+ }
535
+ const edits = [];
536
+ const moduleSpecifierOwners = new Map();
537
+ for (const [file, fileObservations] of observations) {
538
+ const firstObservation = fileObservations.values().next().value;
539
+ if (!firstObservation)
540
+ continue;
541
+ const owners = samePath(firstObservation.fileName, input.sourceFile) || samePath(firstObservation.fileName, input.targetFile)
542
+ ? input.sourceOwners
543
+ : ownersForFile(input.discovery, firstObservation.fileName);
544
+ if (owners.length === 0) {
545
+ return ownerDivergenceFailure({
546
+ reason: "owner-evidence-missing",
547
+ fileName: firstObservation.fileName,
548
+ owners,
549
+ observations: fileObservations,
550
+ error: `No exact owner evidence exists for ${firstObservation.fileName}.`
551
+ });
552
+ }
553
+ if (owners.length > 1)
554
+ input.metrics?.observeDivergence("multiOwnerFiles", firstObservation.fileName);
555
+ const ownerRoles = new Map(owners.map((owner) => [
556
+ pathKey(owner),
557
+ ownerAuthority.roleForConsumer({ consumerFile: firstObservation.fileName, ownerConfig: owner })
558
+ ]));
559
+ const requiredOwners = owners.filter((owner) => ownerRoles.get(pathKey(owner)) !== "generated-declaration-projection");
560
+ let candidate = requiredOwners
561
+ .map((owner) => fileObservations.get(pathKey(owner)))
562
+ .find((observation) => Boolean(observation));
563
+ if (!candidate) {
564
+ return ownerDivergenceFailure({
565
+ reason: "owner-evidence-missing",
566
+ fileName: firstObservation.fileName,
567
+ owners,
568
+ ownerRoles,
569
+ observations: fileObservations,
570
+ error: `No non-projection owner edit exists for ${firstObservation.fileName}.`
571
+ });
572
+ }
573
+ const requiredObservations = requiredOwners
574
+ .map((owner) => fileObservations.get(pathKey(owner)))
575
+ .filter((observation) => Boolean(observation));
576
+ if (requiredObservations.length !== requiredOwners.length) {
577
+ return ownerDivergenceFailure({
578
+ reason: "owner-edit-missing",
579
+ fileName: candidate.fileName,
580
+ owners,
581
+ ownerRoles,
582
+ observations: fileObservations,
583
+ error: `An exact owner omitted ${candidate.fileName}.`
584
+ });
585
+ }
586
+ let reconciledModuleSpecifiers = false;
587
+ if (new Set(requiredObservations.map(editSignature)).size > 1) {
588
+ input.metrics?.observeDivergence("divergentProposalFiles", candidate.fileName);
589
+ const isNewTarget = samePath(candidate.fileName, input.targetFile) && !input.targetExisted;
590
+ if (samePath(candidate.fileName, input.sourceFile) || samePath(candidate.fileName, input.targetFile) && !isNewTarget ||
591
+ !isRegularFile(candidate.fileName) && !isNewTarget) {
592
+ input.metrics?.observeDivergence("unresolvedDivergences", candidate.fileName);
593
+ return ownerDivergenceFailure({
594
+ reason: "source-target-edit-disagreement",
595
+ fileName: candidate.fileName,
596
+ owners,
597
+ ownerRoles,
598
+ observations: fileObservations,
599
+ error: `Exact owners disagree on ${candidate.fileName}.`
600
+ });
601
+ }
602
+ const configuredEnding = input.importRules.length > 0
603
+ ? (0, import_rules_1.resolveImportRuleForFile)(candidate.fileName, input.importRules)?.ending
604
+ : input.workspacePreferences
605
+ ? (0, typescript_preferences_1.resolveWorkspaceImportPreferences)(input.workspacePreferences, candidate.fileName).ending
606
+ : undefined;
607
+ const preferredEnding = configuredEnding === "auto" || configuredEnding === "js" || configuredEnding === "minimal"
608
+ ? configuredEnding
609
+ : undefined;
610
+ const reconciliation = isNewTarget
611
+ ? (0, semantic_move_owner_candidates_1.reconcileSemanticMoveNewTargetCandidates)({
612
+ fileName: candidate.fileName,
613
+ sourceFile: input.sourceFile,
614
+ sourceText: fs.readFileSync(input.sourceFile, "utf8"),
615
+ ownerConfigs: requiredOwners,
616
+ observations: requiredObservations,
617
+ ...(preferredEnding ? { preferredEnding } : {}),
618
+ resolver: input.canonicalModuleResolver
619
+ })
620
+ : (0, semantic_move_owner_candidates_1.reconcileSemanticMoveOwnerCandidates)({
621
+ fileName: candidate.fileName,
622
+ expectedText: fs.readFileSync(candidate.fileName, "utf8"),
623
+ targetFile: input.targetFile,
624
+ ownerConfigs: requiredOwners,
625
+ observations: requiredObservations,
626
+ resolver: input.moduleSpecifierResolver
627
+ });
628
+ const policyCanSelect = !isNewTarget && reconciliation.status === "ambiguous" && Boolean(input.importRules.length > 0
629
+ ? (0, import_rules_1.resolveImportRuleForFile)(candidate.fileName, input.importRules)?.specifier
630
+ : input.workspacePreferences &&
631
+ (0, typescript_preferences_1.resolveWorkspaceImportPreferences)(input.workspacePreferences, candidate.fileName).specifier);
632
+ if (reconciliation.status !== "selected" && !policyCanSelect) {
633
+ input.metrics?.observeDivergence("unresolvedDivergences", candidate.fileName);
634
+ const reason = reconciliation.status === "ambiguous"
635
+ ? `${reconciliation.validCandidateCount} module-specifier candidates are valid for every exact owner`
636
+ : reconciliation.status === "none-valid"
637
+ ? "no module-specifier candidate is valid for every exact owner"
638
+ : "owner plans differ outside module-specifier literals";
639
+ return ownerDivergenceFailure({
640
+ reason: reconciliation.status === "ambiguous"
641
+ ? "module-specifier-ambiguous"
642
+ : reconciliation.status === "none-valid"
643
+ ? "module-specifier-none-valid"
644
+ : isNewTarget
645
+ ? "source-target-edit-disagreement"
646
+ : "non-module-specifier-disagreement",
647
+ fileName: candidate.fileName,
648
+ owners,
649
+ ownerRoles,
650
+ observations: fileObservations,
651
+ ...(reconciliation.status === "ambiguous"
652
+ ? { universallyValidCandidateCount: reconciliation.validCandidateCount }
653
+ : reconciliation.status === "none-valid"
654
+ ? { universallyValidCandidateCount: 0 }
655
+ : {}),
656
+ error: `${reason}: ${candidate.fileName}.`
657
+ });
658
+ }
659
+ candidate = reconciliation.edit;
660
+ reconciledModuleSpecifiers = true;
661
+ input.metrics?.observeDivergence("policyResolvedDivergences", candidate.fileName);
662
+ }
663
+ moduleSpecifierOwners.set(pathKey(candidate.fileName), requiredOwners);
664
+ const signature = editSignature(candidate);
665
+ for (const owner of owners) {
666
+ const ownerKey = pathKey(owner);
667
+ const observation = fileObservations.get(pathKey(owner));
668
+ if (!resultMap.has(ownerKey)) {
669
+ return ownerDivergenceFailure({
670
+ reason: "owner-evidence-missing",
671
+ fileName: candidate.fileName,
672
+ owners,
673
+ ownerRoles,
674
+ observations: fileObservations,
675
+ error: `${owner} disagrees on ${candidate.fileName}.`
676
+ });
677
+ }
678
+ // A proven declaration output describes the pre-build package view. Its worker must finish,
679
+ // but neither an empty nor a conflicting proposal can overrule the exact source owner.
680
+ if (ownerRoles.get(ownerKey) === "generated-declaration-projection")
681
+ continue;
682
+ if (!observation) {
683
+ return ownerDivergenceFailure({
684
+ reason: "owner-edit-missing",
685
+ fileName: candidate.fileName,
686
+ owners,
687
+ ownerRoles,
688
+ observations: fileObservations,
689
+ error: `${owner} disagrees on ${candidate.fileName}.`
690
+ });
691
+ }
692
+ if (!reconciledModuleSpecifiers && editSignature(observation) !== signature) {
693
+ return ownerDivergenceFailure({
694
+ reason: "owner-edit-disagreement",
695
+ fileName: candidate.fileName,
696
+ owners,
697
+ ownerRoles,
698
+ observations: fileObservations,
699
+ error: `${owner} disagrees on ${candidate.fileName}.`
700
+ });
701
+ }
702
+ }
703
+ const exactOwnerKeys = new Set(owners.map(pathKey));
704
+ if ([...fileObservations].some(([config, observation]) => !exactOwnerKeys.has(config) && editSignature(observation) !== signature)) {
705
+ return ownerDivergenceFailure({
706
+ reason: "non-owner-projection-disagreement",
707
+ fileName: candidate.fileName,
708
+ owners: uniquePaths([...owners, ...fileObservations.keys()]),
709
+ ownerRoles,
710
+ observations: fileObservations,
711
+ error: `A non-owning projection disagrees on ${candidate.fileName}.`
712
+ });
713
+ }
714
+ const isTarget = samePath(candidate.fileName, input.targetFile);
715
+ const expectedExists = isTarget ? input.targetExisted : true;
716
+ if (candidate.isNewFile !== !expectedExists || (expectedExists && !isRegularFile(candidate.fileName))) {
717
+ return { ok: false, code: "SEMANTIC_MOVE_FILE_SHAPE_INVALID", error: `Invalid new/existing file evidence for ${candidate.fileName}.` };
718
+ }
719
+ const expectedBytes = expectedExists ? fs.readFileSync(candidate.fileName) : Buffer.alloc(0);
720
+ const expectedText = expectedBytes.toString("utf8");
721
+ const textChanges = normalizeExistingTargetEndOfFileSentinel({
722
+ fileName: candidate.fileName,
723
+ expectedText,
724
+ changes: candidate.textChanges,
725
+ enabled: isTarget && expectedExists
726
+ });
727
+ const validation = validateTextChanges(candidate.fileName, expectedText, textChanges);
728
+ if (!validation.ok)
729
+ return validation;
730
+ edits.push({
731
+ ...candidate,
732
+ textChanges,
733
+ expectedExists,
734
+ expectedText,
735
+ expectedHash: crypto.createHash("sha256").update(expectedBytes).digest("hex")
736
+ });
737
+ observations.set(file, fileObservations);
738
+ }
739
+ return {
740
+ ok: true,
741
+ edits: edits.sort((left, right) => left.fileName.localeCompare(right.fileName)),
742
+ moduleSpecifierOwners
743
+ };
744
+ }
745
+ function ownerDivergenceFailure(input) {
746
+ const signatures = new Set();
747
+ const ownerEvidence = uniquePaths(input.owners).map((owner) => {
748
+ const observation = input.observations.get(pathKey(owner));
749
+ if (observation)
750
+ signatures.add(editSignature(observation));
751
+ return {
752
+ configFilePath: path.normalize(owner),
753
+ role: input.ownerRoles?.get(pathKey(owner)) ?? "unproven",
754
+ proposal: observation ? "present" : "missing",
755
+ ...(observation
756
+ ? { proposalHash: crypto.createHash("sha256").update(editSignature(observation)).digest("hex") }
757
+ : {})
758
+ };
759
+ });
760
+ return {
761
+ ok: false,
762
+ code: "SEMANTIC_MOVE_OWNER_DIVERGENCE",
763
+ error: input.error,
764
+ divergence: {
765
+ reason: input.reason,
766
+ fileName: path.normalize(input.fileName),
767
+ ownerEvidence,
768
+ candidateCount: signatures.size,
769
+ ...(input.universallyValidCandidateCount !== undefined
770
+ ? { universallyValidCandidateCount: input.universallyValidCandidateCount }
771
+ : {})
772
+ }
773
+ };
774
+ }
775
+ function verifyMoveStructure(sourceFile, targetFile, sourceText, entities, edits) {
776
+ const sourceEdit = edits.find((edit) => samePath(edit.fileName, sourceFile));
777
+ const targetEdit = edits.find((edit) => samePath(edit.fileName, targetFile));
778
+ if (!sourceEdit || !targetEdit)
779
+ return { ok: false, code: "SEMANTIC_MOVE_REQUIRED_EDIT_MISSING", error: "Source or target edit is missing." };
780
+ const renderedSource = applyTextChanges(sourceEdit.expectedText, sourceEdit.textChanges);
781
+ const renderedTarget = applyTextChanges(targetEdit.expectedText, targetEdit.textChanges);
782
+ for (const entity of entities) {
783
+ const expectedCount = (0, semantic_move_declarations_1.countSemanticMoveDeclarations)(sourceFile, sourceText, entity.name, entity.kind);
784
+ if (expectedCount !== entity.declarationStarts.length || (0, semantic_move_declarations_1.countSemanticMoveDeclarations)(sourceFile, renderedSource, entity.name, entity.kind) !== 0 ||
785
+ (0, semantic_move_declarations_1.countSemanticMoveDeclarations)(targetFile, renderedTarget, entity.name, entity.kind) !== expectedCount) {
786
+ return {
787
+ ok: false,
788
+ code: "SEMANTIC_MOVE_STRUCTURE_DIVERGENCE",
789
+ error: `TypeScript move did not transfer the exact top-level declaration group for ${entity.name}.`
790
+ };
791
+ }
792
+ }
793
+ const requestedKinds = new Set(entities.map((entity) => `${entity.name}\0${entity.kind ?? "*"}`));
794
+ const protectedDeclarations = new Map();
795
+ for (const candidate of (0, semantic_move_declarations_1.collectSemanticMoveDeclarations)(sourceFile, sourceText)) {
796
+ if (requestedKinds.has(`${candidate.name}\0*`) || requestedKinds.has(`${candidate.name}\0${candidate.kind}`))
797
+ continue;
798
+ const key = `${candidate.name}\0${candidate.kind}`;
799
+ const current = protectedDeclarations.get(key);
800
+ protectedDeclarations.set(key, { name: candidate.name, kind: candidate.kind, count: (current?.count ?? 0) + 1 });
801
+ }
802
+ for (const declaration of protectedDeclarations.values()) {
803
+ if ((0, semantic_move_declarations_1.countSemanticMoveDeclarations)(sourceFile, renderedSource, declaration.name, declaration.kind) !== declaration.count) {
804
+ return {
805
+ ok: false,
806
+ code: "SEMANTIC_MOVE_STRUCTURE_DIVERGENCE",
807
+ error: `TypeScript move changed unrequested top-level ${declaration.kind} declaration ${declaration.name}.`
808
+ };
809
+ }
810
+ }
811
+ return { ok: true };
812
+ }
813
+ function groupContiguousEntityRanges(ranges) {
814
+ const ordered = [...ranges].sort((left, right) => left.first - right.first || left.last - right.last);
815
+ const groups = [];
816
+ for (const range of ordered) {
817
+ const current = groups[groups.length - 1];
818
+ if (current && range.first <= current.last + 1) {
819
+ current.last = Math.max(current.last, range.last);
820
+ current.ids.push(range.id);
821
+ }
822
+ else {
823
+ groups.push({ last: range.last, ids: [range.id] });
824
+ }
825
+ }
826
+ return groups.map((group) => group.ids);
827
+ }
828
+ function chooseSemanticMoveTargetSpecifier(input) {
829
+ let configuredRule = input.importRules.length > 0
830
+ ? (0, import_rules_1.resolveImportRuleForFile)(input.fromFile, input.importRules)
831
+ : null;
832
+ if (!configuredRule && input.workspacePreferences) {
833
+ const preferences = (0, typescript_preferences_1.resolveWorkspaceImportPreferences)(input.workspacePreferences, input.fromFile);
834
+ if (preferences.specifier || preferences.ending) {
835
+ configuredRule = {
836
+ scope: ".",
837
+ scopePath: input.workspaceRoot,
838
+ ...(preferences.specifier ? { specifier: preferences.specifier } : {}),
839
+ ...(preferences.ending ? { ending: preferences.ending } : {})
840
+ };
841
+ }
842
+ }
843
+ const inferredEnding = /\.[cm]?js$/i.test(input.originalSpecifier) ? "js" : "minimal";
844
+ const rule = (0, import_specifier_policy_1.materializeAutoImportEnding)({
845
+ scope: configuredRule?.scope ?? ".",
846
+ scopePath: configuredRule?.scopePath ?? input.workspaceRoot,
847
+ specifier: configuredRule?.specifier ?? "relative",
848
+ ending: configuredRule?.ending ?? inferredEnding,
849
+ ...(configuredRule?.builtin ? { builtin: configuredRule.builtin } : {}),
850
+ ...(configuredRule?.unusedImports ? { unusedImports: configuredRule.unusedImports } : {})
851
+ }, input.originalSpecifier);
852
+ const config = (0, import_specifier_policy_1.readNearestTsConfig)(input.fromFile, input.workspaceRoot, input.configCache);
853
+ const preferred = (0, import_specifier_policy_1.chooseImportSpecifier)({
854
+ fromFile: input.fromFile,
855
+ targetFile: input.targetFile,
856
+ config,
857
+ rule,
858
+ allowIndexCollapse: true
859
+ });
860
+ const relative = (0, import_specifier_policy_1.chooseImportSpecifier)({
861
+ fromFile: input.fromFile,
862
+ targetFile: input.targetFile,
863
+ config,
864
+ rule: { ...rule, specifier: "relative" },
865
+ allowIndexCollapse: true
866
+ });
867
+ return [preferred, relative].find((specifier) => input.moduleSpecifierResolver({
868
+ specifier,
869
+ containingFile: input.fromFile,
870
+ targetFile: input.targetFile,
871
+ ownerConfigs: input.owners
872
+ })) ?? null;
873
+ }
874
+ function applySafeDynamicImportMoveEdits(input) {
875
+ const names = new Set(input.entities.map((entity) => entity.name));
876
+ const editsByFile = new Map(input.edits.map((edit) => [pathKey(edit.fileName), edit]));
877
+ const renderedByFile = new Map();
878
+ const processed = new Set();
879
+ const configCache = new Map();
880
+ for (const edge of input.discovery.edges) {
881
+ if (edge.kind !== "dynamic" || !samePath(edge.targetFile, input.sourceFile) || !isRegularFile(edge.fromFile)) {
882
+ continue;
883
+ }
884
+ const key = `${pathKey(edge.fromFile)}\0${edge.moduleSpecifier}`;
885
+ if (processed.has(key))
886
+ continue;
887
+ processed.add(key);
888
+ const edit = editsByFile.get(pathKey(edge.fromFile));
889
+ const expectedText = edit?.expectedText ?? fs.readFileSync(edge.fromFile, "utf8");
890
+ const currentText = renderedByFile.get(pathKey(edge.fromFile)) ??
891
+ (edit ? applyTextChanges(edit.expectedText, edit.textChanges) : expectedText);
892
+ const source = typescript_1.default.createSourceFile(edge.fromFile, currentText, typescript_1.default.ScriptTarget.Latest, true, scriptKindForFile(edge.fromFile));
893
+ const literals = collectSafeDynamicImportLiterals(source, edge.moduleSpecifier, names);
894
+ if (literals.length === 0)
895
+ continue;
896
+ const owners = ownersForFile(input.discovery, edge.fromFile);
897
+ if (owners.length === 0)
898
+ continue;
899
+ const nextSpecifier = chooseSemanticMoveTargetSpecifier({
900
+ workspaceRoot: input.workspaceRoot,
901
+ fromFile: edge.fromFile,
902
+ targetFile: input.targetFile,
903
+ originalSpecifier: edge.moduleSpecifier,
904
+ owners,
905
+ importRules: input.importRules,
906
+ ...(input.workspacePreferences ? { workspacePreferences: input.workspacePreferences } : {}),
907
+ moduleSpecifierResolver: input.moduleSpecifierResolver,
908
+ configCache
909
+ });
910
+ if (!nextSpecifier)
911
+ continue;
912
+ let nextText = currentText;
913
+ for (const literal of literals.sort((left, right) => right.start - left.start)) {
914
+ nextText = `${nextText.slice(0, literal.start)}${nextSpecifier}${nextText.slice(literal.start + literal.length)}`;
915
+ }
916
+ renderedByFile.set(pathKey(edge.fromFile), nextText);
917
+ }
918
+ return mergeSemanticMoveRenderedFiles(input.edits, renderedByFile, input.discovery);
919
+ }
920
+ function exportStarEdgeKey(edge) {
921
+ return `${pathKey(edge.fromFile)}\0${edge.specifierStart}`;
922
+ }
923
+ function applySafeNamedReexportMoveEdits(input) {
924
+ const names = new Set(input.entities.map((entity) => entity.name));
925
+ const editsByFile = new Map(input.edits.map((edit) => [pathKey(edit.fileName), edit]));
926
+ const renderedByFile = new Map();
927
+ const processed = new Set();
928
+ const configCache = new Map();
929
+ const sourceEdit = editsByFile.get(pathKey(input.sourceFile));
930
+ const renderedSource = sourceEdit
931
+ ? applyTextChanges(sourceEdit.expectedText, sourceEdit.textChanges)
932
+ : fs.readFileSync(input.sourceFile, "utf8");
933
+ const retainedNames = new Set((0, semantic_move_declarations_1.collectSemanticMoveDeclarations)(input.sourceFile, renderedSource).map((declaration) => declaration.name));
934
+ for (const edge of input.discovery.edges) {
935
+ if (edge.kind !== "reexport" || !samePath(edge.targetFile, input.sourceFile) || !isRegularFile(edge.fromFile))
936
+ continue;
937
+ const key = `${pathKey(edge.fromFile)}\0${edge.moduleSpecifier}`;
938
+ if (processed.has(key))
939
+ continue;
940
+ processed.add(key);
941
+ const edit = editsByFile.get(pathKey(edge.fromFile));
942
+ const expectedText = edit?.expectedText ?? fs.readFileSync(edge.fromFile, "utf8");
943
+ const currentText = renderedByFile.get(pathKey(edge.fromFile)) ??
944
+ (edit ? applyTextChanges(edit.expectedText, edit.textChanges) : expectedText);
945
+ const source = typescript_1.default.createSourceFile(edge.fromFile, currentText, typescript_1.default.ScriptTarget.Latest, true, scriptKindForFile(edge.fromFile));
946
+ const matching = source.statements.filter((statement) => typescript_1.default.isExportDeclaration(statement) && statement.exportClause !== undefined && typescript_1.default.isNamedExports(statement.exportClause) &&
947
+ statement.moduleSpecifier !== undefined && typescript_1.default.isStringLiteralLike(statement.moduleSpecifier) &&
948
+ statement.moduleSpecifier.text === edge.moduleSpecifier);
949
+ if (matching.length === 0)
950
+ continue;
951
+ const owners = ownersForFile(input.discovery, edge.fromFile);
952
+ if (owners.length === 0)
953
+ continue;
954
+ const nextSpecifier = chooseSemanticMoveTargetSpecifier({
955
+ workspaceRoot: input.workspaceRoot,
956
+ fromFile: edge.fromFile,
957
+ targetFile: input.targetFile,
958
+ originalSpecifier: edge.moduleSpecifier,
959
+ owners,
960
+ importRules: input.importRules,
961
+ ...(input.workspacePreferences ? { workspacePreferences: input.workspacePreferences } : {}),
962
+ moduleSpecifierResolver: input.moduleSpecifierResolver,
963
+ configCache
964
+ });
965
+ if (!nextSpecifier)
966
+ continue;
967
+ const replacements = matching.flatMap((statement) => {
968
+ const replacement = renderSemanticMoveNamedReexportReplacement(source, statement, edge.moduleSpecifier, nextSpecifier, names, retainedNames);
969
+ return replacement === null
970
+ ? []
971
+ : [{ start: statement.getStart(source), length: statement.getWidth(source), replacement }];
972
+ });
973
+ if (replacements.length === 0)
974
+ continue;
975
+ let rendered = currentText;
976
+ for (const replacement of replacements.sort((left, right) => right.start - left.start)) {
977
+ rendered = `${rendered.slice(0, replacement.start)}${replacement.replacement}${rendered.slice(replacement.start + replacement.length)}`;
978
+ }
979
+ renderedByFile.set(pathKey(edge.fromFile), rendered);
980
+ }
981
+ return mergeSemanticMoveRenderedFiles(input.edits, renderedByFile, input.discovery);
982
+ }
983
+ function renderSemanticMoveNamedReexportReplacement(source, statement, sourceSpecifier, targetSpecifier, movedNames, retainedNames) {
984
+ const clause = statement.exportClause;
985
+ if (!clause || !typescript_1.default.isNamedExports(clause) || statement.attributes)
986
+ return null;
987
+ const clauseStart = clause.getStart(source);
988
+ const comments = [...clause.getText(source).matchAll(/\/\/[^\r\n]*|\/\*[\s\S]*?\*\//g)].map((match) => ({
989
+ pos: clauseStart + match.index,
990
+ text: match[0]
991
+ }));
992
+ const claimedComments = new Set();
993
+ const descriptors = [];
994
+ for (const element of clause.elements) {
995
+ if (!typescript_1.default.isIdentifier(element.name) || element.propertyName && !typescript_1.default.isIdentifier(element.propertyName))
996
+ return null;
997
+ const sourceName = (element.propertyName ?? element.name).text;
998
+ const alias = element.propertyName ? `${element.propertyName.text} as ${element.name.text}` : element.name.text;
999
+ const typeOnly = statement.isTypeOnly || element.isTypeOnly;
1000
+ const leadingComments = (typescript_1.default.getLeadingCommentRanges(source.text, element.getFullStart()) ?? [])
1001
+ .filter((range) => range.pos >= clauseStart && range.end <= clause.getEnd());
1002
+ for (const range of leadingComments)
1003
+ claimedComments.add(range.pos);
1004
+ descriptors.push({
1005
+ sourceName,
1006
+ text: !statement.isTypeOnly && element.isTypeOnly ? `type ${alias}` : alias,
1007
+ typeOnly,
1008
+ comments: leadingComments.map((range) => source.text.slice(range.pos, range.end)),
1009
+ end: element.getEnd()
1010
+ });
1011
+ }
1012
+ for (const comment of comments.filter((candidate) => !claimedComments.has(candidate.pos))) {
1013
+ let previous;
1014
+ for (let index = descriptors.length - 1; index >= 0; index--) {
1015
+ if (descriptors[index].end <= comment.pos) {
1016
+ previous = descriptors[index];
1017
+ break;
1018
+ }
1019
+ }
1020
+ if (previous && source.getLineAndCharacterOfPosition(previous.end).line === source.getLineAndCharacterOfPosition(comment.pos).line) {
1021
+ previous.comments.push(comment.text);
1022
+ claimedComments.add(comment.pos);
1023
+ }
1024
+ }
1025
+ const moved = descriptors.filter((descriptor) => movedNames.has(descriptor.sourceName) && !retainedNames.has(descriptor.sourceName));
1026
+ if (moved.length === 0)
1027
+ return null;
1028
+ const retained = descriptors.filter((descriptor) => !movedNames.has(descriptor.sourceName) || retainedNames.has(descriptor.sourceName));
1029
+ const rawSpecifier = statement.moduleSpecifier?.getText(source) ?? "";
1030
+ const quote = rawSpecifier.startsWith("'") ? "'" : '"';
1031
+ const semicolon = statement.getText(source).trimEnd().endsWith(";");
1032
+ return [
1033
+ ...comments.filter((comment) => !claimedComments.has(comment.pos)).map((comment) => comment.text),
1034
+ ...(retained.length > 0
1035
+ ? [renderSemanticMoveNamedReexport(sourceSpecifier, quote, statement.isTypeOnly, retained, semicolon)]
1036
+ : []),
1037
+ renderSemanticMoveNamedReexport(targetSpecifier, quote, statement.isTypeOnly, moved, semicolon)
1038
+ ].join("\n");
1039
+ }
1040
+ function renderSemanticMoveNamedReexport(moduleSpecifier, quote, statementTypeOnly, descriptors, semicolon) {
1041
+ const prefix = statementTypeOnly ? "export type" : "export";
1042
+ const suffix = semicolon ? ";" : "";
1043
+ const typeModes = new Set(descriptors.map((descriptor) => descriptor.typeOnly));
1044
+ if (descriptors.length <= 2 && typeModes.size === 1 && descriptors.every((descriptor) => descriptor.comments.length === 0)) {
1045
+ return `${prefix} { ${descriptors.map((descriptor) => descriptor.text).join(", ")} } from ${quote}${moduleSpecifier}${quote}${suffix}`;
1046
+ }
1047
+ return [
1048
+ `${prefix} {`,
1049
+ ...descriptors.flatMap((descriptor) => [
1050
+ ...descriptor.comments.flatMap((comment) => comment.split(/\r?\n/).map((line) => ` ${line.trimStart()}`)),
1051
+ ` ${descriptor.text},`
1052
+ ]),
1053
+ `} from ${quote}${moduleSpecifier}${quote}${suffix}`
1054
+ ].join("\n");
1055
+ }
1056
+ function applySafeExportStarMoveEdits(input) {
1057
+ const coveredEdges = new Set();
1058
+ const editsByFile = new Map(input.edits.map((edit) => [pathKey(edit.fileName), edit]));
1059
+ const sourceEdit = editsByFile.get(pathKey(input.sourceFile));
1060
+ const renderedSource = sourceEdit
1061
+ ? applyTextChanges(sourceEdit.expectedText, sourceEdit.textChanges)
1062
+ : fs.readFileSync(input.sourceFile, "utf8");
1063
+ if (!typescript_1.default.isExternalModule(typescript_1.default.createSourceFile(input.sourceFile, renderedSource, typescript_1.default.ScriptTarget.Latest, true, scriptKindForFile(input.sourceFile)))) {
1064
+ return { edits: [...input.edits], coveredEdges };
1065
+ }
1066
+ const renderedByFile = new Map();
1067
+ const configCache = new Map();
1068
+ for (const edge of input.discovery.edges) {
1069
+ if (edge.kind !== "exportStar" || !samePath(edge.targetFile, input.sourceFile) || !isRegularFile(edge.fromFile))
1070
+ continue;
1071
+ const owners = ownersForFile(input.discovery, edge.fromFile);
1072
+ if (owners.length === 0)
1073
+ continue;
1074
+ const valueEntities = [];
1075
+ const typeEntities = [];
1076
+ let completeProof = true;
1077
+ for (const entity of input.entities) {
1078
+ const proofs = owners.map((owner) => input.results
1079
+ .find((result) => samePath(result.configFilePath, owner))
1080
+ ?.exportStarProofs?.find((proof) => samePath(proof.barrelFile, edge.fromFile) &&
1081
+ proof.specifierStart === edge.specifierStart && proof.entity === entity.name));
1082
+ if (proofs.some((proof) => !proof?.checked)) {
1083
+ completeProof = false;
1084
+ break;
1085
+ }
1086
+ const matches = proofs.map((proof) => proof.matchesSourceSymbol);
1087
+ if (new Set(matches).size !== 1) {
1088
+ completeProof = false;
1089
+ break;
1090
+ }
1091
+ if (!matches[0]) {
1092
+ completeProof = false;
1093
+ break;
1094
+ }
1095
+ const typeOnly = proofs.map((proof) => proof.typeOnly);
1096
+ if (new Set(typeOnly).size !== 1) {
1097
+ completeProof = false;
1098
+ break;
1099
+ }
1100
+ (typeOnly[0] ? typeEntities : valueEntities).push(entity.name);
1101
+ }
1102
+ if (!completeProof)
1103
+ continue;
1104
+ const uniqueValueEntities = [...new Set(valueEntities)];
1105
+ const valueEntityNames = new Set(uniqueValueEntities);
1106
+ const uniqueTypeEntities = [...new Set(typeEntities)].filter((name) => !valueEntityNames.has(name));
1107
+ const nextSpecifier = chooseSemanticMoveTargetSpecifier({
1108
+ workspaceRoot: input.workspaceRoot,
1109
+ fromFile: edge.fromFile,
1110
+ targetFile: input.targetFile,
1111
+ originalSpecifier: edge.moduleSpecifier,
1112
+ owners,
1113
+ importRules: input.importRules,
1114
+ ...(input.workspacePreferences ? { workspacePreferences: input.workspacePreferences } : {}),
1115
+ moduleSpecifierResolver: input.moduleSpecifierResolver,
1116
+ configCache
1117
+ });
1118
+ if (!nextSpecifier)
1119
+ continue;
1120
+ const existing = editsByFile.get(pathKey(edge.fromFile));
1121
+ const expectedText = existing?.expectedText ?? fs.readFileSync(edge.fromFile, "utf8");
1122
+ const currentText = renderedByFile.get(pathKey(edge.fromFile)) ??
1123
+ (existing ? applyTextChanges(existing.expectedText, existing.textChanges) : expectedText);
1124
+ const barrelSource = typescript_1.default.createSourceFile(edge.fromFile, currentText, typescript_1.default.ScriptTarget.Latest, true, scriptKindForFile(edge.fromFile));
1125
+ const star = barrelSource.statements.find((statement) => typescript_1.default.isExportDeclaration(statement) && !statement.exportClause && statement.moduleSpecifier !== undefined &&
1126
+ typescript_1.default.isStringLiteralLike(statement.moduleSpecifier) && statement.moduleSpecifier.text === edge.moduleSpecifier);
1127
+ if (!star?.moduleSpecifier || !typescript_1.default.isStringLiteralLike(star.moduleSpecifier))
1128
+ continue;
1129
+ const rawSpecifier = star.moduleSpecifier.getText(barrelSource);
1130
+ const quote = rawSpecifier.startsWith("'") ? "'" : '"';
1131
+ renderedByFile.set(pathKey(edge.fromFile), mergeOrAppendSemanticMoveNamedExport({
1132
+ source: barrelSource,
1133
+ text: currentText,
1134
+ moduleSpecifier: nextSpecifier,
1135
+ quote,
1136
+ valueEntities: uniqueValueEntities,
1137
+ typeEntities: uniqueTypeEntities
1138
+ }));
1139
+ coveredEdges.add(exportStarEdgeKey(edge));
1140
+ }
1141
+ return {
1142
+ edits: mergeSemanticMoveRenderedFiles(input.edits, renderedByFile, input.discovery),
1143
+ coveredEdges
1144
+ };
1145
+ }
1146
+ function mergeSemanticMoveRenderedFiles(edits, renderedByFile, discovery) {
1147
+ if (renderedByFile.size === 0)
1148
+ return [...edits];
1149
+ const result = [...edits];
1150
+ for (const [fileKey, rendered] of renderedByFile) {
1151
+ const existingIndex = result.findIndex((edit) => pathKey(edit.fileName) === fileKey);
1152
+ if (existingIndex >= 0) {
1153
+ const existing = result[existingIndex];
1154
+ result[existingIndex] = {
1155
+ ...existing,
1156
+ textChanges: [{ span: { start: 0, length: existing.expectedText.length }, newText: rendered }]
1157
+ };
1158
+ continue;
1159
+ }
1160
+ const fileName = discovery.edges.find((edge) => pathKey(edge.fromFile) === fileKey).fromFile;
1161
+ const expectedBytes = fs.readFileSync(fileName);
1162
+ const expectedText = expectedBytes.toString("utf8");
1163
+ result.push({
1164
+ fileName,
1165
+ isNewFile: false,
1166
+ textChanges: [{ span: { start: 0, length: expectedText.length }, newText: rendered }],
1167
+ expectedExists: true,
1168
+ expectedText,
1169
+ expectedHash: crypto.createHash("sha256").update(expectedBytes).digest("hex")
1170
+ });
1171
+ }
1172
+ return result.sort((left, right) => left.fileName.localeCompare(right.fileName));
1173
+ }
1174
+ function renderSemanticMoveNamedExport(moduleSpecifier, quote, valueEntities, typeEntities) {
1175
+ const specifiers = [
1176
+ ...valueEntities,
1177
+ ...typeEntities.map((name) => `type ${name}`)
1178
+ ];
1179
+ if (specifiers.length <= 2 && (valueEntities.length === 0 || typeEntities.length === 0)) {
1180
+ return `export { ${specifiers.join(", ")} } from ${quote}${moduleSpecifier}${quote};`;
1181
+ }
1182
+ return [
1183
+ "export {",
1184
+ ...specifiers.map((specifier) => ` ${specifier},`),
1185
+ `} from ${quote}${moduleSpecifier}${quote};`
1186
+ ].join("\n");
1187
+ }
1188
+ function mergeOrAppendSemanticMoveNamedExport(input) {
1189
+ const matching = input.source.statements.filter((statement) => typescript_1.default.isExportDeclaration(statement) && statement.exportClause !== undefined && typescript_1.default.isNamedExports(statement.exportClause) &&
1190
+ statement.moduleSpecifier !== undefined && typescript_1.default.isStringLiteralLike(statement.moduleSpecifier) &&
1191
+ statement.moduleSpecifier.text === input.moduleSpecifier);
1192
+ const append = () => {
1193
+ const rendered = renderSemanticMoveNamedExport(input.moduleSpecifier, input.quote, input.valueEntities, input.typeEntities);
1194
+ const separator = input.text.length === 0 || input.text.endsWith("\n") ? "" : "\n";
1195
+ return `${input.text}${separator}${rendered}\n`;
1196
+ };
1197
+ if (matching.length === 0)
1198
+ return append();
1199
+ const indexes = matching.map((statement) => input.source.statements.indexOf(statement));
1200
+ if (indexes.some((value, index) => index > 0 && value !== indexes[index - 1] + 1))
1201
+ return append();
1202
+ const existingValues = [];
1203
+ const existingTypes = [];
1204
+ for (const statement of matching) {
1205
+ const clause = statement.exportClause;
1206
+ if (!clause || !typescript_1.default.isNamedExports(clause))
1207
+ return append();
1208
+ const statementValues = [];
1209
+ const statementTypes = [];
1210
+ for (const element of clause.elements) {
1211
+ if (element.propertyName || !typescript_1.default.isIdentifier(element.name))
1212
+ return append();
1213
+ (statement.isTypeOnly || element.isTypeOnly ? statementTypes : statementValues).push(element.name.text);
1214
+ }
1215
+ const rawSpecifier = statement.moduleSpecifier?.getText(input.source) ?? "";
1216
+ const statementQuote = rawSpecifier.startsWith("'") ? "'" : '"';
1217
+ if (statement.getText(input.source) !== renderSemanticMoveNamedExport(input.moduleSpecifier, statementQuote, statementValues, statementTypes))
1218
+ return append();
1219
+ existingValues.push(...statementValues);
1220
+ existingTypes.push(...statementTypes);
1221
+ }
1222
+ const valueEntities = [...new Set([...existingValues, ...input.valueEntities])];
1223
+ const valueNames = new Set(valueEntities);
1224
+ const typeEntities = [...new Set([...existingTypes, ...input.typeEntities])].filter((name) => !valueNames.has(name));
1225
+ const rendered = renderSemanticMoveNamedExport(input.moduleSpecifier, input.quote, valueEntities, typeEntities);
1226
+ const first = matching[0];
1227
+ const last = matching[matching.length - 1];
1228
+ return `${input.text.slice(0, first.getStart(input.source))}${rendered}${input.text.slice(last.getEnd())}`;
1229
+ }
1230
+ function collectSafeDynamicImportLiterals(source, moduleSpecifier, names) {
1231
+ const literals = [];
1232
+ const visit = (node) => {
1233
+ if (typescript_1.default.isCallExpression(node) && node.expression.kind === typescript_1.default.SyntaxKind.ImportKeyword &&
1234
+ node.arguments.length === 1 && typescript_1.default.isStringLiteralLike(node.arguments[0]) &&
1235
+ node.arguments[0].text === moduleSpecifier && analyzeDynamicImportUsage(source, node, names) === "movedOnly") {
1236
+ const literal = node.arguments[0];
1237
+ literals.push({ start: literal.getStart(source) + 1, length: literal.text.length });
1238
+ }
1239
+ typescript_1.default.forEachChild(node, visit);
1240
+ };
1241
+ visit(source);
1242
+ return literals;
1243
+ }
1244
+ function analyzeDynamicImportUsage(source, call, names) {
1245
+ const initializer = typescript_1.default.isAwaitExpression(call.parent) ? call.parent : call;
1246
+ const declaration = initializer.parent;
1247
+ if (!typescript_1.default.isVariableDeclaration(declaration) || declaration.initializer !== initializer || !typescript_1.default.isIdentifier(declaration.name)) {
1248
+ return "uncertain";
1249
+ }
1250
+ const binding = declaration.name;
1251
+ let moved = false;
1252
+ let retained = false;
1253
+ let uncertain = false;
1254
+ const visit = (node) => {
1255
+ if (uncertain)
1256
+ return;
1257
+ if (typescript_1.default.isIdentifier(node) && node.text === binding.text && node !== binding) {
1258
+ const parent = node.parent;
1259
+ let property = null;
1260
+ if (typescript_1.default.isPropertyAccessExpression(parent) && parent.expression === node) {
1261
+ property = parent.name.text;
1262
+ }
1263
+ else if (typescript_1.default.isElementAccessExpression(parent) && parent.expression === node &&
1264
+ parent.argumentExpression && typescript_1.default.isStringLiteralLike(parent.argumentExpression)) {
1265
+ property = parent.argumentExpression.text;
1266
+ }
1267
+ else {
1268
+ uncertain = true;
1269
+ return;
1270
+ }
1271
+ if (names.has(property))
1272
+ moved = true;
1273
+ else
1274
+ retained = true;
1275
+ }
1276
+ typescript_1.default.forEachChild(node, visit);
1277
+ };
1278
+ visit(source);
1279
+ if (uncertain)
1280
+ return "uncertain";
1281
+ if (moved && retained)
1282
+ return "mixed";
1283
+ if (moved)
1284
+ return "movedOnly";
1285
+ if (retained)
1286
+ return "unaffected";
1287
+ return "uncertain";
1288
+ }
1289
+ function verifyMovedEntityEdgeCoverage(sourceFile, entities, discovery, edits, coveredExportStarEdges = new Set()) {
1290
+ const names = new Set(entities.map((entity) => entity.name));
1291
+ const editsByFile = new Map(edits.map((edit) => [pathKey(edit.fileName), edit]));
1292
+ const sourceEdit = editsByFile.get(pathKey(sourceFile));
1293
+ const renderedSource = sourceEdit ? applyTextChanges(sourceEdit.expectedText, sourceEdit.textChanges) : fs.readFileSync(sourceFile, "utf8");
1294
+ const sourceRemainsModule = typescript_1.default.isExternalModule(typescript_1.default.createSourceFile(sourceFile, renderedSource, typescript_1.default.ScriptTarget.Latest, true, scriptKindForFile(sourceFile)));
1295
+ for (const edge of discovery.edges.filter((candidate) => samePath(candidate.targetFile, sourceFile))) {
1296
+ if (samePath(edge.fromFile, sourceFile) || !isRegularFile(edge.fromFile))
1297
+ continue;
1298
+ if (edge.kind === "exportStar" && coveredExportStarEdges.has(exportStarEdgeKey(edge)))
1299
+ continue;
1300
+ const originalText = fs.readFileSync(edge.fromFile, "utf8");
1301
+ const originalAffected = sourceRemainsModule
1302
+ ? moduleEdgeCarriesMovedEntity(edge.kind, edge.moduleSpecifier, originalText, edge.fromFile, names)
1303
+ : containsModuleEdge(originalText, edge.fromFile, edge.moduleSpecifier);
1304
+ if (!originalAffected)
1305
+ continue;
1306
+ const edit = editsByFile.get(pathKey(edge.fromFile));
1307
+ const finalText = edit ? applyTextChanges(edit.expectedText, edit.textChanges) : originalText;
1308
+ const finalAffected = sourceRemainsModule
1309
+ ? moduleEdgeCarriesMovedEntity(edge.kind, edge.moduleSpecifier, finalText, edge.fromFile, names)
1310
+ : containsModuleEdge(finalText, edge.fromFile, edge.moduleSpecifier);
1311
+ if (finalAffected) {
1312
+ return {
1313
+ ok: false,
1314
+ code: "SEMANTIC_MOVE_REQUIRED_EDGE_UNCHANGED",
1315
+ error: `TypeScript move left a required ${edge.kind} edge pointing at the old source: ${edge.fromFile}:${edge.line}.`
1316
+ };
1317
+ }
1318
+ }
1319
+ return { ok: true };
1320
+ }
1321
+ function containsModuleEdge(text, fileName, moduleSpecifier) {
1322
+ const source = typescript_1.default.createSourceFile(fileName, text, typescript_1.default.ScriptTarget.Latest, true, scriptKindForFile(fileName));
1323
+ return containsModuleSpecifier(source, moduleSpecifier);
1324
+ }
1325
+ function moduleEdgeCarriesMovedEntity(kind, moduleSpecifier, text, fileName, names) {
1326
+ const source = typescript_1.default.createSourceFile(fileName, text, typescript_1.default.ScriptTarget.Latest, true, scriptKindForFile(fileName));
1327
+ if (kind === "dynamic") {
1328
+ let carries = false;
1329
+ const visit = (node) => {
1330
+ if (carries)
1331
+ return;
1332
+ if (typescript_1.default.isCallExpression(node) && node.expression.kind === typescript_1.default.SyntaxKind.ImportKeyword &&
1333
+ node.arguments.length === 1 && typescript_1.default.isStringLiteralLike(node.arguments[0]) &&
1334
+ node.arguments[0].text === moduleSpecifier && analyzeDynamicImportUsage(source, node, names) !== "unaffected") {
1335
+ carries = true;
1336
+ return;
1337
+ }
1338
+ typescript_1.default.forEachChild(node, visit);
1339
+ };
1340
+ visit(source);
1341
+ return carries;
1342
+ }
1343
+ let carries = false;
1344
+ source.forEachChild((node) => {
1345
+ if (carries)
1346
+ return;
1347
+ if (typescript_1.default.isImportDeclaration(node) && moduleText(node.moduleSpecifier) === moduleSpecifier) {
1348
+ const bindings = node.importClause?.namedBindings;
1349
+ if (bindings && typescript_1.default.isNamedImports(bindings)) {
1350
+ carries = bindings.elements.some((element) => names.has((element.propertyName ?? element.name).text));
1351
+ }
1352
+ else if (bindings && typescript_1.default.isNamespaceImport(bindings)) {
1353
+ carries = namespaceReferencesEntity(source, bindings.name.text, names);
1354
+ }
1355
+ return;
1356
+ }
1357
+ if (typescript_1.default.isExportDeclaration(node) && node.moduleSpecifier && moduleText(node.moduleSpecifier) === moduleSpecifier) {
1358
+ if (!node.exportClause || typescript_1.default.isNamespaceExport(node.exportClause))
1359
+ carries = true;
1360
+ else
1361
+ carries = node.exportClause.elements.some((element) => names.has((element.propertyName ?? element.name).text));
1362
+ return;
1363
+ }
1364
+ if (kind === "require" || kind === "importEquals") {
1365
+ carries = containsModuleSpecifier(node, moduleSpecifier);
1366
+ }
1367
+ });
1368
+ return carries;
1369
+ }
1370
+ function namespaceReferencesEntity(source, namespaceName, names) {
1371
+ let found = false;
1372
+ const visit = (node) => {
1373
+ if (found)
1374
+ return;
1375
+ if (typescript_1.default.isPropertyAccessExpression(node) && typescript_1.default.isIdentifier(node.expression) && node.expression.text === namespaceName && names.has(node.name.text)) {
1376
+ found = true;
1377
+ return;
1378
+ }
1379
+ if (typescript_1.default.isQualifiedName(node) && typescript_1.default.isIdentifier(node.left) && node.left.text === namespaceName && names.has(node.right.text)) {
1380
+ found = true;
1381
+ return;
1382
+ }
1383
+ typescript_1.default.forEachChild(node, visit);
1384
+ };
1385
+ typescript_1.default.forEachChild(source, visit);
1386
+ return found;
1387
+ }
1388
+ function containsModuleSpecifier(node, moduleSpecifier) {
1389
+ let found = false;
1390
+ const visit = (candidate) => {
1391
+ if (found)
1392
+ return;
1393
+ if (typescript_1.default.isStringLiteralLike(candidate) && candidate.text === moduleSpecifier) {
1394
+ found = true;
1395
+ return;
1396
+ }
1397
+ typescript_1.default.forEachChild(candidate, visit);
1398
+ };
1399
+ visit(node);
1400
+ return found;
1401
+ }
1402
+ function moduleText(node) {
1403
+ return typescript_1.default.isStringLiteralLike(node) ? node.text : null;
1404
+ }
1405
+ function verifyBeforeHashes(results, edits, synthesizedFiles = new Set()) {
1406
+ if (results.some((result) => !result.configHash || result.configHash !== hashFile(result.configFilePath)))
1407
+ return false;
1408
+ for (const edit of edits.filter((item) => item.expectedExists)) {
1409
+ const observed = results.flatMap((result) => Object.entries(result.beforeHashes))
1410
+ .filter(([file]) => samePath(file, edit.fileName))
1411
+ .map(([, hash]) => hash);
1412
+ if ((observed.length === 0 && !synthesizedFiles.has(pathKey(edit.fileName))) ||
1413
+ observed.some((hash) => hash !== edit.expectedHash) || hashFile(edit.fileName) !== edit.expectedHash)
1414
+ return false;
1415
+ }
1416
+ return true;
1417
+ }
1418
+ function validateTextChanges(fileName, text, changes) {
1419
+ const ordered = [...changes].sort((left, right) => left.span.start - right.span.start || left.span.length - right.span.length);
1420
+ for (const [index, change] of ordered.entries()) {
1421
+ if (change.span.start < 0 || change.span.length < 0 || change.span.start + change.span.length > text.length) {
1422
+ return { ok: false, code: "SEMANTIC_MOVE_EDIT_SPAN_INVALID", error: `Invalid edit span in ${fileName}.` };
1423
+ }
1424
+ const previous = index > 0 ? ordered[index - 1] : undefined;
1425
+ if (previous && previous.span.start + previous.span.length > change.span.start) {
1426
+ return { ok: false, code: "SEMANTIC_MOVE_EDIT_OVERLAP", error: `Overlapping edits in ${fileName}.` };
1427
+ }
1428
+ }
1429
+ return { ok: true };
1430
+ }
1431
+ function normalizeExistingTargetEndOfFileSentinel(input) {
1432
+ if (!input.enabled)
1433
+ return [...input.changes];
1434
+ const source = typescript_1.default.createSourceFile(input.fileName, input.expectedText, typescript_1.default.ScriptTarget.Latest, true, scriptKindForFile(input.fileName));
1435
+ if (source.statements.length > 0)
1436
+ return [...input.changes];
1437
+ return input.changes.map((change) => change.span.length === 0 && change.span.start === input.expectedText.length + 1
1438
+ ? { ...change, span: { start: input.expectedText.length, length: 0 } }
1439
+ : change);
1440
+ }
1441
+ function normalizeFileEdit(edit) {
1442
+ return {
1443
+ fileName: path.normalize(edit.fileName),
1444
+ isNewFile: edit.isNewFile,
1445
+ textChanges: edit.textChanges.map((change) => ({
1446
+ span: { start: change.span.start, length: change.span.length },
1447
+ newText: change.newText
1448
+ }))
1449
+ };
1450
+ }
1451
+ function editSignature(edit) {
1452
+ return JSON.stringify({ isNewFile: edit.isNewFile, textChanges: edit.textChanges });
1453
+ }
1454
+ function applyTextChanges(text, changes) {
1455
+ const ordered = [...changes].sort((left, right) => left.span.start - right.span.start || left.span.length - right.span.length);
1456
+ let cursor = 0;
1457
+ let output = "";
1458
+ for (const change of ordered) {
1459
+ output += text.slice(cursor, change.span.start) + change.newText;
1460
+ cursor = change.span.start + change.span.length;
1461
+ }
1462
+ return output + text.slice(cursor);
1463
+ }
1464
+ function ownersForFile(discovery, fileName) {
1465
+ return discovery.fileOwners.find((item) => samePath(item.file, fileName))?.ownerConfigs.map(path.normalize).sort() ?? [];
1466
+ }
1467
+ function discoverySummary(discovery) {
1468
+ return {
1469
+ filesScanned: discovery?.filesScanned ?? 0,
1470
+ bytesScanned: discovery?.bytesScanned ?? 0,
1471
+ consumerCount: discovery?.consumerFiles.length ?? 0,
1472
+ edgeCount: discovery?.edgeCount ?? 0,
1473
+ ownerConfigCount: discovery?.ownerConfigs.length ?? 0,
1474
+ workspaceFingerprint: discovery?.workspaceFingerprint ?? ""
1475
+ };
1476
+ }
1477
+ function incomplete(code, error, root, sourceFile, targetFile, discovery, startedAt, snapshotHash = "", configWorkers = [], divergences = []) {
1478
+ return {
1479
+ complete: false,
1480
+ code,
1481
+ error,
1482
+ workspaceRoot: root,
1483
+ sourceFile,
1484
+ targetFile,
1485
+ targetExisted: fs.existsSync(targetFile),
1486
+ entities: [],
1487
+ edits: [],
1488
+ discovery,
1489
+ configWorkers,
1490
+ snapshotHash,
1491
+ planHash: "",
1492
+ totalMs: Date.now() - startedAt,
1493
+ ...(divergences.length > 0 ? { divergences } : {})
1494
+ };
1495
+ }
1496
+ function isValidIdentifierName(value) {
1497
+ const source = typescript_1.default.createSourceFile("name.ts", `const ${value}=1`, typescript_1.default.ScriptTarget.Latest, true, typescript_1.default.ScriptKind.TS);
1498
+ const parseDiagnostics = source.parseDiagnostics ?? [];
1499
+ const statement = source.statements[0];
1500
+ return parseDiagnostics.length === 0 && statement !== undefined && typescript_1.default.isVariableStatement(statement) &&
1501
+ statement.declarationList.declarations.length === 1 &&
1502
+ typescript_1.default.isIdentifier(statement.declarationList.declarations[0].name) &&
1503
+ statement.declarationList.declarations[0].name.text === value;
1504
+ }
1505
+ function scriptKindForFile(file) {
1506
+ const extension = path.extname(file).toLowerCase();
1507
+ if (extension === ".tsx")
1508
+ return typescript_1.default.ScriptKind.TSX;
1509
+ if ([".js", ".mjs", ".cjs"].includes(extension))
1510
+ return typescript_1.default.ScriptKind.JS;
1511
+ if (extension === ".jsx")
1512
+ return typescript_1.default.ScriptKind.JSX;
1513
+ return typescript_1.default.ScriptKind.TS;
1514
+ }
1515
+ function isRegularFile(file) {
1516
+ try {
1517
+ return fs.statSync(file).isFile();
1518
+ }
1519
+ catch {
1520
+ return false;
1521
+ }
1522
+ }
1523
+ function hashFiles(files) {
1524
+ const hash = crypto.createHash("sha256");
1525
+ for (const file of uniquePaths(files))
1526
+ hash.update(file).update("\0").update(fs.readFileSync(file)).update("\0");
1527
+ return hash.digest("hex");
1528
+ }
1529
+ function hashFile(file) {
1530
+ return crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex");
1531
+ }
1532
+ function uniquePaths(files) {
1533
+ return [...new Map(files.map((file) => [pathKey(file), path.normalize(file)])).values()].sort();
1534
+ }
1535
+ function isInside(root, file) {
1536
+ const relative = path.relative(root, path.resolve(file));
1537
+ return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
1538
+ }
1539
+ function samePath(left, right) {
1540
+ return pathKey(left) === pathKey(right);
1541
+ }
1542
+ function pathKey(file) {
1543
+ const normalized = path.normalize(file);
1544
+ return process.platform === "win32" ? normalized.toLowerCase() : normalized;
1545
+ }
1546
+ function errorMessage(error) {
1547
+ return error instanceof Error ? error.message : String(error);
1548
+ }
1549
+ function readErrorCode(error) {
1550
+ return error && typeof error === "object" && typeof error.code === "string"
1551
+ ? error.code
1552
+ : null;
1553
+ }