deadbyte-mcp 0.8.10 → 0.9.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 (347) hide show
  1. package/CONTEXT.md +41 -0
  2. package/MANIFEST.SHA256 +346 -82
  3. package/R34-BASELINE.json +9 -0
  4. package/README.txt +135 -9
  5. package/bench/fixtures/corpus.json +17 -0
  6. package/bin/WORKER-REGISTRY.txt +3 -3
  7. package/bin/appcontainer-stage.exe +0 -0
  8. package/bin/appcontainer-stage.obj +0 -0
  9. package/bin/bootstrap-advapi32.exe +0 -0
  10. package/bin/bootstrap-advapi32.obj +0 -0
  11. package/bin/bootstrap-exitcode.exe +0 -0
  12. package/bin/bootstrap-exitcode.obj +0 -0
  13. package/bin/bootstrap-kernel32.exe +0 -0
  14. package/bin/bootstrap-kernel32.obj +0 -0
  15. package/bin/child-control-probe.exe +0 -0
  16. package/bin/child-control-probe.obj +0 -0
  17. package/bin/child-control-stage.exe +0 -0
  18. package/bin/child-control-stage.obj +0 -0
  19. package/bin/contained-reverse-worker.exe +0 -0
  20. package/bin/contained-reverse-worker.obj +0 -0
  21. package/bin/contained-transform-worker.exe +0 -0
  22. package/bin/contained-transform-worker.obj +0 -0
  23. package/bin/containment-probe.exe +0 -0
  24. package/bin/containment-probe.obj +0 -0
  25. package/bin/deadbyte-contain.exe +0 -0
  26. package/bin/deadbyte-contain.obj +0 -0
  27. package/bin/deadbyte-exec.exe +0 -0
  28. package/bin/deadbyte-exec.obj +0 -0
  29. package/bin/deadbyte-process-host.exe +0 -0
  30. package/bin/deadbyte-process-host.obj +0 -0
  31. package/bin/deadbyte-tunnel-host.exe +0 -0
  32. package/bin/deadbyte-tunnel-host.obj +0 -0
  33. package/controller/README.TXT +10 -4
  34. package/controller/deadbyte-controller.config.psd1.example +14 -0
  35. package/controller/deadbyte-controller.ps1 +144 -19
  36. package/controller/deadbyte-process-policy.json +5 -5
  37. package/controller/deadbyte-semantic-lsp-config.json +95 -0
  38. package/docs/ADR-0001-PRODUCTION-BASELINE-SEAMS.md +29 -0
  39. package/docs/ARCHITECTURE.md +6 -5
  40. package/docs/superpowers/plans/2026-09-16-deadbyte-loop-engine.md +846 -0
  41. package/docs/superpowers/plans/2026-09-17-r35-production-successor.md +408 -0
  42. package/docs/superpowers/specs/2026-09-16-deadbyte-loop-engine-design.md +435 -0
  43. package/docs/superpowers/specs/2026-09-17-r35-production-successor-design.md +220 -0
  44. package/node_modules/typescript/LICENSE.txt +55 -0
  45. package/node_modules/typescript/README.md +50 -0
  46. package/node_modules/typescript/SECURITY.md +41 -0
  47. package/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
  48. package/node_modules/typescript/bin/tsc +2 -0
  49. package/node_modules/typescript/bin/tsserver +2 -0
  50. package/node_modules/typescript/lib/_tsc.js +133818 -0
  51. package/node_modules/typescript/lib/_tsserver.js +659 -0
  52. package/node_modules/typescript/lib/_typingsInstaller.js +222 -0
  53. package/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +2122 -0
  54. package/node_modules/typescript/lib/de/diagnosticMessages.generated.json +2122 -0
  55. package/node_modules/typescript/lib/es/diagnosticMessages.generated.json +2122 -0
  56. package/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +2122 -0
  57. package/node_modules/typescript/lib/it/diagnosticMessages.generated.json +2122 -0
  58. package/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +2122 -0
  59. package/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +2122 -0
  60. package/node_modules/typescript/lib/lib.d.ts +22 -0
  61. package/node_modules/typescript/lib/lib.decorators.d.ts +384 -0
  62. package/node_modules/typescript/lib/lib.decorators.legacy.d.ts +22 -0
  63. package/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +41 -0
  64. package/node_modules/typescript/lib/lib.dom.d.ts +39429 -0
  65. package/node_modules/typescript/lib/lib.dom.iterable.d.ts +571 -0
  66. package/node_modules/typescript/lib/lib.es2015.collection.d.ts +147 -0
  67. package/node_modules/typescript/lib/lib.es2015.core.d.ts +597 -0
  68. package/node_modules/typescript/lib/lib.es2015.d.ts +28 -0
  69. package/node_modules/typescript/lib/lib.es2015.generator.d.ts +77 -0
  70. package/node_modules/typescript/lib/lib.es2015.iterable.d.ts +605 -0
  71. package/node_modules/typescript/lib/lib.es2015.promise.d.ts +81 -0
  72. package/node_modules/typescript/lib/lib.es2015.proxy.d.ts +128 -0
  73. package/node_modules/typescript/lib/lib.es2015.reflect.d.ts +144 -0
  74. package/node_modules/typescript/lib/lib.es2015.symbol.d.ts +46 -0
  75. package/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +326 -0
  76. package/node_modules/typescript/lib/lib.es2016.array.include.d.ts +116 -0
  77. package/node_modules/typescript/lib/lib.es2016.d.ts +21 -0
  78. package/node_modules/typescript/lib/lib.es2016.full.d.ts +23 -0
  79. package/node_modules/typescript/lib/lib.es2016.intl.d.ts +31 -0
  80. package/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +21 -0
  81. package/node_modules/typescript/lib/lib.es2017.d.ts +26 -0
  82. package/node_modules/typescript/lib/lib.es2017.date.d.ts +31 -0
  83. package/node_modules/typescript/lib/lib.es2017.full.d.ts +23 -0
  84. package/node_modules/typescript/lib/lib.es2017.intl.d.ts +44 -0
  85. package/node_modules/typescript/lib/lib.es2017.object.d.ts +49 -0
  86. package/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +135 -0
  87. package/node_modules/typescript/lib/lib.es2017.string.d.ts +45 -0
  88. package/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +53 -0
  89. package/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +77 -0
  90. package/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +53 -0
  91. package/node_modules/typescript/lib/lib.es2018.d.ts +24 -0
  92. package/node_modules/typescript/lib/lib.es2018.full.d.ts +24 -0
  93. package/node_modules/typescript/lib/lib.es2018.intl.d.ts +83 -0
  94. package/node_modules/typescript/lib/lib.es2018.promise.d.ts +30 -0
  95. package/node_modules/typescript/lib/lib.es2018.regexp.d.ts +37 -0
  96. package/node_modules/typescript/lib/lib.es2019.array.d.ts +79 -0
  97. package/node_modules/typescript/lib/lib.es2019.d.ts +24 -0
  98. package/node_modules/typescript/lib/lib.es2019.full.d.ts +24 -0
  99. package/node_modules/typescript/lib/lib.es2019.intl.d.ts +23 -0
  100. package/node_modules/typescript/lib/lib.es2019.object.d.ts +33 -0
  101. package/node_modules/typescript/lib/lib.es2019.string.d.ts +37 -0
  102. package/node_modules/typescript/lib/lib.es2019.symbol.d.ts +24 -0
  103. package/node_modules/typescript/lib/lib.es2020.bigint.d.ts +765 -0
  104. package/node_modules/typescript/lib/lib.es2020.d.ts +27 -0
  105. package/node_modules/typescript/lib/lib.es2020.date.d.ts +42 -0
  106. package/node_modules/typescript/lib/lib.es2020.full.d.ts +24 -0
  107. package/node_modules/typescript/lib/lib.es2020.intl.d.ts +474 -0
  108. package/node_modules/typescript/lib/lib.es2020.number.d.ts +28 -0
  109. package/node_modules/typescript/lib/lib.es2020.promise.d.ts +47 -0
  110. package/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +99 -0
  111. package/node_modules/typescript/lib/lib.es2020.string.d.ts +44 -0
  112. package/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +41 -0
  113. package/node_modules/typescript/lib/lib.es2021.d.ts +23 -0
  114. package/node_modules/typescript/lib/lib.es2021.full.d.ts +24 -0
  115. package/node_modules/typescript/lib/lib.es2021.intl.d.ts +166 -0
  116. package/node_modules/typescript/lib/lib.es2021.promise.d.ts +48 -0
  117. package/node_modules/typescript/lib/lib.es2021.string.d.ts +33 -0
  118. package/node_modules/typescript/lib/lib.es2021.weakref.d.ts +78 -0
  119. package/node_modules/typescript/lib/lib.es2022.array.d.ts +121 -0
  120. package/node_modules/typescript/lib/lib.es2022.d.ts +25 -0
  121. package/node_modules/typescript/lib/lib.es2022.error.d.ts +75 -0
  122. package/node_modules/typescript/lib/lib.es2022.full.d.ts +24 -0
  123. package/node_modules/typescript/lib/lib.es2022.intl.d.ts +145 -0
  124. package/node_modules/typescript/lib/lib.es2022.object.d.ts +26 -0
  125. package/node_modules/typescript/lib/lib.es2022.regexp.d.ts +39 -0
  126. package/node_modules/typescript/lib/lib.es2022.string.d.ts +25 -0
  127. package/node_modules/typescript/lib/lib.es2023.array.d.ts +924 -0
  128. package/node_modules/typescript/lib/lib.es2023.collection.d.ts +21 -0
  129. package/node_modules/typescript/lib/lib.es2023.d.ts +22 -0
  130. package/node_modules/typescript/lib/lib.es2023.full.d.ts +24 -0
  131. package/node_modules/typescript/lib/lib.es2023.intl.d.ts +56 -0
  132. package/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +65 -0
  133. package/node_modules/typescript/lib/lib.es2024.collection.d.ts +29 -0
  134. package/node_modules/typescript/lib/lib.es2024.d.ts +26 -0
  135. package/node_modules/typescript/lib/lib.es2024.full.d.ts +24 -0
  136. package/node_modules/typescript/lib/lib.es2024.object.d.ts +29 -0
  137. package/node_modules/typescript/lib/lib.es2024.promise.d.ts +35 -0
  138. package/node_modules/typescript/lib/lib.es2024.regexp.d.ts +25 -0
  139. package/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +68 -0
  140. package/node_modules/typescript/lib/lib.es2024.string.d.ts +29 -0
  141. package/node_modules/typescript/lib/lib.es5.d.ts +4601 -0
  142. package/node_modules/typescript/lib/lib.es6.d.ts +23 -0
  143. package/node_modules/typescript/lib/lib.esnext.array.d.ts +35 -0
  144. package/node_modules/typescript/lib/lib.esnext.collection.d.ts +96 -0
  145. package/node_modules/typescript/lib/lib.esnext.d.ts +29 -0
  146. package/node_modules/typescript/lib/lib.esnext.decorators.d.ts +28 -0
  147. package/node_modules/typescript/lib/lib.esnext.disposable.d.ts +193 -0
  148. package/node_modules/typescript/lib/lib.esnext.error.d.ts +24 -0
  149. package/node_modules/typescript/lib/lib.esnext.float16.d.ts +445 -0
  150. package/node_modules/typescript/lib/lib.esnext.full.d.ts +24 -0
  151. package/node_modules/typescript/lib/lib.esnext.intl.d.ts +21 -0
  152. package/node_modules/typescript/lib/lib.esnext.iterator.d.ts +148 -0
  153. package/node_modules/typescript/lib/lib.esnext.promise.d.ts +34 -0
  154. package/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +25 -0
  155. package/node_modules/typescript/lib/lib.scripthost.d.ts +322 -0
  156. package/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +41 -0
  157. package/node_modules/typescript/lib/lib.webworker.d.ts +13150 -0
  158. package/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +23 -0
  159. package/node_modules/typescript/lib/lib.webworker.iterable.d.ts +340 -0
  160. package/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +2122 -0
  161. package/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +2122 -0
  162. package/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +2122 -0
  163. package/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +2122 -0
  164. package/node_modules/typescript/lib/tsc.js +8 -0
  165. package/node_modules/typescript/lib/tsserver.js +8 -0
  166. package/node_modules/typescript/lib/tsserverlibrary.d.ts +17 -0
  167. package/node_modules/typescript/lib/tsserverlibrary.js +21 -0
  168. package/node_modules/typescript/lib/typesMap.json +497 -0
  169. package/node_modules/typescript/lib/typescript.d.ts +11437 -0
  170. package/node_modules/typescript/lib/typescript.js +200276 -0
  171. package/node_modules/typescript/lib/typingsInstaller.js +8 -0
  172. package/node_modules/typescript/lib/watchGuard.js +53 -0
  173. package/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +2122 -0
  174. package/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +2122 -0
  175. package/node_modules/typescript/package.json +120 -0
  176. package/package.json +5 -3
  177. package/proof/CONTAINMENT-BUILD.txt +6 -6
  178. package/proof/R34-TASK8-SUPERVISOR-CHECKPOINT.json +29 -0
  179. package/proof/R34-TASK9-MCP-SURFACE-CHECKPOINT.json +28 -0
  180. package/scripts/capability-benchmark.mjs +27 -0
  181. package/scripts/deferred-slot-operation.mjs +4 -2
  182. package/scripts/final-closure-verify.mjs +10 -10
  183. package/scripts/final-closure.mjs +11 -11
  184. package/scripts/gate-windows.ps1 +3 -3
  185. package/scripts/release-parity.mjs +14 -14
  186. package/scripts/semantic-preflight.ps1 +73 -0
  187. package/scripts/tool-surface-snapshot.mjs +73 -0
  188. package/scripts/windows-gate-evidence.mjs +5 -5
  189. package/src/audit-verify.mjs +6 -2
  190. package/src/autonomous-action-reconcile.mjs +142 -0
  191. package/src/autonomous-context-engine.mjs +255 -0
  192. package/src/autonomous-live-state.mjs +17 -0
  193. package/src/autonomous-local-supervisor.mjs +249 -0
  194. package/src/autonomous-loop-state.mjs +304 -0
  195. package/src/autonomous-output-contracts.mjs +22 -3
  196. package/src/autonomous-plan.mjs +181 -0
  197. package/src/autonomous-planner-contracts.mjs +44 -0
  198. package/src/autonomous-planner.mjs +91 -6
  199. package/src/autonomous-policy.mjs +15 -2
  200. package/src/autonomous-progress.mjs +127 -0
  201. package/src/autonomous-runtime.mjs +601 -48
  202. package/src/autonomous-supervisor-host.mjs +70 -0
  203. package/src/autonomous-supervisor.mjs +31 -8
  204. package/src/capability-benchmark-runner.mjs +108 -0
  205. package/src/capability-benchmark.mjs +50 -0
  206. package/src/coding-mcp-tools.mjs +46 -3
  207. package/src/coding-output-contracts.mjs +45 -0
  208. package/src/context-provenance.mjs +86 -0
  209. package/src/deadbyte-cli.mjs +117 -25
  210. package/src/document-adapter.mjs +43 -0
  211. package/src/lsp-stdio-client.mjs +112 -0
  212. package/src/machine-fs-smoke-client.mjs +2 -1
  213. package/src/mcp-server.mjs +17 -3
  214. package/src/observation-smoke-client.mjs +3 -2
  215. package/src/operator-surface.mjs +37 -0
  216. package/src/provider-circuit.mjs +125 -0
  217. package/src/release-generation.mjs +44 -5
  218. package/src/remote-mcp-autonomous-smoke-client.mjs +53 -14
  219. package/src/remote-mcp-coding-smoke-client.mjs +5 -4
  220. package/src/remote-mcp-r24-disarmed-smoke-client.mjs +4 -2
  221. package/src/remote-mcp-r34-parity-client.mjs +177 -0
  222. package/src/remote-mcp-smoke-client.mjs +2 -1
  223. package/src/remote-result-journal.mjs +114 -0
  224. package/src/runtime-update.mjs +58 -8
  225. package/src/semantic-backend-registry.mjs +39 -0
  226. package/src/semantic-code.mjs +179 -0
  227. package/src/semantic-lsp-backend.mjs +183 -0
  228. package/src/semantic-lsp-config.mjs +112 -0
  229. package/src/tool-surface-ledger.mjs +92 -0
  230. package/src/version.mjs +1 -1
  231. package/test/audit-verify.test.mjs +1 -1
  232. package/test/autonomous-action-reconcile.test.mjs +106 -0
  233. package/test/autonomous-adversarial.test.mjs +149 -6
  234. package/test/autonomous-context-engine.test.mjs +181 -0
  235. package/test/autonomous-live-state.test.mjs +27 -0
  236. package/test/autonomous-local-supervisor.test.mjs +403 -0
  237. package/test/autonomous-loop-state.test.mjs +126 -0
  238. package/test/autonomous-loop-v2.test.mjs +105 -0
  239. package/test/autonomous-loop.test.mjs +79 -1
  240. package/test/autonomous-output-contract.test.mjs +54 -0
  241. package/test/autonomous-plan.test.mjs +101 -0
  242. package/test/autonomous-progress.test.mjs +106 -0
  243. package/test/autonomous-r34-e2e.test.mjs +338 -0
  244. package/test/autonomous-runtime.test.mjs +3 -3
  245. package/test/autonomous-supervisor-integration.test.mjs +48 -3
  246. package/test/capability-benchmark-runner.test.mjs +49 -0
  247. package/test/capability-benchmark.test.mjs +47 -0
  248. package/test/cli-entrypoint.test.mjs +12 -0
  249. package/test/coding-catalog-consistency.test.mjs +24 -0
  250. package/test/coding-plane.test.mjs +3 -3
  251. package/test/context-provenance.test.mjs +61 -0
  252. package/test/controller-r27.test.mjs +4 -3
  253. package/test/controller.test.mjs +52 -0
  254. package/test/core.test.mjs +1 -1
  255. package/test/deferred-slot-operation-behavior.test.mjs +5 -1
  256. package/test/deferred-slot-operation.test.mjs +2 -1
  257. package/test/document-adapter.test.mjs +23 -0
  258. package/test/fixtures/lsp-framed-server.mjs +33 -0
  259. package/test/fixtures/semantic/cpp/compile_commands.json +4 -0
  260. package/test/fixtures/semantic/cpp/lib.cpp +2 -0
  261. package/test/fixtures/semantic/cpp/lib.hpp +2 -0
  262. package/test/fixtures/semantic/cpp/main.cpp +2 -0
  263. package/test/fixtures/semantic/python/lib.py +2 -0
  264. package/test/fixtures/semantic/python/main.py +2 -0
  265. package/test/fixtures/semantic/rust/Cargo.lock +7 -0
  266. package/test/fixtures/semantic/rust/Cargo.toml +8 -0
  267. package/test/fixtures/semantic/rust/src/lib.rs +3 -0
  268. package/test/fixtures/semantic/rust/src/main.rs +5 -0
  269. package/test/fixtures/semantic/rust/src/math.rs +3 -0
  270. package/test/fixtures/semantic/rust/target/.rustc_info.json +1 -0
  271. package/test/fixtures/semantic/rust/target/CACHEDIR.TAG +3 -0
  272. package/test/fixtures/semantic/rust/target/debug/.cargo-lock +0 -0
  273. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/dep-test-lib-semantic_rust +0 -0
  274. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/invoked.timestamp +1 -0
  275. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/test-lib-semantic_rust +1 -0
  276. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/test-lib-semantic_rust.json +1 -0
  277. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/dep-test-bin-semantic_rust_bin +0 -0
  278. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/invoked.timestamp +1 -0
  279. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/test-bin-semantic_rust_bin +1 -0
  280. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/test-bin-semantic_rust_bin.json +1 -0
  281. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/dep-lib-semantic_rust +0 -0
  282. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/invoked.timestamp +1 -0
  283. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/lib-semantic_rust +1 -0
  284. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/lib-semantic_rust.json +1 -0
  285. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/bin-semantic_rust_bin +1 -0
  286. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/bin-semantic_rust_bin.json +1 -0
  287. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/dep-bin-semantic_rust_bin +0 -0
  288. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/invoked.timestamp +1 -0
  289. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust-4c168fa33c79d09c.rmeta +0 -0
  290. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust-6212ccd976aa3808.rmeta +0 -0
  291. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust_bin-5dcd474439c54a26.rmeta +0 -0
  292. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust_bin-d741378dccdef61c.rmeta +0 -0
  293. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust-4c168fa33c79d09c.d +5 -0
  294. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust-6212ccd976aa3808.d +5 -0
  295. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust_bin-5dcd474439c54a26.d +6 -0
  296. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust_bin-d741378dccdef61c.d +6 -0
  297. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/dep-graph.bin +0 -0
  298. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/query-cache.bin +0 -0
  299. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/work-products.bin +0 -0
  300. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc.lock +0 -0
  301. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/dep-graph.bin +0 -0
  302. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/metadata.rmeta +0 -0
  303. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/query-cache.bin +0 -0
  304. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/work-products.bin +0 -0
  305. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq.lock +0 -0
  306. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/dep-graph.bin +0 -0
  307. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/query-cache.bin +0 -0
  308. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/work-products.bin +0 -0
  309. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3.lock +0 -0
  310. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/dep-graph.bin +0 -0
  311. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/query-cache.bin +0 -0
  312. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/work-products.bin +0 -0
  313. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt.lock +0 -0
  314. package/test/fixtures/semantic/rust/target/flycheck0/stderr +1 -0
  315. package/test/fixtures/semantic/rust/target/flycheck0/stdout +5 -0
  316. package/test/fixtures/semantic/typescript/lib.ts +3 -0
  317. package/test/fixtures/semantic/typescript/main.ts +2 -0
  318. package/test/fixtures/tool-surface-stdio-server.mjs +14 -0
  319. package/test/helpers/autonomous-r34-fixture.mjs +120 -0
  320. package/test/lsp-stdio-client.test.mjs +72 -0
  321. package/test/multi-file-read.test.mjs +41 -0
  322. package/test/observation-integration.test.mjs +3 -3
  323. package/test/production-docs.test.mjs +48 -0
  324. package/test/prompts-resources.test.mjs +35 -0
  325. package/test/provider-circuit.test.mjs +93 -0
  326. package/test/public-autonomous-ingress-budget.test.mjs +28 -0
  327. package/test/r33-closeout-regression.test.mjs +3 -3
  328. package/test/r33-finalization.test.mjs +19 -16
  329. package/test/release-generation.test.mjs +23 -2
  330. package/test/release-version.test.mjs +24 -17
  331. package/test/remote-r24-catalog.test.mjs +5 -4
  332. package/test/remote-result-journal.test.mjs +58 -0
  333. package/test/remote-session-cli.test.mjs +112 -17
  334. package/test/runtime-self-update.test.mjs +63 -0
  335. package/test/semantic-backend-registry.test.mjs +29 -0
  336. package/test/semantic-code.test.mjs +66 -0
  337. package/test/semantic-lsp-backend.test.mjs +99 -0
  338. package/test/semantic-lsp-config.test.mjs +81 -0
  339. package/test/semantic-lsp-readiness.test.mjs +34 -0
  340. package/test/semantic-lsp-transient-empty.test.mjs +32 -0
  341. package/test/semantic-lsp-transient-null.test.mjs +31 -0
  342. package/test/semantic-multilang.test.mjs +72 -0
  343. package/test/semantic-runtime-routing.test.mjs +32 -0
  344. package/test/semantic-server-config-integration.test.mjs +66 -0
  345. package/test/tool-surface-ledger.test.mjs +59 -0
  346. package/test/tool-surface-snapshot.test.mjs +17 -0
  347. package/test/tracer-bullet.test.mjs +77 -0
@@ -1,14 +1,14 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import { readFile } from 'node:fs/promises';
4
- import { fileURLToPath } from 'node:url';
4
+ import { createHash } from 'node:crypto';
5
5
 
6
6
  const root = new URL('../', import.meta.url);
7
7
  const text = rel => readFile(new URL(rel, root), 'utf8');
8
8
 
9
- test('R33 patch successor release authority agrees on V0.8.10 / R33 identity', async () => {
9
+ test('R35 successor release authority agrees on V0.9.0 / R35 identity', async () => {
10
10
  const pkg = JSON.parse(await text('package.json'));
11
- const [version, controller, gate, readme, architecture, controllerReadme, deferred, parity, closure, closureVerify] = await Promise.all([
11
+ const [version, controller, gate, readme, architecture, controllerReadme, deferred, parity, closure, closureVerify, windowsGate, semanticConfig] = await Promise.all([
12
12
  text('src/version.mjs'),
13
13
  text('controller/deadbyte-controller.ps1'),
14
14
  text('scripts/gate-windows.ps1'),
@@ -16,20 +16,27 @@ test('R33 patch successor release authority agrees on V0.8.10 / R33 identity', a
16
16
  text('docs/ARCHITECTURE.md'),
17
17
  text('controller/README.TXT'),
18
18
  text('scripts/deferred-slot-operation.mjs'),
19
- text('src/remote-mcp-r33-parity-client.mjs'),
19
+ text('src/remote-mcp-r34-parity-client.mjs'),
20
20
  text('scripts/final-closure.mjs'),
21
- text('scripts/final-closure-verify.mjs')
21
+ text('scripts/final-closure-verify.mjs'),
22
+ text('scripts/windows-gate-evidence.mjs'),
23
+ text('controller/deadbyte-semantic-lsp-config.json')
22
24
  ]);
23
- assert.equal(pkg.version, '0.8.10');
24
- assert.match(version, /DEADBYTE_VERSION = '0\.8\.10'/);
25
- assert.match(controller, /CONTROLLER V0\.8\.10 \/ R33/);
26
- assert.match(gate, /DEADBYTE V0\.8\.10 \/ R33 WINDOWS BATCH GATE: PASS/);
27
- assert.match(readme, /^DEADBYTE MCP V0\.8\.10 \/ R33 FINAL MACHINE BASELINE$/m);
28
- assert.match(architecture, /^# DEADBYTE MCP V0\.8\.10 \/ R33 ARCHITECTURE$/m);
29
- assert.match(controllerReadme, /^DEADBYTE MCP V0\.8\.10 \/ R33 CONTROLLER$/m);
30
- assert.match(controllerReadme, /68-tool public catalog/);
31
- assert.match(deferred, /--expected-version','0\.8\.10'/);
32
- assert.match(parity, /version:'0\.8\.10'/);
33
- assert.match(closure, /version:'0\.8\.10'/);
34
- assert.match(closureVerify, /DEADBYTE V0\.8\.10 \/ R33 WINDOWS BATCH GATE: PASS/);
25
+ assert.equal(pkg.version, '0.9.0');
26
+ assert.match(version, /DEADBYTE_VERSION = '0\.9\.0'/);
27
+ assert.match(controller, /CONTROLLER V0\.9\.0 \/ R35/);
28
+ assert.match(gate, /DEADBYTE V0\.9\.0 \/ R35 WINDOWS BATCH GATE: PASS/);
29
+ assert.match(readme, /^DEADBYTE MCP V0\.9\.0 \/ R35 PRODUCTION BASELINE$/m);
30
+ assert.match(architecture, /^# DEADBYTE MCP V0\.9\.0 \/ R35 ARCHITECTURE$/m);
31
+ assert.match(controllerReadme, /^DEADBYTE MCP V0\.9\.0 \/ R35 CONTROLLER$/m);
32
+ assert.match(controllerReadme, /73-tool public catalog/);
33
+ assert.match(deferred, /--expected-version','0\.9\.0'/);
34
+ assert.match(parity, /version:'0\.9\.0'/);
35
+ assert.match(closure, /version:'0\.9\.0'/);
36
+ assert.match(closureVerify, /DEADBYTE V0\.9\.0 \/ R35 WINDOWS BATCH GATE: PASS/);
37
+ assert.match(windowsGate, /schema:'deadbyte\.r35-windows-gate\.v1'/);
38
+ assert.equal(createHash('sha256').update(Buffer.from(semanticConfig,'utf8')).digest('hex'), 'd274b099a298c1033fea8f1e8849751693bbc0448778d619400acb82d4f53a3b');
39
+ assert.match(deferred, /--semantic-lsp-config/);
40
+ assert.match(deferred, /--semantic-lsp-config-sha256/);
41
+ assert.match(deferred, /deadbyte-semantic-lsp-config\.json/);
35
42
  });
@@ -66,10 +66,11 @@ test('R32 remote gate accepts observation only with machine plus coding configur
66
66
  assert.match(source, /observation_runtime: observationRuntime/);
67
67
  });
68
68
 
69
- test('R32 disarmed public gate requires the fully enabled 68-tool catalog', async () => {
69
+ test('R34 disarmed public gate requires the exact canonical 73-tool catalog', async () => {
70
70
  const disarmedPath = fileURLToPath(new URL('../src/remote-mcp-r24-disarmed-smoke-client.mjs', import.meta.url));
71
71
  const source = await readFile(disarmedPath, 'utf8');
72
- assert.match(source, /listed\.tools\.length !== 68/);
73
- assert.match(source, /tool_count:68/);
74
- assert.doesNotMatch(source, /expected 61 tools/);
72
+ assert.match(source, /R34_EXPECTED_TOOLS/);
73
+ assert.match(source, /JSON\.stringify\(names\).*JSON\.stringify\(R34_EXPECTED_TOOLS\)/s);
74
+ assert.match(source, /tool_count:R34_EXPECTED_TOOLS\.length/);
75
+ assert.doesNotMatch(source, /listed\.tools\.length !== 68/);
75
76
  });
@@ -0,0 +1,58 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { mkdtemp, readFile, rm } from 'node:fs/promises';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { openRemoteResultJournal, parseRemoteResultCursor } from '../src/remote-result-journal.mjs';
7
+
8
+ const H=c=>c.repeat(64);
9
+ const session='a'.repeat(24);
10
+ const item=(requestId,payload,status='ok')=>({request_id:requestId,tool:'coding_tree',status,
11
+ observed_at_utc:'2026-09-17T00:00:00.000Z',payload_sha256:payload});
12
+
13
+ test('remote result journal is monotonic, restart-safe, and suppresses duplicate terminal results',async()=>{
14
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r35-remote-results-'));
15
+ const file=path.join(root,'journal.json');
16
+ try{
17
+ const first=await openRemoteResultJournal({filePath:file,sessionId:session,maxEntries:8});
18
+ const a=await first.recordTerminal(item('req-1',H('1')));
19
+ const duplicate=await first.recordTerminal(item('req-1',H('1')));
20
+ const b=await first.recordTerminal(item('req-2',H('2'),'error'));
21
+ assert.equal(a.event.seq,1);assert.equal(duplicate.duplicate,true);assert.equal(duplicate.event.seq,1);
22
+ assert.equal(b.event.seq,2);assert.equal(first.cursor(),'r1:'+session+':2');
23
+
24
+ const restarted=await openRemoteResultJournal({filePath:file,sessionId:session,maxEntries:8});
25
+ const c=await restarted.recordTerminal(item('req-3',H('3')));
26
+ assert.equal(c.event.seq,3);
27
+ const replay=await restarted.replayAfter('r1:'+session+':1',{limit:8});
28
+ assert.deepEqual(replay.events.map(event=>event.seq),[2,3]);
29
+ assert.equal(replay.next_cursor,'r1:'+session+':3');
30
+ }finally{await rm(root,{recursive:true,force:true});}
31
+ });
32
+
33
+ test('bounded retention rejects stale cursor and never stores raw payload bytes',async()=>{
34
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r35-remote-retention-'));
35
+ const file=path.join(root,'journal.json');
36
+ try{
37
+ const journal=await openRemoteResultJournal({filePath:file,sessionId:session,maxEntries:2});
38
+ await journal.recordTerminal(item('req-1',H('1')));
39
+ await journal.recordTerminal(item('req-2',H('2')));
40
+ await journal.recordTerminal(item('req-3',H('3')));
41
+ await assert.rejects(journal.replayAfter('r1:'+session+':0',{limit:8}),/cursor_outside_retention/);
42
+ const text=await readFile(file,'utf8');
43
+ assert.doesNotMatch(text,/stdout|stderr|payload\s*:/i);
44
+ const stored=JSON.parse(text);
45
+ assert.deepEqual(stored.events.map(event=>event.seq),[2,3]);
46
+ assert.equal(stored.next_seq,4);
47
+ }finally{await rm(root,{recursive:true,force:true});}
48
+ });
49
+
50
+ test('cursor parser rejects foreign sessions and malformed cursors',async()=>{
51
+ assert.deepEqual(parseRemoteResultCursor('r1:'+session+':42'),{session_id:session,seq:42});
52
+ assert.throws(()=>parseRemoteResultCursor('bad'),/cursor/i);
53
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r35-remote-cursor-'));
54
+ try{
55
+ const journal=await openRemoteResultJournal({filePath:path.join(root,'j.json'),sessionId:session,maxEntries:8});
56
+ await assert.rejects(journal.replayAfter('r1:'+'b'.repeat(24)+':0',{limit:8}),/cursor session mismatch/);
57
+ }finally{await rm(root,{recursive:true,force:true});}
58
+ });
@@ -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 : ARMED [standing-grant]' }\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,7 +65,7 @@ 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{
@@ -78,16 +78,22 @@ winTest('bare remote arms every authority plane, verifies ARMED state, streams l
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&&!/\[LOG\] Live tool results/.test(output.stdout)) await sleep(50);
82
+ assert.match(output.stdout,/\[OK\] ONLINE/);
83
+ assert.match(output.stdout,/\[OK\] Authority ARMED: process, coding, autonomous, host/);
84
+ assert.match(output.stdout,/\[LOG\] Live tool results\. Ctrl\+C disconnects and revokes authority\./);
85
+ assert.doesNotMatch(output.stdout,/Process plane\s*:/);
86
+ assert.doesNotMatch(output.stdout,/Coding plane\s*:/);
84
87
  const auditDir=path.join(fx.state,'audit');
85
88
  const runtimeLogs=path.join(fx.state,'runtime','logs');
86
89
  await mkdir(auditDir,{recursive:true});
87
90
  await mkdir(runtimeLogs,{recursive:true});
91
+ const marker=JSON.parse(await readFile(path.join(fx.state,'runtime','remote-session.json'),'utf8'));
92
+ assert.match(String(marker.result_session_id||''),/^[0-9a-f]{24}$/);
88
93
  const auditEvents=[
89
94
  {seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'abcdef1234567890'},
90
95
  {seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false}},
96
+ {seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false}},
91
97
  {seq:3,event_type:'tool.request',tool:'coding_file_read',request_id:'fedcba9876543210'},
92
98
  {seq:4,event_type:'tool.result',tool:'coding_file_read',request_id:'fedcba9876543210',outcome:{is_error:true}}
93
99
  ];
@@ -98,21 +104,28 @@ winTest('bare remote arms every authority plane, verifies ARMED state, streams l
98
104
  '[TOOL OUT] 2026-09-16T00:00:00.002Z #000002 coding_file_read {"is_error":true}'
99
105
  ].join('\n')+'\n','utf8');
100
106
  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/);
107
+ while(Date.now()<logDeadline&&!/\[ERR\] coding_file_read/.test(output.stdout)) await sleep(50);
108
+ assert.match(output.stdout,/\[OK\] coding_tree \[cursor r1:[0-9a-f]{24}:1\]/);
109
+ assert.match(output.stdout,/\[ERR\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/);
110
+ assert.equal((output.stdout.match(/\[OK\] coding_tree/g)||[]).length,1,'duplicate terminal result must print once');
111
+ const resultJournal=JSON.parse(await readFile(path.join(fx.state,'runtime','remote-results',`${marker.result_session_id}.json`),'utf8'));
112
+ assert.deepEqual(resultJournal.events.map(event=>event.seq),[1,2]);
113
+ assert.equal(resultJournal.events[0].request_id,'abcdef1234567890');
114
+ assert.ok(resultJournal.events.every(event=>/^[0-9a-f]{64}$/.test(event.payload_sha256)));
115
+ assert.doesNotMatch(JSON.stringify(resultJournal),/TOOL IN|TOOL OUT|stdout_excerpt|stderr_excerpt/);
116
+ assert.doesNotMatch(output.stdout,/abcdef12|fedcba98/);
117
+ assert.doesNotMatch(output.stdout,/tool\.request/);
118
+ assert.doesNotMatch(output.stdout,/BRIDGE\.STDOUT/);
119
+ assert.doesNotMatch(output.stdout,/\[TOOL IN \]|\[TOOL OUT\]/);
120
+ assert.doesNotMatch(output.stdout,/payload bytes=/);
109
121
  child.stdin.end();
110
122
  const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
111
123
  assert.equal(ended.timeout,undefined,'remote session did not exit after foreground input closed');
112
124
  const commands=await traceCommands(fx.trace);
113
125
  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);
126
+ assert.match(output.stdout,/^DEADBYTE MCP$/m);
127
+ assert.match(output.stdout,/Live tool results/i);
128
+ assert.doesNotMatch(output.stdout,/disarmautonomous OK|disarmcoding OK|disarmprocess OK|disarmhost OK|DEADBYTE MCP = PARKED/);
116
129
  const withoutApprovedEmoji=output.stdout.replace(/[📜📥📤✅❌⚠♻🛡]/gu,'');
117
130
  assert.doesNotMatch(withoutApprovedEmoji,/\p{Extended_Pictographic}/u,'human live stream may use only the approved semantic emoji set');
118
131
  }finally{
@@ -121,11 +134,93 @@ winTest('bare remote arms every authority plane, verifies ARMED state, streams l
121
134
  }
122
135
  });
123
136
 
137
+ winTest('remote --resume replays only terminal results after the cursor before starting a new live session',async()=>{
138
+ const fx=await fixture();
139
+ let first=null,second=null;
140
+ try{
141
+ first=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
142
+ const firstOutput=await collect(first);
143
+ await waitFor(fx.trace,commands=>commands.includes('hoststatus'));
144
+ const liveDeadline=Date.now()+3000;
145
+ while(Date.now()<liveDeadline&&!/\[LOG\] Live tool results/.test(firstOutput.stdout)) await sleep(50);
146
+ const auditDir=path.join(fx.state,'audit');await mkdir(auditDir,{recursive:true});
147
+ const auditFile=path.join(auditDir,'segment-00000001.jsonl');
148
+ 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');
149
+ let deadline=Date.now()+3000;
150
+ while(Date.now()<deadline&&!/coding_tree \[cursor r1:[0-9a-f]{24}:1\]/.test(firstOutput.stdout)) await sleep(50);
151
+ const cursor1=firstOutput.stdout.match(/coding_tree \[cursor (r1:[0-9a-f]{24}:1)\]/)?.[1];
152
+ assert.ok(cursor1,'first result cursor missing');
153
+ 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'});
154
+ deadline=Date.now()+3000;
155
+ while(Date.now()<deadline&&!/coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/.test(firstOutput.stdout)) await sleep(50);
156
+ first.stdin.end();
157
+ const firstEnded=await Promise.race([firstOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
158
+ assert.equal(firstEnded.timeout,undefined);
159
+
160
+ second=spawn(process.execPath,[cliPath,'remote','--resume',cursor1],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
161
+ const secondOutput=await collect(second);
162
+ deadline=Date.now()+5000;
163
+ while(Date.now()<deadline&&(!/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/.test(secondOutput.stdout)||
164
+ !/\[LOG\] Live tool results/.test(secondOutput.stdout))) await sleep(50);
165
+ assert.match(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/);
166
+ assert.doesNotMatch(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_tree/);
167
+ const replayIndex=secondOutput.stdout.indexOf('[REPLAY]');
168
+ const liveIndex=secondOutput.stdout.indexOf('[LOG] Live tool results');
169
+ assert.ok(replayIndex>=0&&liveIndex>replayIndex,'resume replay must happen before new live tail');
170
+ second.stdin.end();
171
+ const secondEnded=await Promise.race([secondOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
172
+ assert.equal(secondEnded.timeout,undefined);
173
+ assert.equal(secondEnded.code,0,secondOutput.stderr);
174
+ }finally{
175
+ if(first?.exitCode===null) first.kill();if(second?.exitCode===null) second.kill();
176
+ await rm(fx.dir,{recursive:true,force:true});
177
+ }
178
+ });
179
+
180
+ winTest('remote --verbose preserves detailed audit and bridge log streaming for debugging',async()=>{
181
+ const fx=await fixture();
182
+ let child=null;
183
+ try{
184
+ child=spawn(process.execPath,[cliPath,'remote','--verbose'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
185
+ const output=await collect(child);
186
+ const ready=await waitFor(fx.trace,commands=>commands.slice(0,9).join(',')==='start,armprocess,armcoding,armautonomous,armhost,processstatus,codingstatus,autonomousstatus,hoststatus');
187
+ assert.equal(ready.length>=9,true);
188
+ const liveDeadline=Date.now()+3000;
189
+ while(Date.now()<liveDeadline&&!/Live logs active/.test(output.stdout)) await sleep(50);
190
+ assert.match(output.stdout,/Live logs active/);
191
+ const auditDir=path.join(fx.state,'audit');
192
+ const runtimeLogs=path.join(fx.state,'runtime','logs');
193
+ await mkdir(auditDir,{recursive:true});
194
+ await mkdir(runtimeLogs,{recursive:true});
195
+ await writeFile(path.join(auditDir,'segment-00000001.jsonl'),[
196
+ JSON.stringify({seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'abcdef1234567890'}),
197
+ JSON.stringify({seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false}})
198
+ ].join('\n')+'\n','utf8');
199
+ await writeFile(path.join(runtimeLogs,'bridge.stdout.log'),[
200
+ '[TOOL IN ] 2026-09-16T00:00:00.000Z #000001 coding_tree {}',
201
+ '[TOOL OUT] 2026-09-16T00:00:00.001Z #000001 coding_tree {"is_error":false}'
202
+ ].join('\n')+'\n','utf8');
203
+ const deadline=Date.now()+3000;
204
+ while(Date.now()<deadline&&!/\[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_tree/.test(output.stdout)) await sleep(50);
205
+ assert.match(output.stdout,/\[AUDIT #1\] tool\.request coding_tree abcdef12/);
206
+ assert.match(output.stdout,/\[AUDIT #2\] tool\.result coding_tree abcdef12/);
207
+ assert.match(output.stdout,/\[BRIDGE\.STDOUT\] \[TOOL IN \].*coding_tree/);
208
+ assert.match(output.stdout,/\[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_tree/);
209
+ child.stdin.end();
210
+ const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
211
+ assert.equal(ended.timeout,undefined,'verbose remote session did not exit after input closed');
212
+ assert.equal(ended.code,0,output.stderr);
213
+ }finally{
214
+ if(child?.exitCode===null) child.kill();
215
+ await rm(fx.dir,{recursive:true,force:true});
216
+ }
217
+ });
218
+
124
219
  winTest('detached guardian revokes authority, parks, and removes the session marker after the owner is hard-killed',async()=>{
125
220
  const fx=await fixture();
126
221
  let child=null;
127
222
  try{
128
- child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['ignore','pipe','pipe'],windowsHide:true});
223
+ child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
129
224
  const output=await collect(child);
130
225
  const ready=await waitFor(fx.trace,commands=>commands.slice(0,9).join(',')==='start,armprocess,armcoding,armautonomous,armhost,processstatus,codingstatus,autonomousstatus,hoststatus');
131
226
  assert.deepEqual(ready.slice(0,9),[
@@ -206,6 +206,40 @@ test('R31 slot-update CLI binds process-policy bootstrap and machine-FS enable e
206
206
  assert.equal(parsed.enableMachineFs,true);
207
207
  });
208
208
 
209
+ test('R35 slot-update CLI binds semantic LSP config as one exact path plus SHA-256 pair', () => {
210
+ const base=['--stage','stage','--development-root','dev','--expected-version','0.9.0','--expected-manifest',hex('a')];
211
+ assert.throws(() => parseUpdateArgs([...base,'--semantic-lsp-config','C:/candidate/semantic.json']), /semantic LSP config.*pair/i);
212
+ assert.throws(() => parseUpdateArgs([...base,'--semantic-lsp-config-sha256',hex('b')]), /semantic LSP config.*pair/i);
213
+ const parsed=parseUpdateArgs([...base,'--semantic-lsp-config','C:/candidate/semantic.json','--semantic-lsp-config-sha256',hex('b')]);
214
+ assert.equal(parsed.semanticLspBootstrap.path,path.resolve('C:/candidate/semantic.json'));
215
+ assert.equal(parsed.semanticLspBootstrap.sha256,hex('b'));
216
+ });
217
+
218
+ test('R35 semantic LSP bootstrap accepts only exact pinned semantic config bytes', async () => {
219
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r35-semantic-bootstrap-'));
220
+ const file=path.join(root,'semantic.json');
221
+ const config={schema:'deadbyte.semantic-lsp-config.v1',servers:[]};
222
+ const bytes=Buffer.from(`${JSON.stringify(config)}\n`,'utf8');
223
+ await writeFile(file,bytes);
224
+ assert.equal(typeof runtimeUpdate.prepareSemanticLspConfigBootstrap,'function');
225
+ const accepted=await runtimeUpdate.prepareSemanticLspConfigBootstrap({path:file,sha256:sha(bytes)});
226
+ assert.equal(accepted.path,path.resolve(file));
227
+ assert.equal(accepted.sha256,sha(bytes));
228
+ await assert.rejects(runtimeUpdate.prepareSemanticLspConfigBootstrap({path:file,sha256:hex('f')}),/semantic LSP config.*SHA-256 mismatch/i);
229
+ const bad=path.join(root,'bad.json');
230
+ const badBytes=Buffer.from(`${JSON.stringify({schema:'wrong',servers:[]})}\n`,'utf8');
231
+ await writeFile(bad,badBytes);
232
+ await assert.rejects(runtimeUpdate.prepareSemanticLspConfigBootstrap({path:bad,sha256:sha(badBytes)}),/semantic LSP config schema/i);
233
+ });
234
+
235
+ test('R35 updater threads pinned semantic LSP config into successor generation', async () => {
236
+ const source=await readFile(new URL('../src/runtime-update.mjs',import.meta.url),'utf8');
237
+ assert.match(source,/prepareSemanticLspConfigBootstrap\(semanticLspBootstrap\)/);
238
+ assert.match(source,/SemanticLspConfigFile=semanticBootstrap\.path/);
239
+ assert.match(source,/SemanticLspConfigSha256=semanticBootstrap\.sha256/);
240
+ assert.match(source,/semanticLspBootstrap:args\.semanticLspBootstrap/);
241
+ });
242
+
209
243
  test('R32 slot-update CLI enables observation only by explicit flag', () => {
210
244
  const base=['--stage','stage','--development-root','dev','--expected-version','0.8.6','--expected-manifest',hex('a')];
211
245
  const plain=parseUpdateArgs(base);
@@ -215,6 +249,35 @@ test('R32 slot-update CLI enables observation only by explicit flag', () => {
215
249
  assert.throws(() => parseUpdateArgs([...base,'--enable-observation','--enable-observation']),/duplicate self-update argument/i);
216
250
  });
217
251
 
252
+ test('R34 slot-update CLI enables the out-of-band supervisor only by explicit flag', () => {
253
+ const base=['--stage','stage','--development-root','dev','--expected-version','0.8.11','--expected-manifest',hex('a')];
254
+ const plain=parseUpdateArgs(base);
255
+ assert.equal(plain.enableAutonomousSupervisor,false);
256
+ const enabled=parseUpdateArgs([...base,'--enable-autonomous-supervisor']);
257
+ assert.equal(enabled.enableAutonomousSupervisor,true);
258
+ assert.throws(() => parseUpdateArgs([...base,'--enable-autonomous-supervisor','--enable-autonomous-supervisor']),/duplicate self-update argument/i);
259
+ });
260
+
261
+ test('R34 supervisor bootstrap derives exact release-bound script identity from trusted Bridge executable', async () => {
262
+ assert.equal(typeof runtimeUpdate.prepareAutonomousSupervisorSpec,'function');
263
+ const base=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r34-supervisor-bootstrap-'));
264
+ const release=path.join(base,'release'),src=path.join(release,'src'); await mkdir(src,{recursive:true});
265
+ const script=Buffer.from('console.log("supervisor-r34")\n','utf8');
266
+ await writeFile(path.join(src,'autonomous-supervisor-host.mjs'),script);
267
+ const nodeHash=sha(await readFile(process.execPath));
268
+ const config={AutonomousRuntimeEnabled:true,AutonomousSupervisorEnabled:false,
269
+ Bridge:{FilePath:process.execPath,FileSha256:nodeHash}};
270
+ const bound=await runtimeUpdate.prepareAutonomousSupervisorSpec(config,{releaseRoot:release,enable:true});
271
+ assert.equal(bound.AutonomousSupervisorEnabled,true);
272
+ assert.deepEqual(bound.Supervisor,{
273
+ FilePath:process.execPath,FileSha256:nodeHash,Arguments:'src\\autonomous-supervisor-host.mjs',
274
+ WorkingDirectory:path.resolve(release),ScriptPath:path.join(path.resolve(release),'src','autonomous-supervisor-host.mjs'),ScriptSha256:sha(script)
275
+ });
276
+ const untouched=await runtimeUpdate.prepareAutonomousSupervisorSpec(config,{releaseRoot:release,enable:false});
277
+ assert.equal(untouched.AutonomousSupervisorEnabled,false);
278
+ assert.equal(untouched.Supervisor,undefined);
279
+ });
280
+
218
281
  test('R31 process-policy bootstrap accepts only an exact pinned enabled process policy', async () => {
219
282
  const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r31-process-bootstrap-'));
220
283
  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,99 @@
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
+ const before=await f.codingRuntime.fileRead({rootId:'project',relativePath:'main.foo'});
47
+ const edited=await f.backend.replaceSymbol({rootId:'project',relativePath:'main.foo',symbolId:symbol.symbol_id,newBody:'export function beta() {}',expectedSha256:before.sha256});
48
+ assert.equal(edited.status,'committed');assert.equal(edited.symbol_name,'alpha');assert.equal(edited.engine,'fixture-lsp');
49
+ assert.equal(await readFile(path.join(f.root,'main.foo'),'utf8'),'export function beta() {}\n');
50
+ } finally {await rm(f.root,{recursive:true,force:true});}
51
+ });
52
+
53
+ test('semantic LSP backend rejects targets outside lease/root policy before launching server',async()=>{
54
+ const f=await makeFixture();
55
+ try{
56
+ await assert.rejects(f.backend.outline({rootId:'missing',relativePath:'main.foo',maxSymbols:10}),/outside active lease/i);
57
+ await assert.rejects(f.backend.outline({rootId:'project',relativePath:'denied/main.foo',maxSymbols:10}),/denied/i);
58
+ } finally {await rm(f.root,{recursive:true,force:true});}
59
+ });
60
+
61
+ test('semantic LSP backend forwards dependency pins before launching server',async()=>{
62
+ const f=await makeFixture();
63
+ try{
64
+ 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}});
65
+ await assert.rejects(backend.outline({rootId:'project',relativePath:'main.foo',maxSymbols:10}),/LSP dependency SHA-256 mismatch/i);
66
+ } finally {await rm(f.root,{recursive:true,force:true});}
67
+ });
68
+
69
+ test('semantic LSP backend separates engine id from LSP language id',async()=>{
70
+ const f=await makeFixture();
71
+ try{
72
+ const fixtureSha=sha256(await readFile(fixture));
73
+ 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}});
74
+ const outline=await backend.outline({rootId:'project',relativePath:'main.foo',maxSymbols:10});
75
+ assert.equal(outline.engine,'fixture-engine');
76
+ assert.equal(outline.symbols[0].name,'alpha');
77
+ } finally {await rm(f.root,{recursive:true,force:true});}
78
+ });
79
+
80
+ test('semantic LSP backend pre-opens bounded same-language project files for deterministic cross-file navigation',async()=>{
81
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-lsp-project-'));
82
+ await writeFile(path.join(root,'main.foo'),'export function main() { return alpha(); }\n','utf8');
83
+ await writeFile(path.join(root,'peer.foo'),'export function alpha() { return 1; }\n','utf8');
84
+ const codingRuntime={
85
+ policy:{roots:{project:{real_path:root,read:true,write:true,exec:false,deny_paths:[]}}},
86
+ async sessionStatus(){return {armed:true,reason:'standing-grant',root_ids:['project']};},
87
+ async tree(){return {truncated:false,entries:[{type:'file',path:'main.foo'},{type:'file',path:'peer.foo'}]};},
88
+ async fileRead({relativePath}){const content=await readFile(path.join(root,relativePath),'utf8');return {status:'ok',content,sha256:sha256(Buffer.from(content,'utf8'))};},
89
+ async textReplace(){throw new Error('not used');}
90
+ };
91
+ try{
92
+ const fixtureSha=sha256(await readFile(fixture));
93
+ 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}});
94
+ const definition=await backend.definition({rootId:'project',relativePath:'main.foo',line:0,column:18,maxResults:10});
95
+ assert.ok(definition.locations.some(item=>item.path==='peer.foo'),JSON.stringify(definition.locations));
96
+ const references=await backend.references({rootId:'project',relativePath:'main.foo',line:0,column:18,maxResults:10});
97
+ assert.ok(references.locations.some(item=>item.path==='peer.foo'),JSON.stringify(references.locations));
98
+ } finally {await rm(root,{recursive:true,force:true});}
99
+ });