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
@@ -18,7 +18,7 @@ async function fixture({failCommand=''}={}){
18
18
  const trace=path.join(dir,'trace.txt');
19
19
  await mkdir(bin,{recursive:true});
20
20
  const launcher=path.join(bin,'DEADBYTE-MCP.ps1');
21
- const ps1=`param([string]$Command)\nAdd-Content -LiteralPath $env:DEADBYTE_REMOTE_TEST_TRACE -Value $Command -Encoding UTF8\nif ($env:DEADBYTE_REMOTE_TEST_FAIL -and $Command -eq $env:DEADBYTE_REMOTE_TEST_FAIL) { Write-Error \"forced $Command failure\"; exit 9 }\nswitch ($Command) {\n 'start' { Write-Host 'DEADBYTE MCP = ONLINE' }\n 'processstatus' { Write-Host 'Process plane : ARMED [standing-grant]' }\n 'codingstatus' { Write-Host 'Coding plane : ARMED [standing-grant]' }\n 'autonomousstatus' { Write-Host 'Autonomous : ARMED [standing-grant]' }\n 'hoststatus' { Write-Host 'Host plane : ARMED [standing-grant]' }\n 'park' { Write-Host 'DEADBYTE MCP = PARKED' }\n default { Write-Host \"$Command OK\" }\n}\nexit 0\n`;
21
+ const ps1=`param([string]$Command)\n$ErrorActionPreference='Stop'\nfor($i=0;$i -lt 20;$i++){ try { [IO.File]::AppendAllText($env:DEADBYTE_REMOTE_TEST_TRACE,(\"$Command\" + [Environment]::NewLine),[Text.Encoding]::UTF8); break } catch { if($i -eq 19){ throw }; Start-Sleep -Milliseconds 10 } }\nif ($env:DEADBYTE_REMOTE_TEST_FAIL -and $Command -eq $env:DEADBYTE_REMOTE_TEST_FAIL) { Write-Error \"forced $Command failure\"; exit 9 }\nswitch ($Command) {\n 'start' { Write-Host 'DEADBYTE MCP = ONLINE' }\n 'processstatus' { Write-Host 'Process plane : ARMED [standing-grant]' }\n 'codingstatus' { Write-Host 'Coding plane : ARMED [standing-grant]' }\n 'autonomousstatus' { Write-Host 'Autonomous : ARMED [standing-grant]' }\n 'hoststatus' { Write-Host 'Host plane : DISARMED [disarmed]' }\n 'park' { Write-Host 'DEADBYTE MCP = PARKED' }\n default { Write-Host \"$Command OK\" }\n}\nexit 0\n`;
22
22
  await writeFile(launcher,ps1,'utf8');
23
23
  return {dir,state,trace,env:{...process.env,DEADBYTE_STATE_ROOT:state,DEADBYTE_REMOTE_TEST_TRACE:trace,DEADBYTE_REMOTE_TEST_FAIL:failCommand}};
24
24
  }
@@ -34,7 +34,7 @@ async function traceCommands(file,{read=readFile,retryDelayMs=10,maxAttempts=20}
34
34
  }
35
35
  return [];
36
36
  }
37
- async function waitFor(file,predicate,{timeoutMs=6000}={}){
37
+ async function waitFor(file,predicate,{timeoutMs=12000}={}){
38
38
  const deadline=Date.now()+timeoutMs;
39
39
  while(Date.now()<deadline){
40
40
  const commands=await traceCommands(file);
@@ -65,31 +65,43 @@ async function collect(child){
65
65
 
66
66
  const winTest=isWindows?test:test.skip;
67
67
 
68
- winTest('bare remote arms every authority plane, verifies ARMED state, streams logs, then disarms and parks when the foreground session ends',async()=>{
68
+ winTest('bare remote uses compact human logs by default, keeps authority semantics, then disarms and parks when the foreground session ends',async()=>{
69
69
  const fx=await fixture();
70
70
  let child=null;
71
71
  try{
72
72
  child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
73
73
  const output=await collect(child);
74
- const ready=await waitFor(fx.trace,commands=>commands.slice(0,9).join(',')==='start,armprocess,armcoding,armautonomous,armhost,processstatus,codingstatus,autonomousstatus,hoststatus');
75
- assert.deepEqual(ready.slice(0,9),[
76
- 'start','armprocess','armcoding','armautonomous','armhost',
74
+ const ready=await waitFor(fx.trace,commands=>commands.slice(0,8).join(',')==='start,armprocess,armcoding,armautonomous,processstatus,codingstatus,autonomousstatus,hoststatus');
75
+ assert.deepEqual(ready.slice(0,8),[
76
+ 'start','armprocess','armcoding','armautonomous',
77
77
  'processstatus','codingstatus','autonomousstatus','hoststatus'
78
78
  ]);
79
79
  assert.equal(child.exitCode,null,'remote session must remain foreground after becoming ready');
80
80
  const tailDeadline=Date.now()+3000;
81
- while(Date.now()<tailDeadline&&!/📜 \[LOG\] Live logs active/.test(output.stdout)) await sleep(50);
82
- assert.match(output.stdout,/📜 \[LOG\] Live logs active\. Press Ctrl\+C to disconnect and revoke authority\./);
83
- assert.match(output.stdout,/🛡️ \[AUTHORITY\] Verifying runtime planes\.\.\./);
81
+ while(Date.now()<tailDeadline&&!/🔐 \[AUTH\] ARMED: process, coding, autonomous \| host DISARMED/.test(output.stdout)) await sleep(50);
82
+ assert.match(output.stdout,/🚀 \[DEVICE\] Starting DEADBYTE MCP/);
83
+ assert.match(output.stdout,/🔌 \[BRIDGE\] Local bridge connected/);
84
+ assert.match(output.stdout,/🔌 \[CLOUD\] Remote MCP connected/);
85
+ assert.match(output.stdout,/\[SESSION\] New foreground session/);
86
+ assert.match(output.stdout,/\[BOOT\] Starting local \+ remote runtime/);
87
+ assert.match(output.stdout,/\[OK\] ONLINE/);
88
+ assert.match(output.stdout,/✅ \[READY\] DEADBYTE MCP online/);
89
+ assert.match(output.stdout,/🔐 \[AUTH\] ARMED: process, coding, autonomous \| host DISARMED/);
90
+ assert.match(output.stdout,/\[LOG\] Live activity\. Ctrl\+C disconnects and revokes authority\./);
91
+ assert.doesNotMatch(output.stdout,/Process plane\s*:/);
92
+ assert.doesNotMatch(output.stdout,/Coding plane\s*:/);
84
93
  const auditDir=path.join(fx.state,'audit');
85
94
  const runtimeLogs=path.join(fx.state,'runtime','logs');
86
95
  await mkdir(auditDir,{recursive:true});
87
96
  await mkdir(runtimeLogs,{recursive:true});
97
+ const marker=JSON.parse(await readFile(path.join(fx.state,'runtime','remote-session.json'),'utf8'));
98
+ assert.match(String(marker.result_session_id||''),/^[0-9a-f]{24}$/);
88
99
  const auditEvents=[
89
- {seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'abcdef1234567890'},
90
- {seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false}},
91
- {seq:3,event_type:'tool.request',tool:'coding_file_read',request_id:'fedcba9876543210'},
92
- {seq:4,event_type:'tool.result',tool:'coding_file_read',request_id:'fedcba9876543210',outcome:{is_error:true}}
100
+ {seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'abcdef1234567890',args:{root_id:'projects',path:'src',content:'DO_NOT_PRINT_PAYLOAD',token:'DO_NOT_PRINT_TOKEN'}},
101
+ {seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false,duration_ms:42}},
102
+ {seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false,duration_ms:42}},
103
+ {seq:3,event_type:'tool.request',tool:'coding_file_read',request_id:'fedcba9876543210',args:{root_id:'projects',path:'src/deadbyte-cli.mjs'}},
104
+ {seq:4,event_type:'tool.result',tool:'coding_file_read',request_id:'fedcba9876543210',outcome:{is_error:true,duration_ms:1734}}
93
105
  ];
94
106
  await writeFile(path.join(auditDir,'segment-00000001.jsonl'),`${auditEvents.map(event=>JSON.stringify(event)).join('\n')}\n`,'utf8');
95
107
  await writeFile(path.join(runtimeLogs,'bridge.stdout.log'),[
@@ -98,22 +110,32 @@ winTest('bare remote arms every authority plane, verifies ARMED state, streams l
98
110
  '[TOOL OUT] 2026-09-16T00:00:00.002Z #000002 coding_file_read {"is_error":true}'
99
111
  ].join('\n')+'\n','utf8');
100
112
  const logDeadline=Date.now()+3000;
101
- while(Date.now()<logDeadline&&!/📤❌ \[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_file_read/.test(output.stdout)) await sleep(50);
102
- assert.match(output.stdout,/📥 \[AUDIT #1\] tool\.request coding_tree abcdef12/);
103
- assert.match(output.stdout,/📤✅ \[AUDIT #2\] tool\.result coding_tree abcdef12/);
104
- assert.match(output.stdout,/📥 \[AUDIT #3\] tool\.request coding_file_read fedcba98/);
105
- assert.match(output.stdout,/📤❌ \[AUDIT #4\] tool\.result coding_file_read fedcba98/);
106
- assert.match(output.stdout,/📥 \[BRIDGE\.STDOUT\] \[TOOL IN \].*coding_tree/);
107
- assert.match(output.stdout,/📤✅ \[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_tree/);
108
- assert.match(output.stdout,/📤❌ \[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_file_read/);
113
+ while(Date.now()<logDeadline&&!/❌ ERR coding_file_read 1\.73s/.test(output.stdout)) await sleep(50);
114
+ assert.match(output.stdout,/▶ RUN coding_tree root=projects path=src/);
115
+ assert.match(output.stdout,/✅ OK coding_tree 42ms \[cursor r1:[0-9a-f]{24}:1\]/);
116
+ assert.match(output.stdout,/▶ RUN coding_file_read root=projects path=src\/deadbyte-cli\.mjs/);
117
+ assert.match(output.stdout,/❌ ERR coding_file_read 1\.73s \[cursor r1:[0-9a-f]{24}:2\]/);
118
+ assert.equal((output.stdout.match(/✅ OK coding_tree 42ms/g)||[]).length,1,'duplicate terminal result must print once');
119
+ const resultJournal=JSON.parse(await readFile(path.join(fx.state,'runtime','remote-results',`${marker.result_session_id}.json`),'utf8'));
120
+ assert.deepEqual(resultJournal.events.map(event=>event.seq),[1,2]);
121
+ assert.equal(resultJournal.events[0].request_id,'abcdef1234567890');
122
+ assert.ok(resultJournal.events.every(event=>/^[0-9a-f]{64}$/.test(event.payload_sha256)));
123
+ assert.doesNotMatch(JSON.stringify(resultJournal),/TOOL IN|TOOL OUT|stdout_excerpt|stderr_excerpt/);
124
+ assert.doesNotMatch(output.stdout,/abcdef12|fedcba98/);
125
+ assert.doesNotMatch(output.stdout,/DO_NOT_PRINT_PAYLOAD|DO_NOT_PRINT_TOKEN/);
126
+ assert.doesNotMatch(output.stdout,/BRIDGE\.STDOUT/);
127
+ assert.doesNotMatch(output.stdout,/\[TOOL IN \]|\[TOOL OUT\]/);
128
+ assert.doesNotMatch(output.stdout,/payload bytes=/);
109
129
  child.stdin.end();
110
130
  const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
111
131
  assert.equal(ended.timeout,undefined,'remote session did not exit after foreground input closed');
112
132
  const commands=await traceCommands(fx.trace);
113
133
  assert.deepEqual(commands.slice(-5),['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park']);
114
- assert.match(output.stdout,/DEADBYTE MCP DEVICE SESSION/i);
115
- assert.match(output.stdout,/Live logs/i);
116
- const withoutApprovedEmoji=output.stdout.replace(/[📜📥📤✅❌⚠♻🛡]/gu,'');
134
+ assert.match(output.stdout,/^DEADBYTE MCP$/m);
135
+ assert.match(output.stdout,/Live activity/i);
136
+ assert.match(output.stdout,/🔐 \[AUTH\] Revoking session authority/);
137
+ assert.doesNotMatch(output.stdout,/disarmautonomous OK|disarmcoding OK|disarmprocess OK|disarmhost OK|DEADBYTE MCP = PARKED/);
138
+ const withoutApprovedEmoji=output.stdout.replace(/[📜📥📤✅❌⚠♻🛡▶🔐🚀🔌]/gu,'');
117
139
  assert.doesNotMatch(withoutApprovedEmoji,/\p{Extended_Pictographic}/u,'human live stream may use only the approved semantic emoji set');
118
140
  }finally{
119
141
  if(child?.exitCode===null) child.kill();
@@ -121,15 +143,98 @@ winTest('bare remote arms every authority plane, verifies ARMED state, streams l
121
143
  }
122
144
  });
123
145
 
146
+ winTest('remote --resume replays only terminal results after the cursor before starting a new live session',async()=>{
147
+ const fx=await fixture();
148
+ let first=null,second=null;
149
+ try{
150
+ first=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
151
+ const firstOutput=await collect(first);
152
+ await waitFor(fx.trace,commands=>commands.includes('hoststatus'));
153
+ const liveDeadline=Date.now()+3000;
154
+ while(Date.now()<liveDeadline&&!/\[LOG\] Live activity/.test(firstOutput.stdout)) await sleep(50);
155
+ const auditDir=path.join(fx.state,'audit');await mkdir(auditDir,{recursive:true});
156
+ const auditFile=path.join(auditDir,'segment-00000001.jsonl');
157
+ await writeFile(auditFile,JSON.stringify({seq:1,event_type:'tool.result',tool:'coding_tree',request_id:'resume-request-1',outcome:{is_error:false}})+'\n','utf8');
158
+ let deadline=Date.now()+3000;
159
+ while(Date.now()<deadline&&!/coding_tree \[cursor r1:[0-9a-f]{24}:1\]/.test(firstOutput.stdout)) await sleep(50);
160
+ const cursor1=firstOutput.stdout.match(/coding_tree \[cursor (r1:[0-9a-f]{24}:1)\]/)?.[1];
161
+ assert.ok(cursor1,'first result cursor missing');
162
+ await writeFile(auditFile,JSON.stringify({seq:2,event_type:'tool.result',tool:'coding_file_read',request_id:'resume-request-2',outcome:{is_error:false}})+'\n',{encoding:'utf8',flag:'a'});
163
+ deadline=Date.now()+3000;
164
+ while(Date.now()<deadline&&!/coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/.test(firstOutput.stdout)) await sleep(50);
165
+ first.stdin.end();
166
+ const firstEnded=await Promise.race([firstOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
167
+ assert.equal(firstEnded.timeout,undefined);
168
+
169
+ second=spawn(process.execPath,[cliPath,'remote','--resume',cursor1],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
170
+ const secondOutput=await collect(second);
171
+ deadline=Date.now()+5000;
172
+ while(Date.now()<deadline&&(!/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/.test(secondOutput.stdout)||
173
+ !/\[LOG\] Live activity/.test(secondOutput.stdout))) await sleep(50);
174
+ assert.match(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/);
175
+ assert.match(secondOutput.stdout,/♻️ \[SESSION\] Previous result stream replayed/);
176
+ assert.doesNotMatch(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_tree/);
177
+ const replayIndex=secondOutput.stdout.indexOf('[REPLAY]');
178
+ const liveIndex=secondOutput.stdout.indexOf('[LOG] Live activity');
179
+ assert.ok(replayIndex>=0&&liveIndex>replayIndex,'resume replay must happen before new live tail');
180
+ second.stdin.end();
181
+ const secondEnded=await Promise.race([secondOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
182
+ assert.equal(secondEnded.timeout,undefined);
183
+ assert.equal(secondEnded.code,0,secondOutput.stderr);
184
+ }finally{
185
+ if(first?.exitCode===null) first.kill();if(second?.exitCode===null) second.kill();
186
+ await rm(fx.dir,{recursive:true,force:true});
187
+ }
188
+ });
189
+
190
+ winTest('remote --verbose preserves detailed audit and bridge log streaming for debugging',async()=>{
191
+ const fx=await fixture();
192
+ let child=null;
193
+ try{
194
+ child=spawn(process.execPath,[cliPath,'remote','--verbose'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
195
+ const output=await collect(child);
196
+ const ready=await waitFor(fx.trace,commands=>commands.slice(0,8).join(',')==='start,armprocess,armcoding,armautonomous,processstatus,codingstatus,autonomousstatus,hoststatus');
197
+ assert.equal(ready.length>=8,true);
198
+ const liveDeadline=Date.now()+3000;
199
+ while(Date.now()<liveDeadline&&!/Live logs active/.test(output.stdout)) await sleep(50);
200
+ assert.match(output.stdout,/Live logs active/);
201
+ const auditDir=path.join(fx.state,'audit');
202
+ const runtimeLogs=path.join(fx.state,'runtime','logs');
203
+ await mkdir(auditDir,{recursive:true});
204
+ await mkdir(runtimeLogs,{recursive:true});
205
+ await writeFile(path.join(auditDir,'segment-00000001.jsonl'),[
206
+ JSON.stringify({seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'abcdef1234567890'}),
207
+ JSON.stringify({seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false}})
208
+ ].join('\n')+'\n','utf8');
209
+ await writeFile(path.join(runtimeLogs,'bridge.stdout.log'),[
210
+ '[TOOL IN ] 2026-09-16T00:00:00.000Z #000001 coding_tree {}',
211
+ '[TOOL OUT] 2026-09-16T00:00:00.001Z #000001 coding_tree {"is_error":false}'
212
+ ].join('\n')+'\n','utf8');
213
+ const deadline=Date.now()+3000;
214
+ while(Date.now()<deadline&&(!/\[AUDIT #2\] tool\.result coding_tree abcdef12/.test(output.stdout)||!/\[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_tree/.test(output.stdout))) await sleep(50);
215
+ assert.match(output.stdout,/\[AUDIT #1\] tool\.request coding_tree abcdef12/);
216
+ assert.match(output.stdout,/\[AUDIT #2\] tool\.result coding_tree abcdef12/);
217
+ assert.match(output.stdout,/\[BRIDGE\.STDOUT\] \[TOOL IN \].*coding_tree/);
218
+ assert.match(output.stdout,/\[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_tree/);
219
+ child.stdin.end();
220
+ const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
221
+ assert.equal(ended.timeout,undefined,'verbose remote session did not exit after input closed');
222
+ assert.equal(ended.code,0,output.stderr);
223
+ }finally{
224
+ if(child?.exitCode===null) child.kill();
225
+ await rm(fx.dir,{recursive:true,force:true});
226
+ }
227
+ });
228
+
124
229
  winTest('detached guardian revokes authority, parks, and removes the session marker after the owner is hard-killed',async()=>{
125
230
  const fx=await fixture();
126
231
  let child=null;
127
232
  try{
128
- child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['ignore','pipe','pipe'],windowsHide:true});
233
+ child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
129
234
  const output=await collect(child);
130
- const ready=await waitFor(fx.trace,commands=>commands.slice(0,9).join(',')==='start,armprocess,armcoding,armautonomous,armhost,processstatus,codingstatus,autonomousstatus,hoststatus');
131
- assert.deepEqual(ready.slice(0,9),[
132
- 'start','armprocess','armcoding','armautonomous','armhost',
235
+ const ready=await waitFor(fx.trace,commands=>commands.slice(0,8).join(',')==='start,armprocess,armcoding,armautonomous,processstatus,codingstatus,autonomousstatus,hoststatus');
236
+ assert.deepEqual(ready.slice(0,8),[
237
+ 'start','armprocess','armcoding','armautonomous',
133
238
  'processstatus','codingstatus','autonomousstatus','hoststatus'
134
239
  ]);
135
240
  const markerPath=path.join(fx.state,'runtime','remote-session.json');
@@ -164,7 +269,7 @@ winTest('detached guardian revokes authority, parks, and removes the session mar
164
269
  });
165
270
 
166
271
  winTest('bare remote rolls back authority and parks if one plane fails to arm',async()=>{
167
- const fx=await fixture({failCommand:'armhost'});
272
+ const fx=await fixture({failCommand:'armcoding'});
168
273
  try{
169
274
  const child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['ignore','pipe','pipe'],windowsHide:true});
170
275
  const output=await collect(child);
@@ -172,7 +277,7 @@ winTest('bare remote rolls back authority and parks if one plane fails to arm',a
172
277
  assert.equal(ended.timeout,undefined,'failed startup did not terminate');
173
278
  assert.notEqual(ended.code,0);
174
279
  const commands=await traceCommands(fx.trace);
175
- assert.deepEqual(commands.slice(0,5),['start','armprocess','armcoding','armautonomous','armhost']);
280
+ assert.deepEqual(commands.slice(0,3),['start','armprocess','armcoding']);
176
281
  assert.deepEqual(commands.slice(-5),['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park']);
177
282
  assert.doesNotMatch(output.stdout,/Live logs/i);
178
283
  }finally{await rm(fx.dir,{recursive:true,force:true});}
@@ -10,6 +10,7 @@ import {
10
10
  loadPowerShellDataFile,
11
11
  parseUpdateArgs,
12
12
  prepareNamedTunnelCloudSpec,
13
+ readControllerStartFailure,
13
14
  runControllerStartNoCapture
14
15
  } from '../scripts/runtime-self-update.mjs';
15
16
  import * as runtimeUpdate from '../scripts/runtime-self-update.mjs';
@@ -31,10 +32,12 @@ test('R32 updater loads controller data with Windows PowerShell modules isolated
31
32
  }
32
33
  });
33
34
 
34
- test('R32 updater applies the isolated Windows PowerShell environment to detached controller starts', async () => {
35
+ test('R36 updater keeps detached start semantics and binds controller sidecar diagnostics', async () => {
35
36
  const source=await readFile(new URL('../src/runtime-update.mjs',import.meta.url),'utf8');
36
37
  assert.match(source,/stdio:'ignore'/);
37
38
  assert.match(source,/env:commandEnvironment\(exe,env\?\?process\.env\)/);
39
+ assert.match(source,/readControllerStartFailure\(ctx\)/);
40
+ assert.match(source,/evidence_sha256/);
38
41
  assert.match(source,/for\(let attempt=1;attempt<=3;attempt\+=1\)/);
39
42
  });
40
43
 
@@ -74,6 +77,60 @@ test('R27 controller start transport returns while its long-lived descendant is
74
77
  assert.doesNotThrow(()=>process.kill(childPid,0),'controller start returned only after descendant exited');
75
78
  });
76
79
 
80
+ test('R36 controller start sidecar is schema-bound and hash-bound', async () => {
81
+ const base=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r36-start-evidence-'));
82
+ const controllerDir=path.join(base,'controller');
83
+ const runtime=path.join(controllerDir,'runtime');
84
+ await mkdir(runtime,{recursive:true});
85
+ await writeFile(path.join(controllerDir,'deadbyte-controller.ps1'),"param([string]$Command)\nexit 0\n");
86
+ const body={
87
+ schema:'deadbyte.controller-start-failure.v1',
88
+ command:'start',
89
+ failed_at_utc:'2026-09-18T00:00:00.000Z',
90
+ message:'R36_CONTROLLER_START_SENTINEL',
91
+ bridge_stdout_tail:'',
92
+ bridge_stderr_tail:'compact bridge failed',
93
+ cloud_stdout_tail:'',
94
+ cloud_stderr_tail:''
95
+ };
96
+ const bytes=Buffer.from(JSON.stringify(body),'utf8');
97
+ await writeFile(path.join(runtime,'controller-start-failure.json'),bytes);
98
+ const evidence=await readControllerStartFailure(legacyContext(base));
99
+ assert.equal(evidence.message,'R36_CONTROLLER_START_SENTINEL');
100
+ assert.equal(evidence.command,'start');
101
+ assert.equal(evidence.sha256,sha(bytes));
102
+ });
103
+
104
+ test('R36 updater preserves exact controller-start failure evidence before rollback', async () => {
105
+ assert.equal(typeof runtimeUpdate.preserveControllerStartFailure,'function');
106
+ const base=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r36-preserve-start-evidence-'));
107
+ const controllerDir=path.join(base,'controller');
108
+ const runtime=path.join(controllerDir,'runtime');
109
+ const evidenceDir=path.join(base,'evidence','updates','candidate');
110
+ await mkdir(runtime,{recursive:true});
111
+ await writeFile(path.join(controllerDir,'deadbyte-controller.ps1'),"param([string]$Command)\nexit 0\n");
112
+ const body={
113
+ schema:'deadbyte.controller-start-failure.v1',
114
+ command:'start',
115
+ failed_at_utc:'2026-09-18T00:00:00.000Z',
116
+ message:'R36_PRESERVE_SENTINEL',
117
+ bridge_stdout_tail:'bridge-out',
118
+ bridge_stderr_tail:'bridge-err',
119
+ cloud_stdout_tail:'',
120
+ cloud_stderr_tail:''
121
+ };
122
+ const bytes=Buffer.from(JSON.stringify(body),'utf8');
123
+ const source=path.join(runtime,'controller-start-failure.json');
124
+ await writeFile(source,bytes);
125
+ const preserved=await runtimeUpdate.preserveControllerStartFailure(legacyContext(base),evidenceDir);
126
+ assert.equal(preserved.sha256,sha(bytes));
127
+ assert.equal(preserved.message,'R36_PRESERVE_SENTINEL');
128
+ assert.equal(preserved.path,path.join(evidenceDir,'controller-start-failure.json'));
129
+ assert.deepEqual(await readFile(preserved.path),bytes);
130
+ await writeFile(source,Buffer.from('destroyed-after-snapshot','utf8'));
131
+ assert.deepEqual(await readFile(preserved.path),bytes,'rollback/runtime restart must not mutate preserved evidence');
132
+ });
133
+
77
134
  test('R28 slot-update CLI binds direct cloudflared plus external token file as one pinned contract', () => {
78
135
  const base=['--stage','stage','--development-root','dev','--expected-version','0.8.4','--expected-manifest',hex('a')];
79
136
  assert.throws(() => parseUpdateArgs([...base,'--cloud-cloudflared','C:/cloudflared.exe']), /named tunnel bootstrap requires all|cloud/i);
@@ -206,6 +263,40 @@ test('R31 slot-update CLI binds process-policy bootstrap and machine-FS enable e
206
263
  assert.equal(parsed.enableMachineFs,true);
207
264
  });
208
265
 
266
+ test('R35 slot-update CLI binds semantic LSP config as one exact path plus SHA-256 pair', () => {
267
+ const base=['--stage','stage','--development-root','dev','--expected-version','0.9.0','--expected-manifest',hex('a')];
268
+ assert.throws(() => parseUpdateArgs([...base,'--semantic-lsp-config','C:/candidate/semantic.json']), /semantic LSP config.*pair/i);
269
+ assert.throws(() => parseUpdateArgs([...base,'--semantic-lsp-config-sha256',hex('b')]), /semantic LSP config.*pair/i);
270
+ const parsed=parseUpdateArgs([...base,'--semantic-lsp-config','C:/candidate/semantic.json','--semantic-lsp-config-sha256',hex('b')]);
271
+ assert.equal(parsed.semanticLspBootstrap.path,path.resolve('C:/candidate/semantic.json'));
272
+ assert.equal(parsed.semanticLspBootstrap.sha256,hex('b'));
273
+ });
274
+
275
+ test('R35 semantic LSP bootstrap accepts only exact pinned semantic config bytes', async () => {
276
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r35-semantic-bootstrap-'));
277
+ const file=path.join(root,'semantic.json');
278
+ const config={schema:'deadbyte.semantic-lsp-config.v1',servers:[]};
279
+ const bytes=Buffer.from(`${JSON.stringify(config)}\n`,'utf8');
280
+ await writeFile(file,bytes);
281
+ assert.equal(typeof runtimeUpdate.prepareSemanticLspConfigBootstrap,'function');
282
+ const accepted=await runtimeUpdate.prepareSemanticLspConfigBootstrap({path:file,sha256:sha(bytes)});
283
+ assert.equal(accepted.path,path.resolve(file));
284
+ assert.equal(accepted.sha256,sha(bytes));
285
+ await assert.rejects(runtimeUpdate.prepareSemanticLspConfigBootstrap({path:file,sha256:hex('f')}),/semantic LSP config.*SHA-256 mismatch/i);
286
+ const bad=path.join(root,'bad.json');
287
+ const badBytes=Buffer.from(`${JSON.stringify({schema:'wrong',servers:[]})}\n`,'utf8');
288
+ await writeFile(bad,badBytes);
289
+ await assert.rejects(runtimeUpdate.prepareSemanticLspConfigBootstrap({path:bad,sha256:sha(badBytes)}),/semantic LSP config schema/i);
290
+ });
291
+
292
+ test('R35 updater threads pinned semantic LSP config into successor generation', async () => {
293
+ const source=await readFile(new URL('../src/runtime-update.mjs',import.meta.url),'utf8');
294
+ assert.match(source,/prepareSemanticLspConfigBootstrap\(semanticLspBootstrap\)/);
295
+ assert.match(source,/SemanticLspConfigFile=semanticBootstrap\.path/);
296
+ assert.match(source,/SemanticLspConfigSha256=semanticBootstrap\.sha256/);
297
+ assert.match(source,/semanticLspBootstrap:args\.semanticLspBootstrap/);
298
+ });
299
+
209
300
  test('R32 slot-update CLI enables observation only by explicit flag', () => {
210
301
  const base=['--stage','stage','--development-root','dev','--expected-version','0.8.6','--expected-manifest',hex('a')];
211
302
  const plain=parseUpdateArgs(base);
@@ -215,6 +306,35 @@ test('R32 slot-update CLI enables observation only by explicit flag', () => {
215
306
  assert.throws(() => parseUpdateArgs([...base,'--enable-observation','--enable-observation']),/duplicate self-update argument/i);
216
307
  });
217
308
 
309
+ test('R34 slot-update CLI enables the out-of-band supervisor only by explicit flag', () => {
310
+ const base=['--stage','stage','--development-root','dev','--expected-version','0.8.11','--expected-manifest',hex('a')];
311
+ const plain=parseUpdateArgs(base);
312
+ assert.equal(plain.enableAutonomousSupervisor,false);
313
+ const enabled=parseUpdateArgs([...base,'--enable-autonomous-supervisor']);
314
+ assert.equal(enabled.enableAutonomousSupervisor,true);
315
+ assert.throws(() => parseUpdateArgs([...base,'--enable-autonomous-supervisor','--enable-autonomous-supervisor']),/duplicate self-update argument/i);
316
+ });
317
+
318
+ test('R34 supervisor bootstrap derives exact release-bound script identity from trusted Bridge executable', async () => {
319
+ assert.equal(typeof runtimeUpdate.prepareAutonomousSupervisorSpec,'function');
320
+ const base=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r34-supervisor-bootstrap-'));
321
+ const release=path.join(base,'release'),src=path.join(release,'src'); await mkdir(src,{recursive:true});
322
+ const script=Buffer.from('console.log("supervisor-r34")\n','utf8');
323
+ await writeFile(path.join(src,'autonomous-supervisor-host.mjs'),script);
324
+ const nodeHash=sha(await readFile(process.execPath));
325
+ const config={AutonomousRuntimeEnabled:true,AutonomousSupervisorEnabled:false,
326
+ Bridge:{FilePath:process.execPath,FileSha256:nodeHash}};
327
+ const bound=await runtimeUpdate.prepareAutonomousSupervisorSpec(config,{releaseRoot:release,enable:true});
328
+ assert.equal(bound.AutonomousSupervisorEnabled,true);
329
+ assert.deepEqual(bound.Supervisor,{
330
+ FilePath:process.execPath,FileSha256:nodeHash,Arguments:'src\\autonomous-supervisor-host.mjs',
331
+ WorkingDirectory:path.resolve(release),ScriptPath:path.join(path.resolve(release),'src','autonomous-supervisor-host.mjs'),ScriptSha256:sha(script)
332
+ });
333
+ const untouched=await runtimeUpdate.prepareAutonomousSupervisorSpec(config,{releaseRoot:release,enable:false});
334
+ assert.equal(untouched.AutonomousSupervisorEnabled,false);
335
+ assert.equal(untouched.Supervisor,undefined);
336
+ });
337
+
218
338
  test('R31 process-policy bootstrap accepts only an exact pinned enabled process policy', async () => {
219
339
  const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r31-process-bootstrap-'));
220
340
  const file=path.join(root,'process-policy.json');
@@ -0,0 +1,29 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { createSemanticBackendRegistry } from '../src/semantic-backend-registry.mjs';
4
+
5
+ const backend=(id,extensions)=>({id,extensions:new Set(extensions),outline(){},definition(){},references(){},replaceSymbol(){},diagnostics(){}});
6
+
7
+ test('semantic backend registry resolves normalized extensions and exposes stable languages',()=>{
8
+ const ts=backend('typescript',['.ts','.tsx']);
9
+ const py=backend('python',['.py']);
10
+ const registry=createSemanticBackendRegistry({backends:[py,ts]});
11
+ assert.equal(registry.backendForPath('SRC/MAIN.TS'),ts);
12
+ assert.equal(registry.backendForPath('pkg/mod.py'),py);
13
+ assert.deepEqual(registry.languages(),[
14
+ {id:'python',extensions:['.py']},
15
+ {id:'typescript',extensions:['.ts','.tsx']}
16
+ ]);
17
+ });
18
+
19
+ test('semantic backend registry fails closed for unsupported languages',()=>{
20
+ const registry=createSemanticBackendRegistry({backends:[backend('typescript',['.ts'])]});
21
+ assert.throws(()=>registry.backendForPath('main.rs'),/unsupported semantic language: \.rs/i);
22
+ assert.throws(()=>registry.backendForPath('README'),/unsupported semantic language: <none>/i);
23
+ });
24
+
25
+ test('semantic backend registry rejects duplicate ids, extension ownership, and incomplete backends',()=>{
26
+ assert.throws(()=>createSemanticBackendRegistry({backends:[backend('a',['.x']),backend('a',['.y'])]}),/duplicate semantic backend id/i);
27
+ assert.throws(()=>createSemanticBackendRegistry({backends:[backend('a',['.x']),backend('b',['.X'])]}),/semantic extension.*already owned/i);
28
+ assert.throws(()=>createSemanticBackendRegistry({backends:[{id:'bad',extensions:new Set(['.x'])}]}),/missing method.*outline/i);
29
+ });
@@ -0,0 +1,66 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { createHash } from 'node:crypto';
4
+ import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { Client } from '@modelcontextprotocol/client';
9
+ import { StdioClientTransport, getDefaultEnvironment } from '@modelcontextprotocol/client/stdio';
10
+ import { generateTrustKeypair } from '../src/trust.mjs';
11
+ import { loadCodingPolicy } from '../src/coding-plane.mjs';
12
+
13
+ const here=path.dirname(fileURLToPath(import.meta.url));
14
+ const repoRoot=path.resolve(here,'..');
15
+ const serverPath=path.join(repoRoot,'src','mcp-server.mjs');
16
+ const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
17
+ const sha256File=async file=>sha256(await readFile(file));
18
+ function structured(value,label){if(value.isError)throw new Error(`${label}: ${JSON.stringify(value.structuredContent??value.content)}`);return value.structuredContent;}
19
+
20
+ async function fixture(){
21
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-semantic-'));
22
+ const project=path.join(root,'project'); const trust=path.join(root,'trust');
23
+ await mkdir(project); await mkdir(trust);
24
+ const keys=await generateTrustKeypair({privateKeyPath:path.join(trust,'private.pem'),publicKeyPath:path.join(trust,'public.pem')});
25
+ const math=`export function add(a: number, b: number) {\n return a + b;\n}\n\nexport function twice(x: number) {\n return add(x, x);\n}\n`;
26
+ const main=`import { add } from './math.js';\nexport const total = add(2, 3);\n`;
27
+ await writeFile(path.join(project,'math.ts'),math,'utf8'); await writeFile(path.join(project,'main.ts'),main,'utf8');
28
+ await writeFile(path.join(project,'tsconfig.json'),JSON.stringify({compilerOptions:{target:'ES2022',module:'NodeNext',moduleResolution:'NodeNext',strict:true},include:['*.ts']},null,2),'utf8');
29
+ const policyPath=path.join(root,'coding-policy.json'); const leasePath=path.join(root,'coding-lease.json');
30
+ await writeFile(policyPath,JSON.stringify({schema:'deadbyte.coding-policy.v1',enabled:true,lease_file:leasePath,evidence_dir:path.join(root,'evidence'),roots:{project:{path:project,read:true,write:true,exec:true,deny_paths:['.git','node_modules']}},commands:{node_script:{kind:'script',executable:process.execPath,executable_sha256:await sha256File(process.execPath),root_ids:['project'],prefix_args:[],extensions:['.mjs','.js'],timeout_ms:30000,max_output_bytes:262144}},max_read_bytes:524288,max_write_bytes:2097152},null,2),'utf8');
31
+ const policy=await loadCodingPolicy(policyPath);
32
+ await writeFile(leasePath,JSON.stringify({schema:'deadbyte.coding-lease.v1',policy_sha256:policy.policy_sha256,instance_nonce:'c'.repeat(64),root_ids:['project'],armed_at_utc:new Date().toISOString(),expires_at_utc:new Date(Date.now()+3600000).toISOString()}),'utf8');
33
+ const client=new Client({name:'deadbyte-semantic-test',version:'0.8.11'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
34
+ const transport=new StdioClientTransport({command:process.execPath,args:[serverPath],cwd:repoRoot,env:{...getDefaultEnvironment(),DEADBYTE_SIGNING_KEY:keys.privateKeyPath,DEADBYTE_VERIFY_KEY:keys.publicKeyPath,DEADBYTE_CODING_RUNTIME:'1',DEADBYTE_CODING_POLICY:policyPath},stderr:'pipe'});
35
+ return {root,project,client,transport,math,main};
36
+ }
37
+
38
+ test('semantic tools provide outline, definition, references and receipt-backed edit by symbol',async()=>{
39
+ const f=await fixture();
40
+ try{
41
+ await f.client.connect(f.transport);
42
+ const names=new Set((await f.client.listTools()).tools.map(t=>t.name));
43
+ for(const name of ['coding_symbol_outline','coding_symbol_definition','coding_symbol_references','coding_symbol_replace']) assert.ok(names.has(name),`missing semantic tool ${name}`);
44
+
45
+ const outline=structured(await f.client.callTool({name:'coding_symbol_outline',arguments:{root_id:'project',path:'math.ts',max_symbols:100}}),'outline');
46
+ assert.equal(outline.status,'ok');
47
+ const add=outline.symbols.find(s=>s.name==='add'&&s.kind==='function');
48
+ assert.ok(add,'add function missing from outline'); assert.match(add.symbol_id,/^[0-9a-f]{64}$/);
49
+
50
+ const useColumn=f.main.split('\n')[1].indexOf('add');
51
+ const definition=structured(await f.client.callTool({name:'coding_symbol_definition',arguments:{root_id:'project',path:'main.ts',line:1,column:useColumn,max_results:20}}),'definition');
52
+ assert.ok(definition.locations.some(x=>x.path==='math.ts'&&x.name==='add'));
53
+
54
+ const references=structured(await f.client.callTool({name:'coding_symbol_references',arguments:{root_id:'project',path:'math.ts',line:add.name_start_line,column:add.name_start_column,max_results:50}}),'references');
55
+ assert.ok(references.locations.some(x=>x.path==='main.ts'));
56
+ assert.ok(references.locations.some(x=>x.path==='math.ts'&&x.start_line===5));
57
+
58
+ const before=structured(await f.client.callTool({name:'coding_file_read',arguments:{root_id:'project',path:'math.ts',encoding:'utf8'}}),'before');
59
+ const replacement='export function add(a: number, b: number) {\n return a - b;\n}';
60
+ const edited=structured(await f.client.callTool({name:'coding_symbol_replace',arguments:{root_id:'project',path:'math.ts',symbol_id:add.symbol_id,new_body:replacement,expected_sha256:before.sha256}}),'replace-symbol');
61
+ assert.equal(edited.status,'committed'); assert.equal(edited.symbol_name,'add');
62
+ const verified=structured(await f.client.callTool({name:'coding_receipt_verify',arguments:{receipt_id:edited.receipt_id}}),'receipt');
63
+ assert.equal(verified.ok,true); assert.equal(verified.signature_valid,true);
64
+ assert.match(await readFile(path.join(f.project,'math.ts'),'utf8'),/return a - b/);
65
+ } finally {await f.client.close().catch(()=>{}); await rm(f.root,{recursive:true,force:true}).catch(()=>{});}
66
+ });
@@ -0,0 +1,108 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { createHash } from 'node:crypto';
4
+ import { mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { createSemanticLspBackend } from '../src/semantic-lsp-backend.mjs';
9
+
10
+ const here=path.dirname(fileURLToPath(import.meta.url));
11
+ const fixture=path.join(here,'fixtures','lsp-framed-server.mjs');
12
+ const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
13
+ const nodeSha=sha256(await readFile(process.execPath));
14
+
15
+ async function makeFixture(){
16
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-lsp-backend-'));
17
+ const source='export function alpha() {}\n';
18
+ await writeFile(path.join(root,'main.foo'),source,'utf8');
19
+ const codingRuntime={
20
+ policy:{roots:{project:{real_path:root,read:true,write:true,exec:false,deny_paths:['denied']}}},
21
+ async sessionStatus(){return {armed:true,reason:'standing-grant',root_ids:['project']};},
22
+ async fileRead({rootId,relativePath}){assert.equal(rootId,'project');const content=await readFile(path.join(root,relativePath),'utf8');return {status:'ok',content,sha256:sha256(Buffer.from(content,'utf8'))};},
23
+ async textReplace({rootId,relativePath,oldString,newString,expectedSha256,expectedReplacements}){
24
+ assert.equal(rootId,'project');assert.equal(expectedReplacements,1);
25
+ const file=path.join(root,relativePath);const before=await readFile(file,'utf8');assert.equal(sha256(Buffer.from(before)),expectedSha256);
26
+ const count=before.split(oldString).length-1;assert.equal(count,1);const after=before.replace(oldString,newString);await writeFile(file,after,'utf8');
27
+ return {status:'committed',receipt_id:'f'.repeat(24),sha256:sha256(Buffer.from(after))};
28
+ }
29
+ };
30
+ const backend=createSemanticLspBackend({id:'fixture-lsp',extensions:['.foo'],codingRuntime,server:{executable_path:process.execPath,executable_sha256:nodeSha,args:[fixture],initialization_options:{fixture:true},request_timeout_ms:1000,max_message_bytes:131072}});
31
+ return {root,source,codingRuntime,backend};
32
+ }
33
+
34
+ test('semantic LSP backend normalizes outline definition references diagnostics and receipt-path replacement',async()=>{
35
+ const f=await makeFixture();
36
+ try{
37
+ const outline=await f.backend.outline({rootId:'project',relativePath:'main.foo',maxSymbols:10});
38
+ assert.equal(outline.engine,'fixture-lsp');assert.equal(outline.symbols.length,1);
39
+ const symbol=outline.symbols[0];assert.equal(symbol.name,'alpha');assert.match(symbol.symbol_id,/^[0-9a-f]{64}$/);
40
+ const def=await f.backend.definition({rootId:'project',relativePath:'main.foo',line:0,column:18,maxResults:10});
41
+ assert.equal(def.locations[0].path,'main.foo');assert.equal(def.locations[0].start_column,16);
42
+ const refs=await f.backend.references({rootId:'project',relativePath:'main.foo',line:0,column:18,maxResults:10});
43
+ assert.equal(refs.locations[0].path,'main.foo');
44
+ const diagnostics=await f.backend.diagnostics({rootId:'project',relativePath:'main.foo',maxResults:10});
45
+ assert.equal(diagnostics.diagnostics[0].message,'fixture diagnostic');
46
+ assert.match(diagnostics.file_sha256,/^[0-9a-f]{64}$/); assert.match(diagnostics.result_sha256,/^[0-9a-f]{64}$/);
47
+ const implementations=await f.backend.implementations({rootId:'project',relativePath:'main.foo',line:0,column:18,maxResults:10});
48
+ assert.equal(implementations.status,'ok'); assert.equal(implementations.locations[0].path,'main.foo'); assert.match(implementations.result_sha256,/^[0-9a-f]{64}$/);
49
+ const unsupportedImpl=await f.backend.implementations({rootId:'project',relativePath:'main.foo',line:0,column:999,maxResults:10});
50
+ assert.equal(unsupportedImpl.status,'unsupported'); assert.equal(unsupportedImpl.capability,'implementations');
51
+ const rename=await f.backend.renameEdits({rootId:'project',relativePath:'main.foo',line:0,column:18,newName:'gamma'});
52
+ assert.equal(rename.status,'ok'); assert.deepEqual(rename.edits,[{path:'main.foo',start:16,length:5,new_text:'gamma'}]);
53
+ const unsupportedRename=await f.backend.renameEdits({rootId:'project',relativePath:'main.foo',line:0,column:18,newName:'UNSUPPORTED'});
54
+ assert.equal(unsupportedRename.status,'unsupported'); assert.equal(unsupportedRename.capability,'rename_preview');
55
+ const before=await f.codingRuntime.fileRead({rootId:'project',relativePath:'main.foo'});
56
+ const edited=await f.backend.replaceSymbol({rootId:'project',relativePath:'main.foo',symbolId:symbol.symbol_id,newBody:'export function beta() {}',expectedSha256:before.sha256});
57
+ assert.equal(edited.status,'committed');assert.equal(edited.symbol_name,'alpha');assert.equal(edited.engine,'fixture-lsp');
58
+ assert.equal(await readFile(path.join(f.root,'main.foo'),'utf8'),'export function beta() {}\n');
59
+ } finally {await rm(f.root,{recursive:true,force:true});}
60
+ });
61
+
62
+ test('semantic LSP backend rejects targets outside lease/root policy before launching server',async()=>{
63
+ const f=await makeFixture();
64
+ try{
65
+ await assert.rejects(f.backend.outline({rootId:'missing',relativePath:'main.foo',maxSymbols:10}),/outside active lease/i);
66
+ await assert.rejects(f.backend.outline({rootId:'project',relativePath:'denied/main.foo',maxSymbols:10}),/denied/i);
67
+ } finally {await rm(f.root,{recursive:true,force:true});}
68
+ });
69
+
70
+ test('semantic LSP backend forwards dependency pins before launching server',async()=>{
71
+ const f=await makeFixture();
72
+ try{
73
+ const backend=createSemanticLspBackend({id:'fixture-pinned',extensions:['.foo'],codingRuntime:f.codingRuntime,server:{executable_path:process.execPath,executable_sha256:nodeSha,args:[fixture],dependencies:[{path:fixture,expectedSha256:'0'.repeat(64)}],request_timeout_ms:1000,max_message_bytes:131072}});
74
+ await assert.rejects(backend.outline({rootId:'project',relativePath:'main.foo',maxSymbols:10}),/LSP dependency SHA-256 mismatch/i);
75
+ } finally {await rm(f.root,{recursive:true,force:true});}
76
+ });
77
+
78
+ test('semantic LSP backend separates engine id from LSP language id',async()=>{
79
+ const f=await makeFixture();
80
+ try{
81
+ const fixtureSha=sha256(await readFile(fixture));
82
+ const backend=createSemanticLspBackend({id:'fixture-engine',extensions:['.foo'],codingRuntime:f.codingRuntime,server:{language_id:'fixture-language',executable_path:process.execPath,executable_sha256:nodeSha,args:[fixture],dependencies:[{path:fixture,expectedSha256:fixtureSha}],initialization_options:{expectedLanguageId:'fixture-language'},request_timeout_ms:1000,max_message_bytes:131072}});
83
+ const outline=await backend.outline({rootId:'project',relativePath:'main.foo',maxSymbols:10});
84
+ assert.equal(outline.engine,'fixture-engine');
85
+ assert.equal(outline.symbols[0].name,'alpha');
86
+ } finally {await rm(f.root,{recursive:true,force:true});}
87
+ });
88
+
89
+ test('semantic LSP backend pre-opens bounded same-language project files for deterministic cross-file navigation',async()=>{
90
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-lsp-project-'));
91
+ await writeFile(path.join(root,'main.foo'),'export function main() { return alpha(); }\n','utf8');
92
+ await writeFile(path.join(root,'peer.foo'),'export function alpha() { return 1; }\n','utf8');
93
+ const codingRuntime={
94
+ policy:{roots:{project:{real_path:root,read:true,write:true,exec:false,deny_paths:[]}}},
95
+ async sessionStatus(){return {armed:true,reason:'standing-grant',root_ids:['project']};},
96
+ async tree(){return {truncated:false,entries:[{type:'file',path:'main.foo'},{type:'file',path:'peer.foo'}]};},
97
+ async fileRead({relativePath}){const content=await readFile(path.join(root,relativePath),'utf8');return {status:'ok',content,sha256:sha256(Buffer.from(content,'utf8'))};},
98
+ async textReplace(){throw new Error('not used');}
99
+ };
100
+ try{
101
+ const fixtureSha=sha256(await readFile(fixture));
102
+ const backend=createSemanticLspBackend({id:'fixture-project',extensions:['.foo'],codingRuntime,server:{language_id:'fixture-language',executable_path:process.execPath,executable_sha256:nodeSha,args:[fixture],dependencies:[{path:fixture,expectedSha256:fixtureSha}],initialization_options:{expectedLanguageId:'fixture-language',requiredOpenCount:2},request_timeout_ms:1000,max_message_bytes:131072}});
103
+ const definition=await backend.definition({rootId:'project',relativePath:'main.foo',line:0,column:18,maxResults:10});
104
+ assert.ok(definition.locations.some(item=>item.path==='peer.foo'),JSON.stringify(definition.locations));
105
+ const references=await backend.references({rootId:'project',relativePath:'main.foo',line:0,column:18,maxResults:10});
106
+ assert.ok(references.locations.some(item=>item.path==='peer.foo'),JSON.stringify(references.locations));
107
+ } finally {await rm(root,{recursive:true,force:true});}
108
+ });