deadbyte-mcp 0.8.9 → 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 (349) hide show
  1. package/CONTEXT.md +41 -0
  2. package/MANIFEST.SHA256 +348 -83
  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/deadbyte-mcp-0.8.9.tgz +0 -0
  39. package/docs/ADR-0001-PRODUCTION-BASELINE-SEAMS.md +29 -0
  40. package/docs/ARCHITECTURE.md +6 -5
  41. package/docs/superpowers/plans/2026-09-16-deadbyte-loop-engine.md +846 -0
  42. package/docs/superpowers/plans/2026-09-17-r35-production-successor.md +408 -0
  43. package/docs/superpowers/specs/2026-09-16-deadbyte-loop-engine-design.md +435 -0
  44. package/docs/superpowers/specs/2026-09-17-r35-production-successor-design.md +220 -0
  45. package/node_modules/typescript/LICENSE.txt +55 -0
  46. package/node_modules/typescript/README.md +50 -0
  47. package/node_modules/typescript/SECURITY.md +41 -0
  48. package/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
  49. package/node_modules/typescript/bin/tsc +2 -0
  50. package/node_modules/typescript/bin/tsserver +2 -0
  51. package/node_modules/typescript/lib/_tsc.js +133818 -0
  52. package/node_modules/typescript/lib/_tsserver.js +659 -0
  53. package/node_modules/typescript/lib/_typingsInstaller.js +222 -0
  54. package/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +2122 -0
  55. package/node_modules/typescript/lib/de/diagnosticMessages.generated.json +2122 -0
  56. package/node_modules/typescript/lib/es/diagnosticMessages.generated.json +2122 -0
  57. package/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +2122 -0
  58. package/node_modules/typescript/lib/it/diagnosticMessages.generated.json +2122 -0
  59. package/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +2122 -0
  60. package/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +2122 -0
  61. package/node_modules/typescript/lib/lib.d.ts +22 -0
  62. package/node_modules/typescript/lib/lib.decorators.d.ts +384 -0
  63. package/node_modules/typescript/lib/lib.decorators.legacy.d.ts +22 -0
  64. package/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +41 -0
  65. package/node_modules/typescript/lib/lib.dom.d.ts +39429 -0
  66. package/node_modules/typescript/lib/lib.dom.iterable.d.ts +571 -0
  67. package/node_modules/typescript/lib/lib.es2015.collection.d.ts +147 -0
  68. package/node_modules/typescript/lib/lib.es2015.core.d.ts +597 -0
  69. package/node_modules/typescript/lib/lib.es2015.d.ts +28 -0
  70. package/node_modules/typescript/lib/lib.es2015.generator.d.ts +77 -0
  71. package/node_modules/typescript/lib/lib.es2015.iterable.d.ts +605 -0
  72. package/node_modules/typescript/lib/lib.es2015.promise.d.ts +81 -0
  73. package/node_modules/typescript/lib/lib.es2015.proxy.d.ts +128 -0
  74. package/node_modules/typescript/lib/lib.es2015.reflect.d.ts +144 -0
  75. package/node_modules/typescript/lib/lib.es2015.symbol.d.ts +46 -0
  76. package/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +326 -0
  77. package/node_modules/typescript/lib/lib.es2016.array.include.d.ts +116 -0
  78. package/node_modules/typescript/lib/lib.es2016.d.ts +21 -0
  79. package/node_modules/typescript/lib/lib.es2016.full.d.ts +23 -0
  80. package/node_modules/typescript/lib/lib.es2016.intl.d.ts +31 -0
  81. package/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +21 -0
  82. package/node_modules/typescript/lib/lib.es2017.d.ts +26 -0
  83. package/node_modules/typescript/lib/lib.es2017.date.d.ts +31 -0
  84. package/node_modules/typescript/lib/lib.es2017.full.d.ts +23 -0
  85. package/node_modules/typescript/lib/lib.es2017.intl.d.ts +44 -0
  86. package/node_modules/typescript/lib/lib.es2017.object.d.ts +49 -0
  87. package/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +135 -0
  88. package/node_modules/typescript/lib/lib.es2017.string.d.ts +45 -0
  89. package/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +53 -0
  90. package/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +77 -0
  91. package/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +53 -0
  92. package/node_modules/typescript/lib/lib.es2018.d.ts +24 -0
  93. package/node_modules/typescript/lib/lib.es2018.full.d.ts +24 -0
  94. package/node_modules/typescript/lib/lib.es2018.intl.d.ts +83 -0
  95. package/node_modules/typescript/lib/lib.es2018.promise.d.ts +30 -0
  96. package/node_modules/typescript/lib/lib.es2018.regexp.d.ts +37 -0
  97. package/node_modules/typescript/lib/lib.es2019.array.d.ts +79 -0
  98. package/node_modules/typescript/lib/lib.es2019.d.ts +24 -0
  99. package/node_modules/typescript/lib/lib.es2019.full.d.ts +24 -0
  100. package/node_modules/typescript/lib/lib.es2019.intl.d.ts +23 -0
  101. package/node_modules/typescript/lib/lib.es2019.object.d.ts +33 -0
  102. package/node_modules/typescript/lib/lib.es2019.string.d.ts +37 -0
  103. package/node_modules/typescript/lib/lib.es2019.symbol.d.ts +24 -0
  104. package/node_modules/typescript/lib/lib.es2020.bigint.d.ts +765 -0
  105. package/node_modules/typescript/lib/lib.es2020.d.ts +27 -0
  106. package/node_modules/typescript/lib/lib.es2020.date.d.ts +42 -0
  107. package/node_modules/typescript/lib/lib.es2020.full.d.ts +24 -0
  108. package/node_modules/typescript/lib/lib.es2020.intl.d.ts +474 -0
  109. package/node_modules/typescript/lib/lib.es2020.number.d.ts +28 -0
  110. package/node_modules/typescript/lib/lib.es2020.promise.d.ts +47 -0
  111. package/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +99 -0
  112. package/node_modules/typescript/lib/lib.es2020.string.d.ts +44 -0
  113. package/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +41 -0
  114. package/node_modules/typescript/lib/lib.es2021.d.ts +23 -0
  115. package/node_modules/typescript/lib/lib.es2021.full.d.ts +24 -0
  116. package/node_modules/typescript/lib/lib.es2021.intl.d.ts +166 -0
  117. package/node_modules/typescript/lib/lib.es2021.promise.d.ts +48 -0
  118. package/node_modules/typescript/lib/lib.es2021.string.d.ts +33 -0
  119. package/node_modules/typescript/lib/lib.es2021.weakref.d.ts +78 -0
  120. package/node_modules/typescript/lib/lib.es2022.array.d.ts +121 -0
  121. package/node_modules/typescript/lib/lib.es2022.d.ts +25 -0
  122. package/node_modules/typescript/lib/lib.es2022.error.d.ts +75 -0
  123. package/node_modules/typescript/lib/lib.es2022.full.d.ts +24 -0
  124. package/node_modules/typescript/lib/lib.es2022.intl.d.ts +145 -0
  125. package/node_modules/typescript/lib/lib.es2022.object.d.ts +26 -0
  126. package/node_modules/typescript/lib/lib.es2022.regexp.d.ts +39 -0
  127. package/node_modules/typescript/lib/lib.es2022.string.d.ts +25 -0
  128. package/node_modules/typescript/lib/lib.es2023.array.d.ts +924 -0
  129. package/node_modules/typescript/lib/lib.es2023.collection.d.ts +21 -0
  130. package/node_modules/typescript/lib/lib.es2023.d.ts +22 -0
  131. package/node_modules/typescript/lib/lib.es2023.full.d.ts +24 -0
  132. package/node_modules/typescript/lib/lib.es2023.intl.d.ts +56 -0
  133. package/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +65 -0
  134. package/node_modules/typescript/lib/lib.es2024.collection.d.ts +29 -0
  135. package/node_modules/typescript/lib/lib.es2024.d.ts +26 -0
  136. package/node_modules/typescript/lib/lib.es2024.full.d.ts +24 -0
  137. package/node_modules/typescript/lib/lib.es2024.object.d.ts +29 -0
  138. package/node_modules/typescript/lib/lib.es2024.promise.d.ts +35 -0
  139. package/node_modules/typescript/lib/lib.es2024.regexp.d.ts +25 -0
  140. package/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +68 -0
  141. package/node_modules/typescript/lib/lib.es2024.string.d.ts +29 -0
  142. package/node_modules/typescript/lib/lib.es5.d.ts +4601 -0
  143. package/node_modules/typescript/lib/lib.es6.d.ts +23 -0
  144. package/node_modules/typescript/lib/lib.esnext.array.d.ts +35 -0
  145. package/node_modules/typescript/lib/lib.esnext.collection.d.ts +96 -0
  146. package/node_modules/typescript/lib/lib.esnext.d.ts +29 -0
  147. package/node_modules/typescript/lib/lib.esnext.decorators.d.ts +28 -0
  148. package/node_modules/typescript/lib/lib.esnext.disposable.d.ts +193 -0
  149. package/node_modules/typescript/lib/lib.esnext.error.d.ts +24 -0
  150. package/node_modules/typescript/lib/lib.esnext.float16.d.ts +445 -0
  151. package/node_modules/typescript/lib/lib.esnext.full.d.ts +24 -0
  152. package/node_modules/typescript/lib/lib.esnext.intl.d.ts +21 -0
  153. package/node_modules/typescript/lib/lib.esnext.iterator.d.ts +148 -0
  154. package/node_modules/typescript/lib/lib.esnext.promise.d.ts +34 -0
  155. package/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +25 -0
  156. package/node_modules/typescript/lib/lib.scripthost.d.ts +322 -0
  157. package/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +41 -0
  158. package/node_modules/typescript/lib/lib.webworker.d.ts +13150 -0
  159. package/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +23 -0
  160. package/node_modules/typescript/lib/lib.webworker.iterable.d.ts +340 -0
  161. package/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +2122 -0
  162. package/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +2122 -0
  163. package/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +2122 -0
  164. package/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +2122 -0
  165. package/node_modules/typescript/lib/tsc.js +8 -0
  166. package/node_modules/typescript/lib/tsserver.js +8 -0
  167. package/node_modules/typescript/lib/tsserverlibrary.d.ts +17 -0
  168. package/node_modules/typescript/lib/tsserverlibrary.js +21 -0
  169. package/node_modules/typescript/lib/typesMap.json +497 -0
  170. package/node_modules/typescript/lib/typescript.d.ts +11437 -0
  171. package/node_modules/typescript/lib/typescript.js +200276 -0
  172. package/node_modules/typescript/lib/typingsInstaller.js +8 -0
  173. package/node_modules/typescript/lib/watchGuard.js +53 -0
  174. package/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +2122 -0
  175. package/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +2122 -0
  176. package/node_modules/typescript/package.json +120 -0
  177. package/package.json +5 -3
  178. package/proof/CONTAINMENT-BUILD.txt +6 -6
  179. package/proof/R34-TASK8-SUPERVISOR-CHECKPOINT.json +29 -0
  180. package/proof/R34-TASK9-MCP-SURFACE-CHECKPOINT.json +28 -0
  181. package/scripts/capability-benchmark.mjs +27 -0
  182. package/scripts/deferred-slot-operation.mjs +4 -2
  183. package/scripts/final-closure-verify.mjs +10 -10
  184. package/scripts/final-closure.mjs +11 -11
  185. package/scripts/gate-windows.ps1 +3 -3
  186. package/scripts/release-parity.mjs +14 -14
  187. package/scripts/semantic-preflight.ps1 +73 -0
  188. package/scripts/tool-surface-snapshot.mjs +73 -0
  189. package/scripts/windows-gate-evidence.mjs +5 -5
  190. package/src/audit-verify.mjs +6 -2
  191. package/src/autonomous-action-reconcile.mjs +142 -0
  192. package/src/autonomous-context-engine.mjs +255 -0
  193. package/src/autonomous-live-state.mjs +17 -0
  194. package/src/autonomous-local-supervisor.mjs +249 -0
  195. package/src/autonomous-loop-state.mjs +304 -0
  196. package/src/autonomous-output-contracts.mjs +22 -3
  197. package/src/autonomous-plan.mjs +181 -0
  198. package/src/autonomous-planner-contracts.mjs +44 -0
  199. package/src/autonomous-planner.mjs +91 -6
  200. package/src/autonomous-policy.mjs +15 -2
  201. package/src/autonomous-progress.mjs +127 -0
  202. package/src/autonomous-runtime.mjs +601 -48
  203. package/src/autonomous-supervisor-host.mjs +70 -0
  204. package/src/autonomous-supervisor.mjs +31 -8
  205. package/src/capability-benchmark-runner.mjs +108 -0
  206. package/src/capability-benchmark.mjs +50 -0
  207. package/src/coding-mcp-tools.mjs +46 -3
  208. package/src/coding-output-contracts.mjs +45 -0
  209. package/src/context-provenance.mjs +86 -0
  210. package/src/deadbyte-cli.mjs +136 -30
  211. package/src/document-adapter.mjs +43 -0
  212. package/src/lsp-stdio-client.mjs +112 -0
  213. package/src/machine-fs-smoke-client.mjs +2 -1
  214. package/src/mcp-server.mjs +17 -3
  215. package/src/observation-smoke-client.mjs +3 -2
  216. package/src/operator-surface.mjs +37 -0
  217. package/src/provider-circuit.mjs +125 -0
  218. package/src/release-generation.mjs +44 -5
  219. package/src/remote-mcp-autonomous-smoke-client.mjs +53 -14
  220. package/src/remote-mcp-coding-smoke-client.mjs +5 -4
  221. package/src/remote-mcp-r24-disarmed-smoke-client.mjs +4 -2
  222. package/src/remote-mcp-r33-parity-client.mjs +1 -1
  223. package/src/remote-mcp-r34-parity-client.mjs +177 -0
  224. package/src/remote-mcp-smoke-client.mjs +2 -1
  225. package/src/remote-result-journal.mjs +114 -0
  226. package/src/runtime-update.mjs +58 -8
  227. package/src/semantic-backend-registry.mjs +39 -0
  228. package/src/semantic-code.mjs +179 -0
  229. package/src/semantic-lsp-backend.mjs +183 -0
  230. package/src/semantic-lsp-config.mjs +112 -0
  231. package/src/tool-surface-ledger.mjs +92 -0
  232. package/src/version.mjs +1 -1
  233. package/test/audit-verify.test.mjs +1 -1
  234. package/test/autonomous-action-reconcile.test.mjs +106 -0
  235. package/test/autonomous-adversarial.test.mjs +149 -6
  236. package/test/autonomous-context-engine.test.mjs +181 -0
  237. package/test/autonomous-live-state.test.mjs +27 -0
  238. package/test/autonomous-local-supervisor.test.mjs +403 -0
  239. package/test/autonomous-loop-state.test.mjs +126 -0
  240. package/test/autonomous-loop-v2.test.mjs +105 -0
  241. package/test/autonomous-loop.test.mjs +79 -1
  242. package/test/autonomous-output-contract.test.mjs +54 -0
  243. package/test/autonomous-plan.test.mjs +101 -0
  244. package/test/autonomous-progress.test.mjs +106 -0
  245. package/test/autonomous-r34-e2e.test.mjs +338 -0
  246. package/test/autonomous-runtime.test.mjs +3 -3
  247. package/test/autonomous-supervisor-integration.test.mjs +48 -3
  248. package/test/capability-benchmark-runner.test.mjs +49 -0
  249. package/test/capability-benchmark.test.mjs +47 -0
  250. package/test/cli-entrypoint.test.mjs +12 -0
  251. package/test/coding-catalog-consistency.test.mjs +24 -0
  252. package/test/coding-plane.test.mjs +3 -3
  253. package/test/context-provenance.test.mjs +61 -0
  254. package/test/controller-r27.test.mjs +4 -3
  255. package/test/controller.test.mjs +52 -0
  256. package/test/core.test.mjs +1 -1
  257. package/test/deferred-slot-operation-behavior.test.mjs +5 -1
  258. package/test/deferred-slot-operation.test.mjs +2 -1
  259. package/test/document-adapter.test.mjs +23 -0
  260. package/test/fixtures/lsp-framed-server.mjs +33 -0
  261. package/test/fixtures/semantic/cpp/compile_commands.json +4 -0
  262. package/test/fixtures/semantic/cpp/lib.cpp +2 -0
  263. package/test/fixtures/semantic/cpp/lib.hpp +2 -0
  264. package/test/fixtures/semantic/cpp/main.cpp +2 -0
  265. package/test/fixtures/semantic/python/lib.py +2 -0
  266. package/test/fixtures/semantic/python/main.py +2 -0
  267. package/test/fixtures/semantic/rust/Cargo.lock +7 -0
  268. package/test/fixtures/semantic/rust/Cargo.toml +8 -0
  269. package/test/fixtures/semantic/rust/src/lib.rs +3 -0
  270. package/test/fixtures/semantic/rust/src/main.rs +5 -0
  271. package/test/fixtures/semantic/rust/src/math.rs +3 -0
  272. package/test/fixtures/semantic/rust/target/.rustc_info.json +1 -0
  273. package/test/fixtures/semantic/rust/target/CACHEDIR.TAG +3 -0
  274. package/test/fixtures/semantic/rust/target/debug/.cargo-lock +0 -0
  275. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/dep-test-lib-semantic_rust +0 -0
  276. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/invoked.timestamp +1 -0
  277. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/test-lib-semantic_rust +1 -0
  278. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/test-lib-semantic_rust.json +1 -0
  279. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/dep-test-bin-semantic_rust_bin +0 -0
  280. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/invoked.timestamp +1 -0
  281. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/test-bin-semantic_rust_bin +1 -0
  282. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/test-bin-semantic_rust_bin.json +1 -0
  283. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/dep-lib-semantic_rust +0 -0
  284. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/invoked.timestamp +1 -0
  285. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/lib-semantic_rust +1 -0
  286. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/lib-semantic_rust.json +1 -0
  287. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/bin-semantic_rust_bin +1 -0
  288. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/bin-semantic_rust_bin.json +1 -0
  289. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/dep-bin-semantic_rust_bin +0 -0
  290. package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/invoked.timestamp +1 -0
  291. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust-4c168fa33c79d09c.rmeta +0 -0
  292. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust-6212ccd976aa3808.rmeta +0 -0
  293. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust_bin-5dcd474439c54a26.rmeta +0 -0
  294. package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust_bin-d741378dccdef61c.rmeta +0 -0
  295. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust-4c168fa33c79d09c.d +5 -0
  296. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust-6212ccd976aa3808.d +5 -0
  297. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust_bin-5dcd474439c54a26.d +6 -0
  298. package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust_bin-d741378dccdef61c.d +6 -0
  299. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/dep-graph.bin +0 -0
  300. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/query-cache.bin +0 -0
  301. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/work-products.bin +0 -0
  302. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc.lock +0 -0
  303. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/dep-graph.bin +0 -0
  304. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/metadata.rmeta +0 -0
  305. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/query-cache.bin +0 -0
  306. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/work-products.bin +0 -0
  307. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq.lock +0 -0
  308. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/dep-graph.bin +0 -0
  309. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/query-cache.bin +0 -0
  310. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/work-products.bin +0 -0
  311. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3.lock +0 -0
  312. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/dep-graph.bin +0 -0
  313. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/query-cache.bin +0 -0
  314. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/work-products.bin +0 -0
  315. package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt.lock +0 -0
  316. package/test/fixtures/semantic/rust/target/flycheck0/stderr +1 -0
  317. package/test/fixtures/semantic/rust/target/flycheck0/stdout +5 -0
  318. package/test/fixtures/semantic/typescript/lib.ts +3 -0
  319. package/test/fixtures/semantic/typescript/main.ts +2 -0
  320. package/test/fixtures/tool-surface-stdio-server.mjs +14 -0
  321. package/test/helpers/autonomous-r34-fixture.mjs +120 -0
  322. package/test/lsp-stdio-client.test.mjs +72 -0
  323. package/test/multi-file-read.test.mjs +41 -0
  324. package/test/observation-integration.test.mjs +3 -3
  325. package/test/production-docs.test.mjs +48 -0
  326. package/test/prompts-resources.test.mjs +35 -0
  327. package/test/provider-circuit.test.mjs +93 -0
  328. package/test/public-autonomous-ingress-budget.test.mjs +28 -0
  329. package/test/r33-closeout-regression.test.mjs +3 -3
  330. package/test/r33-finalization.test.mjs +19 -16
  331. package/test/release-generation.test.mjs +23 -2
  332. package/test/release-version.test.mjs +24 -17
  333. package/test/remote-r24-catalog.test.mjs +5 -4
  334. package/test/remote-result-journal.test.mjs +58 -0
  335. package/test/remote-session-cli.test.mjs +150 -15
  336. package/test/runtime-self-update.test.mjs +63 -0
  337. package/test/semantic-backend-registry.test.mjs +29 -0
  338. package/test/semantic-code.test.mjs +66 -0
  339. package/test/semantic-lsp-backend.test.mjs +99 -0
  340. package/test/semantic-lsp-config.test.mjs +81 -0
  341. package/test/semantic-lsp-readiness.test.mjs +34 -0
  342. package/test/semantic-lsp-transient-empty.test.mjs +32 -0
  343. package/test/semantic-lsp-transient-null.test.mjs +31 -0
  344. package/test/semantic-multilang.test.mjs +72 -0
  345. package/test/semantic-runtime-routing.test.mjs +32 -0
  346. package/test/semantic-server-config-integration.test.mjs +66 -0
  347. package/test/tool-surface-ledger.test.mjs +59 -0
  348. package/test/tool-surface-snapshot.test.mjs +17 -0
  349. 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.9 / 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.9 / R33 identity', as
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.9');
24
- assert.match(version, /DEADBYTE_VERSION = '0\.8\.9'/);
25
- assert.match(controller, /CONTROLLER V0\.8\.9 \/ R33/);
26
- assert.match(gate, /DEADBYTE V0\.8\.9 \/ R33 WINDOWS BATCH GATE: PASS/);
27
- assert.match(readme, /^DEADBYTE MCP V0\.8\.9 \/ R33 FINAL MACHINE BASELINE$/m);
28
- assert.match(architecture, /^# DEADBYTE MCP V0\.8\.9 \/ R33 ARCHITECTURE$/m);
29
- assert.match(controllerReadme, /^DEADBYTE MCP V0\.8\.9 \/ R33 CONTROLLER$/m);
30
- assert.match(controllerReadme, /68-tool public catalog/);
31
- assert.match(deferred, /--expected-version','0\.8\.9'/);
32
- assert.match(parity, /version:'0\.8\.9'/);
33
- assert.match(closure, /version:'0\.8\.9'/);
34
- assert.match(closureVerify, /DEADBYTE V0\.8\.9 \/ 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,36 +65,151 @@ 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.includes('hoststatus'));
74
+ const ready=await waitFor(fx.trace,commands=>commands.slice(0,9).join(',')==='start,armprocess,armcoding,armautonomous,armhost,processstatus,codingstatus,autonomousstatus,hoststatus');
75
75
  assert.deepEqual(ready.slice(0,9),[
76
76
  'start','armprocess','armcoding','armautonomous','armhost',
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\./);
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*:/);
83
87
  const auditDir=path.join(fx.state,'audit');
88
+ const runtimeLogs=path.join(fx.state,'runtime','logs');
84
89
  await mkdir(auditDir,{recursive:true});
85
- await writeFile(path.join(auditDir,'segment-00000001.jsonl'),`${JSON.stringify({seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'abcdef1234567890'})}\n`,'utf8');
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}$/);
93
+ const auditEvents=[
94
+ {seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'abcdef1234567890'},
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}},
97
+ {seq:3,event_type:'tool.request',tool:'coding_file_read',request_id:'fedcba9876543210'},
98
+ {seq:4,event_type:'tool.result',tool:'coding_file_read',request_id:'fedcba9876543210',outcome:{is_error:true}}
99
+ ];
100
+ await writeFile(path.join(auditDir,'segment-00000001.jsonl'),`${auditEvents.map(event=>JSON.stringify(event)).join('\n')}\n`,'utf8');
101
+ await writeFile(path.join(runtimeLogs,'bridge.stdout.log'),[
102
+ '[TOOL IN ] 2026-09-16T00:00:00.000Z #000001 coding_tree {}',
103
+ '[TOOL OUT] 2026-09-16T00:00:00.001Z #000001 coding_tree {"is_error":false}',
104
+ '[TOOL OUT] 2026-09-16T00:00:00.002Z #000002 coding_file_read {"is_error":true}'
105
+ ].join('\n')+'\n','utf8');
86
106
  const logDeadline=Date.now()+3000;
87
- while(Date.now()<logDeadline&&!/\[AUDIT #1\] tool\.request coding_tree abcdef12/.test(output.stdout)) await sleep(50);
88
- assert.match(output.stdout,/\[AUDIT #1\] tool\.request coding_tree abcdef12/);
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=/);
89
121
  child.stdin.end();
90
122
  const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
91
123
  assert.equal(ended.timeout,undefined,'remote session did not exit after foreground input closed');
92
124
  const commands=await traceCommands(fx.trace);
93
125
  assert.deepEqual(commands.slice(-5),['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park']);
94
- assert.match(output.stdout,/DEADBYTE MCP DEVICE SESSION/i);
95
- assert.match(output.stdout,/Live logs/i);
96
- const withoutLiveMarker=output.stdout.replace('📜 [LOG] Live logs active. Press Ctrl+C to disconnect and revoke authority.\n','');
97
- assert.doesNotMatch(withoutLiveMarker,/\p{Extended_Pictographic}/u,'only the live-log marker may use emoji');
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/);
129
+ const withoutApprovedEmoji=output.stdout.replace(/[📜📥📤✅❌⚠♻🛡]/gu,'');
130
+ assert.doesNotMatch(withoutApprovedEmoji,/\p{Extended_Pictographic}/u,'human live stream may use only the approved semantic emoji set');
131
+ }finally{
132
+ if(child?.exitCode===null) child.kill();
133
+ await rm(fx.dir,{recursive:true,force:true});
134
+ }
135
+ });
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);
98
213
  }finally{
99
214
  if(child?.exitCode===null) child.kill();
100
215
  await rm(fx.dir,{recursive:true,force:true});
@@ -105,9 +220,9 @@ winTest('detached guardian revokes authority, parks, and removes the session mar
105
220
  const fx=await fixture();
106
221
  let child=null;
107
222
  try{
108
- 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});
109
224
  const output=await collect(child);
110
- const ready=await waitFor(fx.trace,commands=>commands.includes('hoststatus'));
225
+ const ready=await waitFor(fx.trace,commands=>commands.slice(0,9).join(',')==='start,armprocess,armcoding,armautonomous,armhost,processstatus,codingstatus,autonomousstatus,hoststatus');
111
226
  assert.deepEqual(ready.slice(0,9),[
112
227
  'start','armprocess','armcoding','armautonomous','armhost',
113
228
  'processstatus','codingstatus','autonomousstatus','hoststatus'
@@ -170,6 +285,7 @@ winTest('bare remote recovers a stale crashed session before arming a new one',a
170
285
  const ready=await waitFor(fx.trace,commands=>commands.includes('hoststatus'));
171
286
  assert.deepEqual(ready.slice(0,5),['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park']);
172
287
  assert.equal(ready[5],'start');
288
+ assert.match(output.stdout,/♻️ \[RECOVERY\] Stale remote session pid=2147483000; revoking authority before restart\./);
173
289
  child.stdin.end();
174
290
  const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
175
291
  assert.equal(ended.timeout,undefined);
@@ -180,6 +296,25 @@ winTest('bare remote recovers a stale crashed session before arming a new one',a
180
296
  }
181
297
  });
182
298
 
299
+ winTest('remote warning lines use the approved warning emoji without changing the warning token',async()=>{
300
+ const fx=await fixture();
301
+ let child=null;
302
+ try{
303
+ child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
304
+ const output=await collect(child);
305
+ await waitFor(fx.trace,commands=>commands.includes('hoststatus'));
306
+ const markerPath=path.join(fx.state,'runtime','remote-session.json');
307
+ await writeFile(markerPath,'{invalid-json\n','utf8');
308
+ child.stdin.end();
309
+ const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
310
+ assert.equal(ended.timeout,undefined,'remote session did not exit after warning fixture');
311
+ assert.match(output.stderr,/⚠️ \[WARN\] remote session marker cleanup:/);
312
+ }finally{
313
+ if(child?.exitCode===null) child.kill();
314
+ await rm(fx.dir,{recursive:true,force:true});
315
+ }
316
+ });
317
+
183
318
  winTest('bare remote refuses a second live foreground session without touching authority',async()=>{
184
319
  const fx=await fixture();
185
320
  let child=null;
@@ -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
+ });