deadbyte-mcp 0.8.10 → 0.10.0

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 (388) hide show
  1. package/CONTEXT.md +41 -0
  2. package/MANIFEST.SHA256 +386 -94
  3. package/R34-BASELINE.json +9 -0
  4. package/README.txt +141 -10
  5. package/bench/fixtures/corpus.json +36 -0
  6. package/bench/fixtures/r36/case-map.json +8 -0
  7. package/bin/WORKER-REGISTRY.txt +3 -3
  8. package/bin/appcontainer-stage.exe +0 -0
  9. package/bin/appcontainer-stage.obj +0 -0
  10. package/bin/bootstrap-advapi32.exe +0 -0
  11. package/bin/bootstrap-advapi32.obj +0 -0
  12. package/bin/bootstrap-exitcode.exe +0 -0
  13. package/bin/bootstrap-exitcode.obj +0 -0
  14. package/bin/bootstrap-kernel32.exe +0 -0
  15. package/bin/bootstrap-kernel32.obj +0 -0
  16. package/bin/child-control-probe.exe +0 -0
  17. package/bin/child-control-probe.obj +0 -0
  18. package/bin/child-control-stage.exe +0 -0
  19. package/bin/child-control-stage.obj +0 -0
  20. package/bin/contained-reverse-worker.exe +0 -0
  21. package/bin/contained-reverse-worker.obj +0 -0
  22. package/bin/contained-transform-worker.exe +0 -0
  23. package/bin/contained-transform-worker.obj +0 -0
  24. package/bin/containment-probe.exe +0 -0
  25. package/bin/containment-probe.obj +0 -0
  26. package/bin/deadbyte-contain.exe +0 -0
  27. package/bin/deadbyte-contain.obj +0 -0
  28. package/bin/deadbyte-exec.exe +0 -0
  29. package/bin/deadbyte-exec.obj +0 -0
  30. package/bin/deadbyte-process-host.exe +0 -0
  31. package/bin/deadbyte-process-host.obj +0 -0
  32. package/bin/deadbyte-tunnel-host.exe +0 -0
  33. package/bin/deadbyte-tunnel-host.obj +0 -0
  34. package/controller/README.TXT +12 -4
  35. package/controller/deadbyte-controller.config.psd1.example +14 -0
  36. package/controller/deadbyte-controller.ps1 +191 -20
  37. package/controller/deadbyte-process-policy.json +5 -5
  38. package/controller/deadbyte-semantic-lsp-config.json +95 -0
  39. package/docs/ADR-0001-PRODUCTION-BASELINE-SEAMS.md +29 -0
  40. package/docs/ARCHITECTURE.md +6 -5
  41. package/docs/R36-CAPABILITY-EVIDENCE.md +43 -0
  42. package/docs/superpowers/plans/2026-09-16-deadbyte-loop-engine.md +846 -0
  43. package/docs/superpowers/plans/2026-09-17-r35-production-successor.md +408 -0
  44. package/docs/superpowers/plans/2026-09-18-r36-zero-loss-autonomy.md +739 -0
  45. package/docs/superpowers/specs/2026-09-16-deadbyte-loop-engine-design.md +435 -0
  46. package/docs/superpowers/specs/2026-09-17-r35-production-successor-design.md +220 -0
  47. package/docs/superpowers/specs/2026-09-18-r36-zero-loss-autonomy-design.md +640 -0
  48. package/node_modules/typescript/LICENSE.txt +55 -0
  49. package/node_modules/typescript/README.md +50 -0
  50. package/node_modules/typescript/SECURITY.md +41 -0
  51. package/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
  52. package/node_modules/typescript/bin/tsc +2 -0
  53. package/node_modules/typescript/bin/tsserver +2 -0
  54. package/node_modules/typescript/lib/_tsc.js +133818 -0
  55. package/node_modules/typescript/lib/_tsserver.js +659 -0
  56. package/node_modules/typescript/lib/_typingsInstaller.js +222 -0
  57. package/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +2122 -0
  58. package/node_modules/typescript/lib/de/diagnosticMessages.generated.json +2122 -0
  59. package/node_modules/typescript/lib/es/diagnosticMessages.generated.json +2122 -0
  60. package/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +2122 -0
  61. package/node_modules/typescript/lib/it/diagnosticMessages.generated.json +2122 -0
  62. package/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +2122 -0
  63. package/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +2122 -0
  64. package/node_modules/typescript/lib/lib.d.ts +22 -0
  65. package/node_modules/typescript/lib/lib.decorators.d.ts +384 -0
  66. package/node_modules/typescript/lib/lib.decorators.legacy.d.ts +22 -0
  67. package/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +41 -0
  68. package/node_modules/typescript/lib/lib.dom.d.ts +39429 -0
  69. package/node_modules/typescript/lib/lib.dom.iterable.d.ts +571 -0
  70. package/node_modules/typescript/lib/lib.es2015.collection.d.ts +147 -0
  71. package/node_modules/typescript/lib/lib.es2015.core.d.ts +597 -0
  72. package/node_modules/typescript/lib/lib.es2015.d.ts +28 -0
  73. package/node_modules/typescript/lib/lib.es2015.generator.d.ts +77 -0
  74. package/node_modules/typescript/lib/lib.es2015.iterable.d.ts +605 -0
  75. package/node_modules/typescript/lib/lib.es2015.promise.d.ts +81 -0
  76. package/node_modules/typescript/lib/lib.es2015.proxy.d.ts +128 -0
  77. package/node_modules/typescript/lib/lib.es2015.reflect.d.ts +144 -0
  78. package/node_modules/typescript/lib/lib.es2015.symbol.d.ts +46 -0
  79. package/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +326 -0
  80. package/node_modules/typescript/lib/lib.es2016.array.include.d.ts +116 -0
  81. package/node_modules/typescript/lib/lib.es2016.d.ts +21 -0
  82. package/node_modules/typescript/lib/lib.es2016.full.d.ts +23 -0
  83. package/node_modules/typescript/lib/lib.es2016.intl.d.ts +31 -0
  84. package/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +21 -0
  85. package/node_modules/typescript/lib/lib.es2017.d.ts +26 -0
  86. package/node_modules/typescript/lib/lib.es2017.date.d.ts +31 -0
  87. package/node_modules/typescript/lib/lib.es2017.full.d.ts +23 -0
  88. package/node_modules/typescript/lib/lib.es2017.intl.d.ts +44 -0
  89. package/node_modules/typescript/lib/lib.es2017.object.d.ts +49 -0
  90. package/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +135 -0
  91. package/node_modules/typescript/lib/lib.es2017.string.d.ts +45 -0
  92. package/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +53 -0
  93. package/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +77 -0
  94. package/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +53 -0
  95. package/node_modules/typescript/lib/lib.es2018.d.ts +24 -0
  96. package/node_modules/typescript/lib/lib.es2018.full.d.ts +24 -0
  97. package/node_modules/typescript/lib/lib.es2018.intl.d.ts +83 -0
  98. package/node_modules/typescript/lib/lib.es2018.promise.d.ts +30 -0
  99. package/node_modules/typescript/lib/lib.es2018.regexp.d.ts +37 -0
  100. package/node_modules/typescript/lib/lib.es2019.array.d.ts +79 -0
  101. package/node_modules/typescript/lib/lib.es2019.d.ts +24 -0
  102. package/node_modules/typescript/lib/lib.es2019.full.d.ts +24 -0
  103. package/node_modules/typescript/lib/lib.es2019.intl.d.ts +23 -0
  104. package/node_modules/typescript/lib/lib.es2019.object.d.ts +33 -0
  105. package/node_modules/typescript/lib/lib.es2019.string.d.ts +37 -0
  106. package/node_modules/typescript/lib/lib.es2019.symbol.d.ts +24 -0
  107. package/node_modules/typescript/lib/lib.es2020.bigint.d.ts +765 -0
  108. package/node_modules/typescript/lib/lib.es2020.d.ts +27 -0
  109. package/node_modules/typescript/lib/lib.es2020.date.d.ts +42 -0
  110. package/node_modules/typescript/lib/lib.es2020.full.d.ts +24 -0
  111. package/node_modules/typescript/lib/lib.es2020.intl.d.ts +474 -0
  112. package/node_modules/typescript/lib/lib.es2020.number.d.ts +28 -0
  113. package/node_modules/typescript/lib/lib.es2020.promise.d.ts +47 -0
  114. package/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +99 -0
  115. package/node_modules/typescript/lib/lib.es2020.string.d.ts +44 -0
  116. package/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +41 -0
  117. package/node_modules/typescript/lib/lib.es2021.d.ts +23 -0
  118. package/node_modules/typescript/lib/lib.es2021.full.d.ts +24 -0
  119. package/node_modules/typescript/lib/lib.es2021.intl.d.ts +166 -0
  120. package/node_modules/typescript/lib/lib.es2021.promise.d.ts +48 -0
  121. package/node_modules/typescript/lib/lib.es2021.string.d.ts +33 -0
  122. package/node_modules/typescript/lib/lib.es2021.weakref.d.ts +78 -0
  123. package/node_modules/typescript/lib/lib.es2022.array.d.ts +121 -0
  124. package/node_modules/typescript/lib/lib.es2022.d.ts +25 -0
  125. package/node_modules/typescript/lib/lib.es2022.error.d.ts +75 -0
  126. package/node_modules/typescript/lib/lib.es2022.full.d.ts +24 -0
  127. package/node_modules/typescript/lib/lib.es2022.intl.d.ts +145 -0
  128. package/node_modules/typescript/lib/lib.es2022.object.d.ts +26 -0
  129. package/node_modules/typescript/lib/lib.es2022.regexp.d.ts +39 -0
  130. package/node_modules/typescript/lib/lib.es2022.string.d.ts +25 -0
  131. package/node_modules/typescript/lib/lib.es2023.array.d.ts +924 -0
  132. package/node_modules/typescript/lib/lib.es2023.collection.d.ts +21 -0
  133. package/node_modules/typescript/lib/lib.es2023.d.ts +22 -0
  134. package/node_modules/typescript/lib/lib.es2023.full.d.ts +24 -0
  135. package/node_modules/typescript/lib/lib.es2023.intl.d.ts +56 -0
  136. package/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +65 -0
  137. package/node_modules/typescript/lib/lib.es2024.collection.d.ts +29 -0
  138. package/node_modules/typescript/lib/lib.es2024.d.ts +26 -0
  139. package/node_modules/typescript/lib/lib.es2024.full.d.ts +24 -0
  140. package/node_modules/typescript/lib/lib.es2024.object.d.ts +29 -0
  141. package/node_modules/typescript/lib/lib.es2024.promise.d.ts +35 -0
  142. package/node_modules/typescript/lib/lib.es2024.regexp.d.ts +25 -0
  143. package/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +68 -0
  144. package/node_modules/typescript/lib/lib.es2024.string.d.ts +29 -0
  145. package/node_modules/typescript/lib/lib.es5.d.ts +4601 -0
  146. package/node_modules/typescript/lib/lib.es6.d.ts +23 -0
  147. package/node_modules/typescript/lib/lib.esnext.array.d.ts +35 -0
  148. package/node_modules/typescript/lib/lib.esnext.collection.d.ts +96 -0
  149. package/node_modules/typescript/lib/lib.esnext.d.ts +29 -0
  150. package/node_modules/typescript/lib/lib.esnext.decorators.d.ts +28 -0
  151. package/node_modules/typescript/lib/lib.esnext.disposable.d.ts +193 -0
  152. package/node_modules/typescript/lib/lib.esnext.error.d.ts +24 -0
  153. package/node_modules/typescript/lib/lib.esnext.float16.d.ts +445 -0
  154. package/node_modules/typescript/lib/lib.esnext.full.d.ts +24 -0
  155. package/node_modules/typescript/lib/lib.esnext.intl.d.ts +21 -0
  156. package/node_modules/typescript/lib/lib.esnext.iterator.d.ts +148 -0
  157. package/node_modules/typescript/lib/lib.esnext.promise.d.ts +34 -0
  158. package/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +25 -0
  159. package/node_modules/typescript/lib/lib.scripthost.d.ts +322 -0
  160. package/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +41 -0
  161. package/node_modules/typescript/lib/lib.webworker.d.ts +13150 -0
  162. package/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +23 -0
  163. package/node_modules/typescript/lib/lib.webworker.iterable.d.ts +340 -0
  164. package/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +2122 -0
  165. package/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +2122 -0
  166. package/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +2122 -0
  167. package/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +2122 -0
  168. package/node_modules/typescript/lib/tsc.js +8 -0
  169. package/node_modules/typescript/lib/tsserver.js +8 -0
  170. package/node_modules/typescript/lib/tsserverlibrary.d.ts +17 -0
  171. package/node_modules/typescript/lib/tsserverlibrary.js +21 -0
  172. package/node_modules/typescript/lib/typesMap.json +497 -0
  173. package/node_modules/typescript/lib/typescript.d.ts +11437 -0
  174. package/node_modules/typescript/lib/typescript.js +200276 -0
  175. package/node_modules/typescript/lib/typingsInstaller.js +8 -0
  176. package/node_modules/typescript/lib/watchGuard.js +53 -0
  177. package/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +2122 -0
  178. package/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +2122 -0
  179. package/node_modules/typescript/package.json +120 -0
  180. package/package.json +5 -3
  181. package/proof/CONTAINMENT-BUILD.txt +6 -6
  182. package/proof/R34-TASK8-SUPERVISOR-CHECKPOINT.json +29 -0
  183. package/proof/R34-TASK9-MCP-SURFACE-CHECKPOINT.json +28 -0
  184. package/scripts/capability-benchmark.mjs +27 -0
  185. package/scripts/deferred-slot-operation.mjs +56 -16
  186. package/scripts/final-closure-verify.mjs +88 -39
  187. package/scripts/final-closure.mjs +63 -56
  188. package/scripts/gate-windows.ps1 +3 -3
  189. package/scripts/release-parity-tests.ps1 +9 -0
  190. package/scripts/release-parity.mjs +149 -139
  191. package/scripts/semantic-preflight.ps1 +73 -0
  192. package/scripts/tool-surface-snapshot.mjs +73 -0
  193. package/scripts/windows-gate-evidence.mjs +5 -5
  194. package/src/audit-verify.mjs +6 -2
  195. package/src/autonomous-action-reconcile.mjs +142 -0
  196. package/src/autonomous-context-engine.mjs +256 -0
  197. package/src/autonomous-live-state.mjs +17 -0
  198. package/src/autonomous-local-supervisor.mjs +249 -0
  199. package/src/autonomous-loop-state.mjs +304 -0
  200. package/src/autonomous-mcp-tools.mjs +5 -1
  201. package/src/autonomous-output-contracts.mjs +26 -7
  202. package/src/autonomous-plan.mjs +181 -0
  203. package/src/autonomous-planner-contracts.mjs +79 -0
  204. package/src/autonomous-planner.mjs +113 -6
  205. package/src/autonomous-policy.mjs +15 -2
  206. package/src/autonomous-progress.mjs +127 -0
  207. package/src/autonomous-runtime.mjs +785 -62
  208. package/src/autonomous-supervisor-host.mjs +70 -0
  209. package/src/autonomous-supervisor.mjs +31 -8
  210. package/src/capability-benchmark-runner.mjs +193 -0
  211. package/src/capability-benchmark.mjs +95 -0
  212. package/src/capability-ledger.mjs +158 -0
  213. package/src/coding-mcp-tools.mjs +65 -8
  214. package/src/coding-output-contracts.mjs +91 -8
  215. package/src/coding-plane.mjs +45 -9
  216. package/src/coding-search.mjs +130 -47
  217. package/src/compact-gateway-mcp-tools.mjs +128 -0
  218. package/src/compact-gateway-output-contracts.mjs +16 -0
  219. package/src/context-provenance.mjs +86 -0
  220. package/src/deadbyte-cli.mjs +145 -30
  221. package/src/document-adapter.mjs +43 -0
  222. package/src/lsp-stdio-client.mjs +112 -0
  223. package/src/machine-fs-smoke-client.mjs +2 -1
  224. package/src/machine-fs.mjs +51 -8
  225. package/src/mcp-server.mjs +46 -9
  226. package/src/native-diff-v2.mjs +337 -0
  227. package/src/native-diff.mjs +50 -2
  228. package/src/observation-smoke-client.mjs +3 -2
  229. package/src/operator-surface.mjs +43 -0
  230. package/src/process-runtime.mjs +98 -11
  231. package/src/process-smoke-client.mjs +11 -3
  232. package/src/provider-circuit.mjs +125 -0
  233. package/src/r36-compact-disarmed-probe.mjs +50 -0
  234. package/src/r36-full-surface-probe.mjs +56 -0
  235. package/src/release-generation.mjs +44 -5
  236. package/src/remote-live-log.mjs +76 -0
  237. package/src/remote-mcp-autonomous-smoke-client.mjs +58 -15
  238. package/src/remote-mcp-coding-smoke-client.mjs +5 -4
  239. package/src/remote-mcp-r24-disarmed-smoke-client.mjs +4 -2
  240. package/src/remote-mcp-r34-parity-client.mjs +177 -0
  241. package/src/remote-mcp-r36-parity-client.mjs +175 -0
  242. package/src/remote-mcp-smoke-client.mjs +113 -56
  243. package/src/remote-result-journal.mjs +114 -0
  244. package/src/runtime-update.mjs +109 -9
  245. package/src/search-cursor.mjs +45 -0
  246. package/src/semantic-backend-registry.mjs +39 -0
  247. package/src/semantic-code.mjs +246 -0
  248. package/src/semantic-lsp-backend.mjs +219 -0
  249. package/src/semantic-lsp-config.mjs +112 -0
  250. package/src/tool-surface-ledger.mjs +92 -0
  251. package/src/version.mjs +1 -1
  252. package/test/audit-verify.test.mjs +1 -1
  253. package/test/autonomous-action-reconcile.test.mjs +106 -0
  254. package/test/autonomous-adversarial.test.mjs +149 -6
  255. package/test/autonomous-capability-r36.test.mjs +151 -0
  256. package/test/autonomous-context-engine.test.mjs +181 -0
  257. package/test/autonomous-live-state.test.mjs +27 -0
  258. package/test/autonomous-local-supervisor.test.mjs +403 -0
  259. package/test/autonomous-loop-state.test.mjs +126 -0
  260. package/test/autonomous-loop-v2.test.mjs +105 -0
  261. package/test/autonomous-loop.test.mjs +79 -1
  262. package/test/autonomous-output-contract.test.mjs +54 -0
  263. package/test/autonomous-plan.test.mjs +101 -0
  264. package/test/autonomous-progress.test.mjs +106 -0
  265. package/test/autonomous-r34-e2e.test.mjs +338 -0
  266. package/test/autonomous-runtime.test.mjs +3 -3
  267. package/test/autonomous-supervisor-integration.test.mjs +48 -3
  268. package/test/capability-benchmark-r36.test.mjs +107 -0
  269. package/test/capability-benchmark-runner.test.mjs +49 -0
  270. package/test/capability-benchmark-semantic-r36.test.mjs +52 -0
  271. package/test/capability-benchmark.test.mjs +47 -0
  272. package/test/capability-claims-r36.test.mjs +23 -0
  273. package/test/capability-ledger-r36.test.mjs +102 -0
  274. package/test/cli-entrypoint.test.mjs +12 -0
  275. package/test/coding-catalog-consistency.test.mjs +24 -0
  276. package/test/coding-plane.test.mjs +3 -3
  277. package/test/coding-runtime.test.mjs +16 -0
  278. package/test/coding-search-r36.test.mjs +90 -0
  279. package/test/compact-catalog-r36.test.mjs +37 -0
  280. package/test/compact-gateway-r36.test.mjs +66 -0
  281. package/test/contained.test.mjs +1 -1
  282. package/test/context-provenance.test.mjs +61 -0
  283. package/test/controller-r27.test.mjs +4 -3
  284. package/test/controller.test.mjs +52 -0
  285. package/test/core.test.mjs +1 -1
  286. package/test/deferred-slot-operation-behavior.test.mjs +5 -1
  287. package/test/deferred-slot-operation.test.mjs +11 -1
  288. package/test/document-adapter.test.mjs +23 -0
  289. package/test/fixtures/lsp-framed-server.mjs +35 -0
  290. package/test/fixtures/semantic/cpp/compile_commands.json +4 -0
  291. package/test/fixtures/semantic/cpp/lib.cpp +2 -0
  292. package/test/fixtures/semantic/cpp/lib.hpp +2 -0
  293. package/test/fixtures/semantic/cpp/main.cpp +2 -0
  294. package/test/fixtures/semantic/python/lib.py +2 -0
  295. package/test/fixtures/semantic/python/main.py +2 -0
  296. package/test/fixtures/semantic/rust/Cargo.lock +7 -0
  297. package/test/fixtures/semantic/rust/Cargo.toml +8 -0
  298. package/test/fixtures/semantic/rust/src/lib.rs +3 -0
  299. package/test/fixtures/semantic/rust/src/main.rs +5 -0
  300. package/test/fixtures/semantic/rust/src/math.rs +3 -0
  301. package/test/fixtures/semantic/rust/target/.rustc_info.json +1 -0
  302. package/test/fixtures/semantic/rust/target/CACHEDIR.TAG +3 -0
  303. package/test/fixtures/semantic/rust/target/debug/.cargo-lock +0 -0
  304. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/dep-test-lib-semantic_rust +0 -0
  305. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/invoked.timestamp +1 -0
  306. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/test-lib-semantic_rust +1 -0
  307. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/test-lib-semantic_rust.json +1 -0
  308. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/dep-test-bin-semantic_rust_bin +0 -0
  309. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/invoked.timestamp +1 -0
  310. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/test-bin-semantic_rust_bin +1 -0
  311. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/test-bin-semantic_rust_bin.json +1 -0
  312. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/dep-lib-semantic_rust +0 -0
  313. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/invoked.timestamp +1 -0
  314. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/lib-semantic_rust +1 -0
  315. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/lib-semantic_rust.json +1 -0
  316. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/bin-semantic_rust_bin +1 -0
  317. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/bin-semantic_rust_bin.json +1 -0
  318. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/dep-bin-semantic_rust_bin +0 -0
  319. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/invoked.timestamp +1 -0
  320. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust-4c168fa33c79d09c.rmeta +0 -0
  321. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust-6212ccd976aa3808.rmeta +0 -0
  322. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust_bin-5dcd474439c54a26.rmeta +0 -0
  323. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust_bin-d741378dccdef61c.rmeta +0 -0
  324. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust-4c168fa33c79d09c.d +5 -0
  325. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust-6212ccd976aa3808.d +5 -0
  326. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust_bin-5dcd474439c54a26.d +6 -0
  327. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust_bin-d741378dccdef61c.d +6 -0
  328. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/dep-graph.bin +0 -0
  329. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/query-cache.bin +0 -0
  330. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/work-products.bin +0 -0
  331. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc.lock +0 -0
  332. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/dep-graph.bin +0 -0
  333. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/metadata.rmeta +0 -0
  334. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/query-cache.bin +0 -0
  335. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/work-products.bin +0 -0
  336. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq.lock +0 -0
  337. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/dep-graph.bin +0 -0
  338. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/query-cache.bin +0 -0
  339. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/work-products.bin +0 -0
  340. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3.lock +0 -0
  341. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/dep-graph.bin +0 -0
  342. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/query-cache.bin +0 -0
  343. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/work-products.bin +0 -0
  344. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt.lock +0 -0
  345. package/test/fixtures/semantic/rust/target/flycheck0/stderr +1 -0
  346. package/test/fixtures/semantic/rust/target/flycheck0/stdout +5 -0
  347. package/test/fixtures/semantic/typescript/lib.ts +3 -0
  348. package/test/fixtures/semantic/typescript/main.ts +2 -0
  349. package/test/fixtures/tool-surface-stdio-server.mjs +14 -0
  350. package/test/helpers/autonomous-r34-fixture.mjs +122 -0
  351. package/test/lsp-stdio-client.test.mjs +72 -0
  352. package/test/multi-file-read.test.mjs +44 -0
  353. package/test/native-diff-topology-r36.test.mjs +105 -0
  354. package/test/observation-integration.test.mjs +3 -3
  355. package/test/package-boundary.test.mjs +6 -0
  356. package/test/process-longrun-r36.test.mjs +82 -0
  357. package/test/process-release-gate.test.mjs +9 -0
  358. package/test/production-docs.test.mjs +48 -0
  359. package/test/prompts-resources.test.mjs +41 -0
  360. package/test/provider-circuit.test.mjs +93 -0
  361. package/test/public-autonomous-ingress-budget.test.mjs +28 -0
  362. package/test/r33-closeout-regression.test.mjs +4 -3
  363. package/test/r33-finalization.test.mjs +26 -18
  364. package/test/r36-finalization.test.mjs +104 -0
  365. package/test/r36-release-identity.test.mjs +52 -0
  366. package/test/release-generation.test.mjs +23 -2
  367. package/test/release-version.test.mjs +27 -17
  368. package/test/remote-live-log-r36.test.mjs +37 -0
  369. package/test/remote-live-log-recovery-r36.test.mjs +41 -0
  370. package/test/remote-r24-catalog.test.mjs +18 -4
  371. package/test/remote-result-journal.test.mjs +58 -0
  372. package/test/remote-session-cli.test.mjs +135 -30
  373. package/test/runtime-self-update.test.mjs +121 -1
  374. package/test/semantic-backend-registry.test.mjs +29 -0
  375. package/test/semantic-code.test.mjs +66 -0
  376. package/test/semantic-lsp-backend.test.mjs +108 -0
  377. package/test/semantic-lsp-config.test.mjs +81 -0
  378. package/test/semantic-lsp-readiness.test.mjs +34 -0
  379. package/test/semantic-lsp-transient-empty.test.mjs +32 -0
  380. package/test/semantic-lsp-transient-null.test.mjs +31 -0
  381. package/test/semantic-multilang.test.mjs +72 -0
  382. package/test/semantic-r36-rename.test.mjs +82 -0
  383. package/test/semantic-runtime-routing.test.mjs +32 -0
  384. package/test/semantic-server-config-integration.test.mjs +66 -0
  385. package/test/tool-surface-ledger.test.mjs +59 -0
  386. package/test/tool-surface-snapshot.test.mjs +17 -0
  387. package/test/tracer-bullet.test.mjs +77 -0
  388. package/deadbyte-mcp-0.8.9.tgz +0 -0
@@ -0,0 +1,39 @@
1
+ import path from 'node:path';
2
+
3
+ const REQUIRED_METHODS=['outline','definition','references','replaceSymbol','diagnostics'];
4
+
5
+ function normalizeExtension(value){
6
+ if(typeof value!=='string'||value.length<2||!value.startsWith('.')) throw new Error(`invalid semantic extension: ${String(value)}`);
7
+ return value.toLowerCase();
8
+ }
9
+
10
+ export function createSemanticBackendRegistry({backends}){
11
+ if(!Array.isArray(backends)||backends.length<1) throw new Error('semantic backend registry requires backends');
12
+ const ids=new Set();
13
+ const byExtension=new Map();
14
+ const normalized=[];
15
+ for(const backend of backends){
16
+ if(!backend||typeof backend!=='object'||Array.isArray(backend)) throw new Error('semantic backend must be an object');
17
+ if(typeof backend.id!=='string'||backend.id.length<1) throw new Error('semantic backend id missing');
18
+ if(ids.has(backend.id)) throw new Error(`duplicate semantic backend id: ${backend.id}`);
19
+ ids.add(backend.id);
20
+ if(!(backend.extensions instanceof Set)||backend.extensions.size<1) throw new Error(`semantic backend ${backend.id} extensions missing`);
21
+ for(const method of REQUIRED_METHODS) if(typeof backend[method]!=='function') throw new Error(`semantic backend ${backend.id} missing method ${method}`);
22
+ const extensions=[...backend.extensions].map(normalizeExtension).sort();
23
+ for(const ext of extensions){
24
+ if(byExtension.has(ext)) throw new Error(`semantic extension ${ext} already owned by ${byExtension.get(ext).id}`);
25
+ byExtension.set(ext,backend);
26
+ }
27
+ normalized.push({id:backend.id,extensions});
28
+ }
29
+ normalized.sort((a,b)=>a.id.localeCompare(b.id,'en'));
30
+ return Object.freeze({
31
+ backendForPath(relativePath){
32
+ const ext=path.extname(String(relativePath)).toLowerCase();
33
+ const backend=byExtension.get(ext);
34
+ if(!backend) throw new Error(`unsupported semantic language: ${ext||'<none>'}`);
35
+ return backend;
36
+ },
37
+ languages(){return normalized.map(item=>({id:item.id,extensions:[...item.extensions]}));}
38
+ });
39
+ }
@@ -0,0 +1,246 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { readFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import * as ts from 'typescript';
5
+ import { createSemanticBackendRegistry } from './semantic-backend-registry.mjs';
6
+
7
+ const SOURCE_EXTENSIONS=new Set(['.ts','.tsx','.mts','.cts','.js','.jsx','.mjs','.cjs']);
8
+ const MAX_PROJECT_ENTRIES=2000;
9
+ const MAX_SOURCE_FILES=1000;
10
+
11
+ function digest(value){return createHash('sha256').update(JSON.stringify(value)).digest('hex');}
12
+ function relNormalized(value){return value.replaceAll('\\','/').replace(/^\.\//,'');}
13
+ function inside(root,target){const rel=path.relative(root,target);return rel===''||(!rel.startsWith(`..${path.sep}`)&&rel!=='..'&&!path.isAbsolute(rel));}
14
+ function denied(root,absolute){
15
+ if(!inside(root.real_path,absolute)) return true;
16
+ const rel=relNormalized(path.relative(root.real_path,absolute)).toLowerCase();
17
+ return root.deny_paths.some(item=>rel===item||rel.startsWith(`${item}/`));
18
+ }
19
+ function sourceExtension(file){return SOURCE_EXTENSIONS.has(path.extname(file).toLowerCase());}
20
+ function defaultOptions(){return {target:ts.ScriptTarget.ES2022,module:ts.ModuleKind.NodeNext,moduleResolution:ts.ModuleResolutionKind.NodeNext,allowJs:true,checkJs:true,strict:false,noEmit:true,jsx:ts.JsxEmit.Preserve,resolveJsonModule:true,skipLibCheck:true};}
21
+ function parseOptions(configText,rootPath){
22
+ if(!configText) return defaultOptions();
23
+ const parsed=ts.parseConfigFileTextToJson(path.join(rootPath,'tsconfig.json'),configText);
24
+ if(parsed.error) return defaultOptions();
25
+ const converted=ts.convertCompilerOptionsFromJson(parsed.config?.compilerOptions??{},rootPath);
26
+ return {...defaultOptions(),...converted.options,noEmit:true};
27
+ }
28
+ function lineColumn(source,pos){const p=source.getLineAndCharacterOfPosition(Math.max(0,Math.min(pos,source.getFullWidth())));return {line:p.line,column:p.character};}
29
+ function locationFromSpan(project,fileName,textSpan,name='',kind='unknown'){
30
+ const absolute=path.resolve(fileName);
31
+ if(!inside(project.root.real_path,absolute)||denied(project.root,absolute)) return null;
32
+ const source=project.service.getProgram()?.getSourceFile(absolute);
33
+ if(!source) return null;
34
+ const start=lineColumn(source,textSpan.start); const end=lineColumn(source,textSpan.start+textSpan.length);
35
+ return {path:relNormalized(path.relative(project.root.real_path,absolute)),name:String(name||''),kind:String(kind||'unknown'),start_line:start.line,start_column:start.column,end_line:end.line,end_column:end.column};
36
+ }
37
+ async function buildProject(codingRuntime,rootId){
38
+ const status=await codingRuntime.sessionStatus();
39
+ if(!status.armed) throw new Error(`coding plane is disarmed: ${status.reason}`);
40
+ if(!status.root_ids.includes(rootId)) throw new Error(`coding root '${rootId}' is outside active lease`);
41
+ const root=codingRuntime.policy.roots[rootId];
42
+ if(!root||root.read!==true) throw new Error(`coding root '${rootId}' does not allow read`);
43
+ const tree=await codingRuntime.tree({rootId,path:'.',maxDepth:12,maxEntries:MAX_PROJECT_ENTRIES});
44
+ if(tree.truncated) throw new Error(`semantic project exceeds ${MAX_PROJECT_ENTRIES} entry bound; use a narrower coding root`);
45
+ const relativeFiles=tree.entries.filter(item=>item.type==='file'&&sourceExtension(item.path)).map(item=>item.path);
46
+ if(relativeFiles.length>MAX_SOURCE_FILES) throw new Error(`semantic project exceeds ${MAX_SOURCE_FILES} source file bound`);
47
+ const files=relativeFiles.map(rel=>path.join(root.real_path,...rel.split('/')));
48
+ let configText='';
49
+ if(tree.entries.some(item=>item.type==='file'&&item.path==='tsconfig.json')) configText=await readFile(path.join(root.real_path,'tsconfig.json'),'utf8');
50
+ const options=parseOptions(configText,root.real_path);
51
+ const versions=new Map(files.map(file=>[path.resolve(file),'1']));
52
+ const tsLibRoot=path.dirname(ts.getDefaultLibFilePath(options));
53
+ const allowedRead=file=>{
54
+ const absolute=path.resolve(file);
55
+ if(inside(tsLibRoot,absolute)) return true;
56
+ return inside(root.real_path,absolute)&&!denied(root,absolute);
57
+ };
58
+ const host={
59
+ getScriptFileNames:()=>files,
60
+ getScriptVersion:file=>versions.get(path.resolve(file))??'1',
61
+ getScriptSnapshot:file=>{if(!allowedRead(file))return undefined;const text=ts.sys.readFile(file);return text===undefined?undefined:ts.ScriptSnapshot.fromString(text);},
62
+ getCurrentDirectory:()=>root.real_path,
63
+ getCompilationSettings:()=>options,
64
+ getDefaultLibFileName:opts=>ts.getDefaultLibFilePath(opts),
65
+ fileExists:file=>allowedRead(file)&&ts.sys.fileExists(file),
66
+ readFile:file=>allowedRead(file)?ts.sys.readFile(file):undefined,
67
+ readDirectory:(dir,extensions,excludes,includes,depth)=>inside(root.real_path,path.resolve(dir))?ts.sys.readDirectory(dir,extensions,excludes,includes,depth):[],
68
+ directoryExists:dir=>allowedRead(path.join(dir,'_probe'))&&ts.sys.directoryExists?.(dir),
69
+ getDirectories:dir=>inside(root.real_path,path.resolve(dir))?(ts.sys.getDirectories?.(dir)??[]):[],
70
+ useCaseSensitiveFileNames:()=>ts.sys.useCaseSensitiveFileNames,
71
+ getNewLine:()=>ts.sys.newLine
72
+ };
73
+ const service=ts.createLanguageService(host,ts.createDocumentRegistry());
74
+ return {root,files,service,options};
75
+ }
76
+ function targetFile(project,relativePath){
77
+ const absolute=path.resolve(project.root.real_path,...relNormalized(relativePath).split('/'));
78
+ if(!inside(project.root.real_path,absolute)||denied(project.root,absolute)||!sourceExtension(absolute)) throw new Error('semantic target must be an allowed JS/TS source file');
79
+ const source=project.service.getProgram()?.getSourceFile(absolute);
80
+ if(!source) throw new Error(`semantic source unavailable: ${relativePath}`);
81
+ return {absolute,source};
82
+ }
83
+ function offsetAt(source,line,column){
84
+ if(!Number.isInteger(line)||line<0||!Number.isInteger(column)||column<0) throw new Error('line and column must be non-negative integers');
85
+ if(line>=source.getLineStarts().length) throw new Error('line is outside source file');
86
+ const lineStart=source.getPositionOfLineAndCharacter(line,0);
87
+ const lineEnd=line+1<source.getLineStarts().length?source.getPositionOfLineAndCharacter(line+1,0):source.getFullWidth();
88
+ const pos=lineStart+column;
89
+ if(pos>lineEnd) throw new Error('column is outside source line');
90
+ return pos;
91
+ }
92
+ function flattenNavigation(project,target,fileSha,maxSymbols){
93
+ const tree=project.service.getNavigationTree(target.absolute);
94
+ const out=[];
95
+ const visit=(item,container='')=>{
96
+ if(out.length>=maxSymbols) return;
97
+ const span=item.spans?.[0];
98
+ if(span&&item.text&&item.text!=='<global>'){
99
+ const loc=locationFromSpan(project,target.absolute,span,item.text,item.kind);
100
+ if(loc){
101
+ const nameSpan=item.nameSpan??span; const nameLoc=locationFromSpan(project,target.absolute,nameSpan,item.text,item.kind)??loc;
102
+ const symbolId=digest({schema:'deadbyte.semantic-symbol.v1',backend:'typescript',path:loc.path,file_sha256:fileSha,name:item.text,kind:item.kind,start:span.start,length:span.length});
103
+ out.push({...loc,symbol_id:symbolId,container_name:container,name_start_line:nameLoc.start_line,name_start_column:nameLoc.start_column,_span:span});
104
+ }
105
+ }
106
+ for(const child of item.childItems??[]) visit(child,item.text&&item.text!=='<global>'?item.text:container);
107
+ };
108
+ visit(tree,'');
109
+ return {symbols:out.slice(0,maxSymbols),truncated:out.length>=maxSymbols};
110
+ }
111
+ function diagnosticCategory(category){return ts.DiagnosticCategory[category]?.toLowerCase?.()??'unknown';}
112
+
113
+ export function createTypeScriptSemanticBackend({codingRuntime}){
114
+ if(!codingRuntime) throw new Error('TypeScript semantic backend requires coding runtime');
115
+ async function outline({rootId,relativePath,maxSymbols=200}){
116
+ if(!Number.isInteger(maxSymbols)||maxSymbols<1||maxSymbols>500) throw new Error('max_symbols must be in [1, 500]');
117
+ const file=await codingRuntime.fileRead({rootId,relativePath,encoding:'utf8'});
118
+ const project=await buildProject(codingRuntime,rootId); const target=targetFile(project,relativePath);
119
+ const flat=flattenNavigation(project,target,file.sha256,maxSymbols);
120
+ return {status:'ok',root_id:rootId,path:relativePath,file_sha256:file.sha256,engine:`typescript-${ts.version}`,symbols:flat.symbols.map(({_span,...x})=>x),truncated:flat.truncated};
121
+ }
122
+ async function definition({rootId,relativePath,line,column,maxResults=50}){
123
+ if(!Number.isInteger(maxResults)||maxResults<1||maxResults>200) throw new Error('max_results must be in [1, 200]');
124
+ await codingRuntime.fileRead({rootId,relativePath,encoding:'utf8'});
125
+ const project=await buildProject(codingRuntime,rootId); const target=targetFile(project,relativePath); const pos=offsetAt(target.source,line,column);
126
+ const defs=project.service.getDefinitionAtPosition(target.absolute,pos)??[];
127
+ const locations=defs.map(item=>locationFromSpan(project,item.fileName,item.textSpan,item.name,item.kind)).filter(Boolean).slice(0,maxResults);
128
+ return {status:'ok',root_id:rootId,path:relativePath,line,column,engine:`typescript-${ts.version}`,locations,truncated:defs.length>maxResults};
129
+ }
130
+ async function references({rootId,relativePath,line,column,maxResults=200}){
131
+ if(!Number.isInteger(maxResults)||maxResults<1||maxResults>500) throw new Error('max_results must be in [1, 500]');
132
+ await codingRuntime.fileRead({rootId,relativePath,encoding:'utf8'});
133
+ const project=await buildProject(codingRuntime,rootId); const target=targetFile(project,relativePath); const pos=offsetAt(target.source,line,column);
134
+ const refs=project.service.getReferencesAtPosition(target.absolute,pos)??[];
135
+ const locations=refs.map(item=>locationFromSpan(project,item.fileName,item.textSpan,'','reference')).filter(Boolean).slice(0,maxResults);
136
+ return {status:'ok',root_id:rootId,path:relativePath,line,column,engine:`typescript-${ts.version}`,locations,truncated:refs.length>maxResults};
137
+ }
138
+ async function replaceSymbol({rootId,relativePath,symbolId,newBody,expectedSha256}){
139
+ if(typeof newBody!=='string'||newBody.length>524288) throw new Error('new_body exceeds 524288 characters');
140
+ const file=await codingRuntime.fileRead({rootId,relativePath,encoding:'utf8'});
141
+ if(file.sha256!==expectedSha256) throw new Error(`semantic replace precondition mismatch: expected ${expectedSha256}, found ${file.sha256}`);
142
+ const project=await buildProject(codingRuntime,rootId); const target=targetFile(project,relativePath);
143
+ const flat=flattenNavigation(project,target,file.sha256,500);
144
+ const symbol=flat.symbols.find(item=>item.symbol_id===symbolId);
145
+ if(!symbol) throw new Error('semantic symbol_id is stale or unknown for current file');
146
+ const oldBody=target.source.text.slice(symbol._span.start,symbol._span.start+symbol._span.length);
147
+ const result=await codingRuntime.textReplace({rootId,relativePath,oldString:oldBody,newString:newBody,expectedSha256,expectedReplacements:1});
148
+ return {...result,symbol_id:symbolId,symbol_name:symbol.name,engine:`typescript-${ts.version}`};
149
+ }
150
+ async function diagnostics({rootId,relativePath,maxResults=200}){
151
+ if(!Number.isInteger(maxResults)||maxResults<1||maxResults>500) throw new Error('max_results must be in [1, 500]');
152
+ const file=await codingRuntime.fileRead({rootId,relativePath,encoding:'utf8'});
153
+ const project=await buildProject(codingRuntime,rootId); const target=targetFile(project,relativePath);
154
+ const all=[...project.service.getSyntacticDiagnostics(target.absolute),...project.service.getSemanticDiagnostics(target.absolute)];
155
+ const diagnosticsOut=all.slice(0,maxResults).map(item=>{
156
+ const span=Number.isInteger(item.start)&&Number.isInteger(item.length)?{start:item.start,length:item.length}:{start:0,length:0};
157
+ const loc=locationFromSpan(project,target.absolute,span,'','diagnostic');
158
+ return {message:ts.flattenDiagnosticMessageText(item.messageText,'\n'),code:String(item.code),severity:diagnosticCategory(item.category),...(loc?{location:loc}:{})};
159
+ });
160
+ const stable={root_id:rootId,path:relativePath,file_sha256:file.sha256,engine:`typescript-${ts.version}`,diagnostics:diagnosticsOut,truncated:all.length>maxResults};
161
+ return {status:'ok',...stable,result_sha256:digest({schema:'deadbyte.semantic-diagnostics.v1',...stable})};
162
+ }
163
+ async function implementations({rootId,relativePath,line,column,maxResults=200}){
164
+ if(!Number.isInteger(maxResults)||maxResults<1||maxResults>500) throw new Error('max_results must be in [1, 500]');
165
+ const file=await codingRuntime.fileRead({rootId,relativePath,encoding:'utf8'});
166
+ const project=await buildProject(codingRuntime,rootId); const target=targetFile(project,relativePath); const pos=offsetAt(target.source,line,column);
167
+ const raw=project.service.getImplementationAtPosition(target.absolute,pos)??[];
168
+ const locations=raw.map(item=>locationFromSpan(project,item.fileName,item.textSpan,item.name??'',item.kind??'implementation')).filter(Boolean).slice(0,maxResults);
169
+ const stable={root_id:rootId,path:relativePath,line,column,file_sha256:file.sha256,engine:`typescript-${ts.version}`,locations,truncated:raw.length>maxResults};
170
+ return {status:'ok',...stable,result_sha256:digest({schema:'deadbyte.semantic-implementations.v1',...stable})};
171
+ }
172
+ async function renameEdits({rootId,relativePath,line,column,newName}){
173
+ const file=await codingRuntime.fileRead({rootId,relativePath,encoding:'utf8'});
174
+ const project=await buildProject(codingRuntime,rootId); const target=targetFile(project,relativePath); const pos=offsetAt(target.source,line,column);
175
+ const info=project.service.getRenameInfo(target.absolute,pos,{allowRenameOfImportPath:false});
176
+ if(!info?.canRename) throw new Error(`semantic rename unavailable: ${info?.localizedErrorMessage??'symbol cannot be renamed'}`);
177
+ const raw=project.service.findRenameLocations(target.absolute,pos,false,false,true)??[];
178
+ if(raw.length<1) throw new Error('semantic rename produced no locations');
179
+ const edits=[];
180
+ for(const item of raw){
181
+ const loc=locationFromSpan(project,item.fileName,item.textSpan,'','rename');
182
+ if(!loc) continue;
183
+ edits.push({path:loc.path,start:item.textSpan.start,length:item.textSpan.length,new_text:`${item.prefixText??''}${newName}${item.suffixText??''}`});
184
+ }
185
+ if(edits.length<1) throw new Error('semantic rename produced no allowed edits');
186
+ edits.sort((a,b)=>a.path.localeCompare(b.path,'en')||a.start-b.start||a.length-b.length);
187
+ return {status:'ok',root_id:rootId,path:relativePath,engine:`typescript-${ts.version}`,target_file_sha256:file.sha256,edits};
188
+ }
189
+ return Object.freeze({id:'typescript',extensions:new Set(SOURCE_EXTENSIONS),outline,definition,references,replaceSymbol,diagnostics,implementations,renameEdits});
190
+ }
191
+
192
+ export function createSemanticCodeRuntime({codingRuntime,backends=[],nativeDiffRuntime=null}){
193
+ if(!codingRuntime) throw new Error('semantic runtime requires coding runtime');
194
+ if(!Array.isArray(backends)) throw new Error('semantic runtime backends must be an array');
195
+ const typescript=createTypeScriptSemanticBackend({codingRuntime});
196
+ const registry=createSemanticBackendRegistry({backends:[typescript,...backends]});
197
+ const backendFor=args=>registry.backendForPath(args.relativePath);
198
+ const route=(method,args)=>{
199
+ const backend=backendFor(args);
200
+ if(typeof backend[method]!=='function') return {status:'unsupported',capability:method,engine:backend.id};
201
+ return backend[method](args);
202
+ };
203
+ async function renamePreview({rootId,relativePath,line,column,newName}){
204
+ if(typeof newName!=='string'||!/^[A-Za-z_$][A-Za-z0-9_$]{0,127}$/.test(newName)) throw new Error('semantic rename new name must be a valid bounded identifier');
205
+ if(!nativeDiffRuntime||typeof nativeDiffRuntime.preview!=='function') throw new Error('semantic rename preview requires Native Diff runtime');
206
+ const backend=backendFor({relativePath});
207
+ if(typeof backend.renameEdits!=='function') return {status:'unsupported',capability:'rename_preview',engine:backend.id};
208
+ const plan=await backend.renameEdits({rootId,relativePath,line,column,newName});
209
+ if(plan?.status==='unsupported') return plan;
210
+ if(!plan||plan.status!=='ok'||!Array.isArray(plan.edits)||plan.edits.length<1) throw new Error('semantic rename backend returned no normalized edits');
211
+ const groups=new Map();
212
+ for(const edit of plan.edits){
213
+ if(!edit||typeof edit.path!=='string'||!Number.isInteger(edit.start)||edit.start<0||!Number.isInteger(edit.length)||edit.length<0||typeof edit.new_text!=='string') throw new Error('semantic rename edit malformed');
214
+ const list=groups.get(edit.path)??[]; list.push(edit); groups.set(edit.path,list);
215
+ }
216
+ const operations=[]; const preimages=[]; let editCount=0;
217
+ for(const filePath of [...groups.keys()].sort((a,b)=>a.localeCompare(b,'en'))){
218
+ const file=await codingRuntime.fileRead({rootId,relativePath:filePath,encoding:'utf8'});
219
+ const edits=[...groups.get(filePath)].sort((a,b)=>a.start-b.start||a.length-b.length);
220
+ let priorEnd=-1;
221
+ for(const edit of edits){
222
+ if(edit.start<priorEnd) throw new Error(`semantic rename overlapping edits in ${filePath}`);
223
+ if(edit.start+edit.length>file.content.length) throw new Error(`semantic rename edit outside ${filePath}`);
224
+ priorEnd=edit.start+edit.length;
225
+ }
226
+ let next=file.content;
227
+ for(const edit of [...edits].sort((a,b)=>b.start-a.start)) next=next.slice(0,edit.start)+edit.new_text+next.slice(edit.start+edit.length);
228
+ operations.push({kind:'write',path:filePath,content:next,encoding:'utf8',expected_sha256:file.sha256});
229
+ preimages.push({path:filePath,sha256:file.sha256});
230
+ editCount+=edits.length;
231
+ }
232
+ const diff=await nativeDiffRuntime.preview({rootId,title:`semantic rename ${relativePath} -> ${newName}`,operations});
233
+ return {status:'ready',diff_id:diff.diff_id,affected_files:operations.length,edit_count:editCount,
234
+ backend:plan.engine??backend.id,preimages};
235
+ }
236
+ return Object.freeze({
237
+ outline:async args=>route('outline',args),
238
+ definition:async args=>route('definition',args),
239
+ references:async args=>route('references',args),
240
+ replaceSymbol:async args=>route('replaceSymbol',args),
241
+ diagnostics:async args=>route('diagnostics',args),
242
+ implementations:async args=>route('implementations',args),
243
+ renamePreview,
244
+ languages:()=>registry.languages()
245
+ });
246
+ }
@@ -0,0 +1,219 @@
1
+ import { createHash } from 'node:crypto';
2
+ import path from 'node:path';
3
+ import { fileURLToPath, pathToFileURL } from 'node:url';
4
+ import { createLspStdioClient } from './lsp-stdio-client.mjs';
5
+
6
+ const SYMBOL_KIND={1:'file',2:'module',3:'namespace',4:'package',5:'class',6:'method',7:'property',8:'field',9:'constructor',10:'enum',11:'interface',12:'function',13:'variable',14:'constant',15:'string',16:'number',17:'boolean',18:'array',19:'object',20:'key',21:'null',22:'enum_member',23:'struct',24:'event',25:'operator',26:'type_parameter'};
7
+ const SEVERITY={1:'error',2:'warning',3:'information',4:'hint'};
8
+ const MAX_WORKSPACE_ENTRIES=512;
9
+ const MAX_WORKSPACE_DOCUMENTS=128;
10
+ const relNormalized=value=>value.replaceAll('\\','/').replace(/^\.\//,'');
11
+ const digest=value=>createHash('sha256').update(JSON.stringify(value)).digest('hex');
12
+ function inside(root,target){const rel=path.relative(root,target);return rel===''||(!rel.startsWith(`..${path.sep}`)&&rel!=='..'&&!path.isAbsolute(rel));}
13
+ function denied(root,absolute){
14
+ if(!inside(root.real_path,absolute)) return true;
15
+ const rel=relNormalized(path.relative(root.real_path,absolute)).toLowerCase();
16
+ return (root.deny_paths??[]).some(item=>rel===String(item).toLowerCase()||rel.startsWith(`${String(item).toLowerCase()}/`));
17
+ }
18
+ function kindName(kind){return SYMBOL_KIND[Number(kind)]??String(kind??'unknown');}
19
+ function validPosition(value){return value&&Number.isInteger(value.line)&&value.line>=0&&Number.isInteger(value.character)&&value.character>=0;}
20
+ function validRange(value){return value&&validPosition(value.start)&&validPosition(value.end);}
21
+ function positionToOffset(text,position){
22
+ if(!validPosition(position)) throw new Error('LSP position invalid');
23
+ let line=0,start=0;
24
+ while(line<position.line){const next=text.indexOf('\n',start);if(next<0)throw new Error('LSP position line outside file');start=next+1;line+=1;}
25
+ const lineEnd=text.indexOf('\n',start);const end=lineEnd<0?text.length:lineEnd;
26
+ const offset=start+position.character;
27
+ if(offset>end) throw new Error('LSP position character outside line');
28
+ return offset;
29
+ }
30
+ function rangeLocation(root,uri,range,{name='',kind='unknown'}={}){
31
+ if(typeof uri!=='string'||!uri.startsWith('file:')||!validRange(range)) return null;
32
+ let absolute;
33
+ try { absolute=path.resolve(fileURLToPath(uri)); } catch { return null; }
34
+ if(!inside(root.real_path,absolute)||denied(root,absolute)) return null;
35
+ return {path:relNormalized(path.relative(root.real_path,absolute)),name:String(name),kind:String(kind),start_line:range.start.line,start_column:range.start.character,end_line:range.end.line,end_column:range.end.character};
36
+ }
37
+ async function rootContext(codingRuntime,rootId,relativePath){
38
+ const status=await codingRuntime.sessionStatus();
39
+ if(!status.armed) throw new Error(`coding plane is disarmed: ${status.reason}`);
40
+ if(!status.root_ids.includes(rootId)) throw new Error(`coding root '${rootId}' is outside active lease`);
41
+ const root=codingRuntime.policy.roots[rootId];
42
+ if(!root||root.read!==true) throw new Error(`coding root '${rootId}' does not allow read`);
43
+ const normalized=relNormalized(relativePath);
44
+ const absolute=path.resolve(root.real_path,...normalized.split('/'));
45
+ if(!inside(root.real_path,absolute)) throw new Error('semantic target escapes coding root');
46
+ if(denied(root,absolute)) throw new Error(`semantic target denied by coding policy: ${normalized}`);
47
+ const file=await codingRuntime.fileRead({rootId,relativePath:normalized,encoding:'utf8'});
48
+ if(typeof file.content!=='string'||typeof file.sha256!=='string') throw new Error('semantic target read missing content identity');
49
+ return {root,rootId,relativePath:normalized,absolute,file,uri:pathToFileURL(absolute).href,rootUri:pathToFileURL(root.real_path+path.sep).href};
50
+ }
51
+ function flattenDocumentSymbols(result,ctx,backendId,maxSymbols){
52
+ if(!Array.isArray(result)) return {symbols:[],truncated:false};
53
+ const out=[];
54
+ const visit=(item,container='')=>{
55
+ if(out.length>=maxSymbols||!item||typeof item!=='object') return;
56
+ if(item.location?.uri&&validRange(item.location.range)){
57
+ const kind=kindName(item.kind);const loc=rangeLocation(ctx.root,item.location.uri,item.location.range,{name:item.name??'',kind});
58
+ if(loc){const selection=item.location.range;const symbolId=digest({schema:'deadbyte.semantic-symbol.v1',backend:backendId,path:loc.path,file_sha256:ctx.file.sha256,name:loc.name,kind,range:item.location.range});out.push({...loc,symbol_id:symbolId,container_name:String(item.containerName??container),name_start_line:selection.start.line,name_start_column:selection.start.character,_range:item.location.range});}
59
+ return;
60
+ }
61
+ if(typeof item.name==='string'&&validRange(item.range)){
62
+ const kind=kindName(item.kind);const loc={path:ctx.relativePath,name:item.name,kind,start_line:item.range.start.line,start_column:item.range.start.character,end_line:item.range.end.line,end_column:item.range.end.character};
63
+ const selection=validRange(item.selectionRange)?item.selectionRange:item.range;
64
+ const symbolId=digest({schema:'deadbyte.semantic-symbol.v1',backend:backendId,path:loc.path,file_sha256:ctx.file.sha256,name:item.name,kind,range:item.range});
65
+ out.push({...loc,symbol_id:symbolId,container_name:container,name_start_line:selection.start.line,name_start_column:selection.start.character,_range:item.range});
66
+ for(const child of item.children??[]) visit(child,item.name);
67
+ }
68
+ };
69
+ for(const item of result) visit(item,'');
70
+ return {symbols:out.slice(0,maxSymbols),truncated:out.length>=maxSymbols};
71
+ }
72
+ function normalizeLocations(result,ctx,maxResults){
73
+ const raw=result==null?[]:(Array.isArray(result)?result:[result]);
74
+ const locations=[];
75
+ for(const item of raw){
76
+ let uri=null,range=null;
77
+ if(item?.uri&&validRange(item.range)){uri=item.uri;range=item.range;}
78
+ else if(item?.targetUri&&validRange(item.targetSelectionRange??item.targetRange)){uri=item.targetUri;range=item.targetSelectionRange??item.targetRange;}
79
+ const loc=rangeLocation(ctx.root,uri,range,{name:'',kind:'reference'});if(loc)locations.push(loc);
80
+ }
81
+ return {locations:locations.slice(0,maxResults),truncated:locations.length>maxResults};
82
+ }
83
+
84
+ export function createSemanticLspBackend({id,extensions,codingRuntime,server}){
85
+ if(typeof id!=='string'||id.length<1) throw new Error('semantic LSP backend id missing');
86
+ if(!Array.isArray(extensions)||extensions.length<1) throw new Error(`semantic LSP backend ${id} extensions missing`);
87
+ if(!codingRuntime) throw new Error(`semantic LSP backend ${id} requires coding runtime`);
88
+ if(!server||typeof server!=='object') throw new Error(`semantic LSP backend ${id} server config missing`);
89
+ const extensionSet=new Set(extensions.map(ext=>String(ext).toLowerCase()));
90
+ const languageId=String(server.language_id??id);
91
+ const startupSettleMs=server.startup_settle_ms===undefined?0:Number(server.startup_settle_ms);
92
+ if(!Number.isInteger(startupSettleMs)||startupSettleMs<0||startupSettleMs>5000) throw new Error(`semantic LSP backend ${id} startup_settle_ms invalid`);
93
+ const nullResultRetryMs=server.null_result_retry_ms===undefined?0:Number(server.null_result_retry_ms);
94
+ const nullResultMaxAttempts=server.null_result_max_attempts===undefined?1:Number(server.null_result_max_attempts);
95
+ const retryEmptyResults=server.retry_empty_results===undefined?false:server.retry_empty_results;
96
+ if(!Number.isInteger(nullResultRetryMs)||nullResultRetryMs<0||nullResultRetryMs>1000) throw new Error(`semantic LSP backend ${id} null_result_retry_ms invalid`);
97
+ if(!Number.isInteger(nullResultMaxAttempts)||nullResultMaxAttempts<1||nullResultMaxAttempts>20) throw new Error(`semantic LSP backend ${id} null_result_max_attempts invalid`);
98
+ if(typeof retryEmptyResults!=='boolean') throw new Error(`semantic LSP backend ${id} retry_empty_results invalid`);
99
+ if(nullResultMaxAttempts>1&&nullResultRetryMs<1) throw new Error(`semantic LSP backend ${id} null_result_retry_ms required when retrying null results`);
100
+ const workspaceDocuments=async ctx=>{
101
+ const target={relativePath:ctx.relativePath,uri:ctx.uri,text:ctx.file.content};
102
+ if(typeof codingRuntime.tree!=='function') return [target];
103
+ const tree=await codingRuntime.tree({rootId:ctx.rootId,path:'.',maxDepth:12,maxEntries:MAX_WORKSPACE_ENTRIES});
104
+ if(tree.truncated) throw new Error(`semantic LSP workspace exceeds ${MAX_WORKSPACE_ENTRIES} entry bound`);
105
+ const relativeFiles=tree.entries.filter(item=>item.type==='file'&&extensionSet.has(path.extname(item.path).toLowerCase())).map(item=>relNormalized(item.path));
106
+ if(relativeFiles.length>MAX_WORKSPACE_DOCUMENTS) throw new Error(`semantic LSP workspace exceeds ${MAX_WORKSPACE_DOCUMENTS} source document bound`);
107
+ const documents=[];
108
+ for(const relativePath of relativeFiles){
109
+ if(relativePath===ctx.relativePath){documents.push(target);continue;}
110
+ const absolute=path.resolve(ctx.root.real_path,...relativePath.split('/'));
111
+ if(!inside(ctx.root.real_path,absolute)||denied(ctx.root,absolute)) continue;
112
+ const file=await codingRuntime.fileRead({rootId:ctx.rootId,relativePath,encoding:'utf8'});
113
+ if(typeof file.content!=='string') throw new Error(`semantic LSP preload missing UTF-8 content: ${relativePath}`);
114
+ documents.push({relativePath,uri:pathToFileURL(absolute).href,text:file.content});
115
+ }
116
+ if(!documents.some(item=>item.relativePath===ctx.relativePath)) documents.unshift(target);
117
+ return documents;
118
+ };
119
+ const open=async ctx=>{
120
+ const client=createLspStdioClient({executablePath:server.executable_path,expectedSha256:server.executable_sha256,args:server.args??[],cwd:ctx.root.real_path,env:server.env??{},dependencies:server.dependencies??[],requestTimeoutMs:server.request_timeout_ms??10000,maxMessageBytes:server.max_message_bytes??4*1024*1024});
121
+ try{
122
+ await client.initialize({processId:null,rootPath:ctx.root.real_path,rootUri:ctx.rootUri,workspaceFolders:[{uri:ctx.rootUri,name:path.basename(ctx.root.real_path)}],capabilities:{workspace:{workspaceFolders:true},textDocument:{documentSymbol:{hierarchicalDocumentSymbolSupport:true},definition:{},references:{},implementation:{},rename:{prepareSupport:false},diagnostic:{}}},initializationOptions:server.initialization_options??{}});
123
+ for(const document of await workspaceDocuments(ctx)) client.notify('textDocument/didOpen',{textDocument:{uri:document.uri,languageId,version:1,text:document.text}});
124
+ if(startupSettleMs>0) await new Promise(resolve=>setTimeout(resolve,startupSettleMs));
125
+ return client;
126
+ } catch(error){await client.shutdown().catch(()=>{});throw error;}
127
+ };
128
+ const withClient=async(ctx,fn)=>{const client=await open(ctx);try{return await fn(client);}finally{await client.shutdown().catch(()=>{});}};
129
+ const requestRead=async(client,method,params)=>{
130
+ let result=null;
131
+ for(let attempt=1;attempt<=nullResultMaxAttempts;attempt+=1){
132
+ result=await client.request(method,params);
133
+ const transientEmpty=retryEmptyResults&&Array.isArray(result)&&result.length===0;
134
+ if((result!==null&&!transientEmpty)||attempt===nullResultMaxAttempts) return result;
135
+ await new Promise(resolve=>setTimeout(resolve,nullResultRetryMs));
136
+ }
137
+ return result;
138
+ };
139
+ async function outline({rootId,relativePath,maxSymbols=200}){
140
+ if(!Number.isInteger(maxSymbols)||maxSymbols<1||maxSymbols>500) throw new Error('max_symbols must be in [1, 500]');
141
+ const ctx=await rootContext(codingRuntime,rootId,relativePath);
142
+ const raw=await withClient(ctx,client=>requestRead(client,'textDocument/documentSymbol',{textDocument:{uri:ctx.uri}}));
143
+ const flat=flattenDocumentSymbols(raw,ctx,id,maxSymbols);
144
+ return {status:'ok',root_id:rootId,path:ctx.relativePath,file_sha256:ctx.file.sha256,engine:id,symbols:flat.symbols.map(({_range,...item})=>item),truncated:flat.truncated};
145
+ }
146
+ async function definition({rootId,relativePath,line,column,maxResults=50}){
147
+ if(!Number.isInteger(maxResults)||maxResults<1||maxResults>200) throw new Error('max_results must be in [1, 200]');
148
+ const ctx=await rootContext(codingRuntime,rootId,relativePath);
149
+ const raw=await withClient(ctx,client=>requestRead(client,'textDocument/definition',{textDocument:{uri:ctx.uri},position:{line,character:column}}));
150
+ const normalized=normalizeLocations(raw,ctx,maxResults);
151
+ return {status:'ok',root_id:rootId,path:ctx.relativePath,line,column,engine:id,...normalized};
152
+ }
153
+ async function references({rootId,relativePath,line,column,maxResults=200}){
154
+ if(!Number.isInteger(maxResults)||maxResults<1||maxResults>500) throw new Error('max_results must be in [1, 500]');
155
+ const ctx=await rootContext(codingRuntime,rootId,relativePath);
156
+ const raw=await withClient(ctx,client=>requestRead(client,'textDocument/references',{textDocument:{uri:ctx.uri},position:{line,character:column},context:{includeDeclaration:true}}));
157
+ const normalized=normalizeLocations(raw,ctx,maxResults);
158
+ return {status:'ok',root_id:rootId,path:ctx.relativePath,line,column,engine:id,...normalized};
159
+ }
160
+ async function diagnostics({rootId,relativePath,maxResults=200}){
161
+ if(!Number.isInteger(maxResults)||maxResults<1||maxResults>500) throw new Error('max_results must be in [1, 500]');
162
+ const ctx=await rootContext(codingRuntime,rootId,relativePath);
163
+ const raw=await withClient(ctx,client=>requestRead(client,'textDocument/diagnostic',{textDocument:{uri:ctx.uri}}));
164
+ const items=Array.isArray(raw?.items)?raw.items:[];
165
+ const diagnosticsOut=items.slice(0,maxResults).filter(item=>validRange(item?.range)).map(item=>({message:String(item.message??''),code:String(item.code??''),severity:SEVERITY[Number(item.severity)]??'unknown',location:{path:ctx.relativePath,name:'',kind:'diagnostic',start_line:item.range.start.line,start_column:item.range.start.character,end_line:item.range.end.line,end_column:item.range.end.character}}));
166
+ const stable={root_id:rootId,path:ctx.relativePath,file_sha256:ctx.file.sha256,engine:id,diagnostics:diagnosticsOut,truncated:items.length>maxResults};
167
+ return {status:'ok',...stable,result_sha256:digest({schema:'deadbyte.semantic-diagnostics.v1',...stable})};
168
+ }
169
+ async function implementations({rootId,relativePath,line,column,maxResults=200}){
170
+ if(!Number.isInteger(maxResults)||maxResults<1||maxResults>500) throw new Error('max_results must be in [1, 500]');
171
+ const ctx=await rootContext(codingRuntime,rootId,relativePath);
172
+ let raw;
173
+ try { raw=await withClient(ctx,client=>requestRead(client,'textDocument/implementation',{textDocument:{uri:ctx.uri},position:{line,character:column}})); }
174
+ catch(error){ if(/-32601|method not found/i.test(String(error))) return {status:'unsupported',capability:'implementations',engine:id}; throw error; }
175
+ const normalized=normalizeLocations(raw,ctx,maxResults);
176
+ const stable={root_id:rootId,path:ctx.relativePath,line,column,file_sha256:ctx.file.sha256,engine:id,...normalized};
177
+ return {status:'ok',...stable,result_sha256:digest({schema:'deadbyte.semantic-implementations.v1',...stable})};
178
+ }
179
+ async function renameEdits({rootId,relativePath,line,column,newName}){
180
+ const ctx=await rootContext(codingRuntime,rootId,relativePath);
181
+ let raw;
182
+ try { raw=await withClient(ctx,client=>requestRead(client,'textDocument/rename',{textDocument:{uri:ctx.uri},position:{line,character:column},newName})); }
183
+ catch(error){ if(/-32601|method not found/i.test(String(error))) return {status:'unsupported',capability:'rename_preview',engine:id}; throw error; }
184
+ const byUri=[];
185
+ if(raw?.changes&&typeof raw.changes==='object') for(const [uri,edits] of Object.entries(raw.changes)) byUri.push({uri,edits});
186
+ for(const change of raw?.documentChanges??[]){ if(change?.textDocument?.uri&&Array.isArray(change.edits)) byUri.push({uri:change.textDocument.uri,edits:change.edits}); }
187
+ const normalized=[];
188
+ for(const group of byUri){
189
+ let absolute; try{absolute=path.resolve(fileURLToPath(group.uri));}catch{continue;}
190
+ if(!inside(ctx.root.real_path,absolute)||denied(ctx.root,absolute)) continue;
191
+ const rel=relNormalized(path.relative(ctx.root.real_path,absolute));
192
+ const file=await codingRuntime.fileRead({rootId,relativePath:rel,encoding:'utf8'});
193
+ for(const edit of group.edits??[]){
194
+ if(!validRange(edit?.range)||typeof edit?.newText!=='string') throw new Error('semantic LSP rename edit malformed');
195
+ const start=positionToOffset(file.content,edit.range.start); const end=positionToOffset(file.content,edit.range.end);
196
+ if(end<start) throw new Error('semantic LSP rename range invalid');
197
+ normalized.push({path:rel,start,length:end-start,new_text:edit.newText});
198
+ }
199
+ }
200
+ if(normalized.length<1) throw new Error('semantic LSP rename produced no allowed edits');
201
+ normalized.sort((a,b)=>a.path.localeCompare(b.path,'en')||a.start-b.start||a.length-b.length);
202
+ return {status:'ok',root_id:rootId,path:ctx.relativePath,engine:id,target_file_sha256:ctx.file.sha256,edits:normalized};
203
+ }
204
+ async function replaceSymbol({rootId,relativePath,symbolId,newBody,expectedSha256}){
205
+ if(typeof newBody!=='string'||newBody.length>524288) throw new Error('new_body exceeds 524288 characters');
206
+ const ctx=await rootContext(codingRuntime,rootId,relativePath);
207
+ if(ctx.file.sha256!==expectedSha256) throw new Error(`semantic replace precondition mismatch: expected ${expectedSha256}, found ${ctx.file.sha256}`);
208
+ const raw=await withClient(ctx,client=>requestRead(client,'textDocument/documentSymbol',{textDocument:{uri:ctx.uri}}));
209
+ const flat=flattenDocumentSymbols(raw,ctx,id,500);
210
+ const symbol=flat.symbols.find(item=>item.symbol_id===symbolId);
211
+ if(!symbol) throw new Error('semantic symbol_id is stale or unknown for current file');
212
+ const start=positionToOffset(ctx.file.content,symbol._range.start);const end=positionToOffset(ctx.file.content,symbol._range.end);
213
+ if(end<start) throw new Error('semantic symbol range invalid');
214
+ const oldBody=ctx.file.content.slice(start,end);
215
+ const result=await codingRuntime.textReplace({rootId,relativePath:ctx.relativePath,oldString:oldBody,newString:newBody,expectedSha256,expectedReplacements:1});
216
+ return {...result,symbol_id:symbolId,symbol_name:symbol.name,engine:id};
217
+ }
218
+ return Object.freeze({id,extensions:extensionSet,outline,definition,references,replaceSymbol,diagnostics,implementations,renameEdits});
219
+ }
@@ -0,0 +1,112 @@
1
+ import path from 'node:path';
2
+ import { createHash } from 'node:crypto';
3
+ import { readFile } from 'node:fs/promises';
4
+ import { createSemanticLspBackend } from './semantic-lsp-backend.mjs';
5
+
6
+ const HEX64=/^[0-9a-f]{64}$/;
7
+ const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
8
+ const ID=/^[A-Za-z0-9._-]{1,64}$/;
9
+
10
+ function plainObject(value){return value&&typeof value==='object'&&!Array.isArray(value);}
11
+
12
+ export function parseSemanticLspConfig(value){
13
+ if(!plainObject(value)||value.schema!=='deadbyte.semantic-lsp-config.v1') throw new Error('semantic LSP config schema mismatch');
14
+ if(!Array.isArray(value.servers)) throw new Error('semantic LSP config servers must be an array');
15
+ if(value.servers.length>16) throw new Error('semantic LSP config server count exceeds 16');
16
+ const ids=new Set();
17
+ const extensions=new Map();
18
+ const servers=value.servers.map((raw,index)=>{
19
+ if(!plainObject(raw)) throw new Error(`semantic LSP server ${index} must be an object`);
20
+ const id=String(raw.id??'');
21
+ if(!ID.test(id)) throw new Error(`semantic LSP server ${index} id invalid`);
22
+ const languageId=String(raw.language_id??id);
23
+ if(!ID.test(languageId)) throw new Error(`semantic LSP server ${id} language_id invalid`);
24
+ if(ids.has(id)) throw new Error(`duplicate semantic LSP server id: ${id}`);
25
+ ids.add(id);
26
+ if(!Array.isArray(raw.extensions)||raw.extensions.length<1||raw.extensions.length>32) throw new Error(`semantic LSP server ${id} extensions missing`);
27
+ const normalizedExtensions=[];
28
+ for(const item of raw.extensions){
29
+ const ext=String(item??'').toLowerCase();
30
+ if(!/^\.[a-z0-9+_-]{1,16}$/.test(ext)) throw new Error(`semantic LSP server ${id} extension invalid: ${ext||'<empty>'}`);
31
+ const owner=extensions.get(ext);
32
+ if(owner&&owner!==id) throw new Error(`semantic extension ${ext} already owned by ${owner}`);
33
+ extensions.set(ext,id);
34
+ if(!normalizedExtensions.includes(ext)) normalizedExtensions.push(ext);
35
+ }
36
+ const executablePath=String(raw.executable_path??'');
37
+ if(!path.isAbsolute(executablePath)) throw new Error(`semantic LSP server ${id} executable_path must be absolute`);
38
+ const executableSha=String(raw.executable_sha256??'').toLowerCase();
39
+ if(!HEX64.test(executableSha)) throw new Error(`semantic LSP server ${id} executable SHA-256 invalid`);
40
+ const args=raw.args===undefined?[]:raw.args;
41
+ if(!Array.isArray(args)||args.length>64||args.some(item=>typeof item!=='string'||item.length>2048)) throw new Error(`semantic LSP server ${id} args invalid`);
42
+ const env=raw.env===undefined?{}:raw.env;
43
+ if(!plainObject(env)||Object.entries(env).some(([key,item])=>!ID.test(key)||typeof item!=='string'||item.length>4096)) throw new Error(`semantic LSP server ${id} env invalid`);
44
+ const dependencies=raw.dependencies===undefined?[]:raw.dependencies;
45
+ if(!Array.isArray(dependencies)||dependencies.length>32) throw new Error(`semantic LSP server ${id} dependencies invalid`);
46
+ const normalizedDependencies=dependencies.map((dependency,depIndex)=>{
47
+ if(!plainObject(dependency)) throw new Error(`semantic LSP server ${id} dependency ${depIndex} invalid`);
48
+ const dependencyPath=String(dependency.path??'');
49
+ if(!path.isAbsolute(dependencyPath)) throw new Error(`semantic LSP server ${id} dependency path must be absolute`);
50
+ const expectedSha256=String(dependency.expected_sha256??dependency.expectedSha256??'').toLowerCase();
51
+ if(!HEX64.test(expectedSha256)) throw new Error(`semantic LSP server ${id} dependency SHA-256 invalid`);
52
+ return {path:dependencyPath,expectedSha256};
53
+ });
54
+ const initializationOptions=raw.initialization_options===undefined?{}:raw.initialization_options;
55
+ if(!plainObject(initializationOptions)) throw new Error(`semantic LSP server ${id} initialization_options invalid`);
56
+ const requestTimeoutMs=raw.request_timeout_ms===undefined?10000:Number(raw.request_timeout_ms);
57
+ if(!Number.isInteger(requestTimeoutMs)||requestTimeoutMs<100||requestTimeoutMs>120000) throw new Error(`semantic LSP server ${id} request_timeout_ms invalid`);
58
+ const maxMessageBytes=raw.max_message_bytes===undefined?4*1024*1024:Number(raw.max_message_bytes);
59
+ if(!Number.isInteger(maxMessageBytes)||maxMessageBytes<256||maxMessageBytes>16*1024*1024) throw new Error(`semantic LSP server ${id} max_message_bytes invalid`);
60
+ const startupSettleMs=raw.startup_settle_ms===undefined?0:Number(raw.startup_settle_ms);
61
+ if(!Number.isInteger(startupSettleMs)||startupSettleMs<0||startupSettleMs>5000) throw new Error(`semantic LSP server ${id} startup_settle_ms invalid`);
62
+ const nullResultRetryMs=raw.null_result_retry_ms===undefined?0:Number(raw.null_result_retry_ms);
63
+ const nullResultMaxAttempts=raw.null_result_max_attempts===undefined?1:Number(raw.null_result_max_attempts);
64
+ const retryEmptyResults=raw.retry_empty_results===undefined?false:raw.retry_empty_results;
65
+ if(!Number.isInteger(nullResultRetryMs)||nullResultRetryMs<0||nullResultRetryMs>1000) throw new Error(`semantic LSP server ${id} null_result_retry_ms invalid`);
66
+ if(!Number.isInteger(nullResultMaxAttempts)||nullResultMaxAttempts<1||nullResultMaxAttempts>20) throw new Error(`semantic LSP server ${id} null_result_max_attempts invalid`);
67
+ if(typeof retryEmptyResults!=='boolean') throw new Error(`semantic LSP server ${id} retry_empty_results invalid`);
68
+ if(nullResultMaxAttempts>1&&nullResultRetryMs<1) throw new Error(`semantic LSP server ${id} null_result_retry_ms required when retrying null results`);
69
+ const required=raw.required===undefined?false:raw.required;
70
+ if(typeof required!=='boolean') throw new Error(`semantic LSP server ${id} required must be boolean`);
71
+ return {id,language_id:languageId,extensions:normalizedExtensions,executable_path:executablePath,executable_sha256:executableSha,args:[...args],env:{...env},dependencies:normalizedDependencies,initialization_options:initializationOptions,request_timeout_ms:requestTimeoutMs,max_message_bytes:maxMessageBytes,startup_settle_ms:startupSettleMs,null_result_retry_ms:nullResultRetryMs,null_result_max_attempts:nullResultMaxAttempts,retry_empty_results:retryEmptyResults,required};
72
+ });
73
+ return Object.freeze({schema:'deadbyte.semantic-lsp-config.v1',servers});
74
+ }
75
+
76
+ export function semanticConfigBindingFromEnv(env=process.env){
77
+ const configPath=String(env.DEADBYTE_SEMANTIC_LSP_CONFIG??'').trim();
78
+ const expectedConfigSha256=String(env.DEADBYTE_SEMANTIC_LSP_CONFIG_SHA256??'').trim().toLowerCase();
79
+ if(!configPath&&!expectedConfigSha256) return null;
80
+ if(configPath&&!expectedConfigSha256) throw new Error('DEADBYTE_SEMANTIC_LSP_CONFIG requires semantic LSP config SHA-256');
81
+ if(!configPath&&expectedConfigSha256) throw new Error('DEADBYTE_SEMANTIC_LSP_CONFIG_SHA256 requires semantic LSP config path');
82
+ if(!path.isAbsolute(configPath)) throw new Error('semantic LSP config path must be absolute');
83
+ if(!HEX64.test(expectedConfigSha256)) throw new Error('semantic LSP config SHA-256 invalid');
84
+ return Object.freeze({configPath,expectedConfigSha256});
85
+ }
86
+
87
+ export async function loadSemanticLspBackends({configPath,expectedConfigSha256,codingRuntime}){
88
+ if(typeof configPath!=='string'||!path.isAbsolute(configPath)) throw new Error('semantic LSP config path must be absolute');
89
+ if(!HEX64.test(expectedConfigSha256??'')) throw new Error('semantic LSP config SHA-256 invalid');
90
+ if(!codingRuntime) throw new Error('semantic LSP config requires coding runtime');
91
+ let configBytes,parsedJson;
92
+ try { configBytes=await readFile(configPath); parsedJson=JSON.parse(configBytes.toString('utf8')); }
93
+ catch(error){ throw new Error(`semantic LSP config read failed: ${error.message}`); }
94
+ const observedConfigSha256=sha256(configBytes);
95
+ if(observedConfigSha256!==expectedConfigSha256) throw new Error(`semantic LSP config SHA-256 mismatch: expected ${expectedConfigSha256}, found ${observedConfigSha256}`);
96
+ const config=parseSemanticLspConfig(parsedJson);
97
+ const backends=[];
98
+ const requiredIds=[];
99
+ for(const server of config.servers){
100
+ const executableBytes=await readFile(server.executable_path);
101
+ const executableSha=sha256(executableBytes);
102
+ if(executableSha!==server.executable_sha256) throw new Error(`semantic LSP executable SHA-256 mismatch for ${server.id}: expected ${server.executable_sha256}, found ${executableSha}`);
103
+ for(const dependency of server.dependencies){
104
+ const dependencyBytes=await readFile(dependency.path);
105
+ const dependencySha=sha256(dependencyBytes);
106
+ if(dependencySha!==dependency.expectedSha256) throw new Error(`semantic LSP dependency SHA-256 mismatch for ${server.id}: expected ${dependency.expectedSha256}, found ${dependencySha}`);
107
+ }
108
+ backends.push(createSemanticLspBackend({id:server.id,extensions:server.extensions,codingRuntime,server}));
109
+ if(server.required) requiredIds.push(server.id);
110
+ }
111
+ return Object.freeze({backends:Object.freeze(backends),required_ids:Object.freeze(requiredIds)});
112
+ }