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.
- package/CONTEXT.md +41 -0
- package/MANIFEST.SHA256 +348 -83
- package/R34-BASELINE.json +9 -0
- package/README.txt +135 -9
- package/bench/fixtures/corpus.json +17 -0
- package/bin/WORKER-REGISTRY.txt +3 -3
- package/bin/appcontainer-stage.exe +0 -0
- package/bin/appcontainer-stage.obj +0 -0
- package/bin/bootstrap-advapi32.exe +0 -0
- package/bin/bootstrap-advapi32.obj +0 -0
- package/bin/bootstrap-exitcode.exe +0 -0
- package/bin/bootstrap-exitcode.obj +0 -0
- package/bin/bootstrap-kernel32.exe +0 -0
- package/bin/bootstrap-kernel32.obj +0 -0
- package/bin/child-control-probe.exe +0 -0
- package/bin/child-control-probe.obj +0 -0
- package/bin/child-control-stage.exe +0 -0
- package/bin/child-control-stage.obj +0 -0
- package/bin/contained-reverse-worker.exe +0 -0
- package/bin/contained-reverse-worker.obj +0 -0
- package/bin/contained-transform-worker.exe +0 -0
- package/bin/contained-transform-worker.obj +0 -0
- package/bin/containment-probe.exe +0 -0
- package/bin/containment-probe.obj +0 -0
- package/bin/deadbyte-contain.exe +0 -0
- package/bin/deadbyte-contain.obj +0 -0
- package/bin/deadbyte-exec.exe +0 -0
- package/bin/deadbyte-exec.obj +0 -0
- package/bin/deadbyte-process-host.exe +0 -0
- package/bin/deadbyte-process-host.obj +0 -0
- package/bin/deadbyte-tunnel-host.exe +0 -0
- package/bin/deadbyte-tunnel-host.obj +0 -0
- package/controller/README.TXT +10 -4
- package/controller/deadbyte-controller.config.psd1.example +14 -0
- package/controller/deadbyte-controller.ps1 +144 -19
- package/controller/deadbyte-process-policy.json +5 -5
- package/controller/deadbyte-semantic-lsp-config.json +95 -0
- package/deadbyte-mcp-0.8.9.tgz +0 -0
- package/docs/ADR-0001-PRODUCTION-BASELINE-SEAMS.md +29 -0
- package/docs/ARCHITECTURE.md +6 -5
- package/docs/superpowers/plans/2026-09-16-deadbyte-loop-engine.md +846 -0
- package/docs/superpowers/plans/2026-09-17-r35-production-successor.md +408 -0
- package/docs/superpowers/specs/2026-09-16-deadbyte-loop-engine-design.md +435 -0
- package/docs/superpowers/specs/2026-09-17-r35-production-successor-design.md +220 -0
- package/node_modules/typescript/LICENSE.txt +55 -0
- package/node_modules/typescript/README.md +50 -0
- package/node_modules/typescript/SECURITY.md +41 -0
- package/node_modules/typescript/ThirdPartyNoticeText.txt +193 -0
- package/node_modules/typescript/bin/tsc +2 -0
- package/node_modules/typescript/bin/tsserver +2 -0
- package/node_modules/typescript/lib/_tsc.js +133818 -0
- package/node_modules/typescript/lib/_tsserver.js +659 -0
- package/node_modules/typescript/lib/_typingsInstaller.js +222 -0
- package/node_modules/typescript/lib/cs/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/de/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/es/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/fr/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/it/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/ja/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/ko/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/lib.d.ts +22 -0
- package/node_modules/typescript/lib/lib.decorators.d.ts +384 -0
- package/node_modules/typescript/lib/lib.decorators.legacy.d.ts +22 -0
- package/node_modules/typescript/lib/lib.dom.asynciterable.d.ts +41 -0
- package/node_modules/typescript/lib/lib.dom.d.ts +39429 -0
- package/node_modules/typescript/lib/lib.dom.iterable.d.ts +571 -0
- package/node_modules/typescript/lib/lib.es2015.collection.d.ts +147 -0
- package/node_modules/typescript/lib/lib.es2015.core.d.ts +597 -0
- package/node_modules/typescript/lib/lib.es2015.d.ts +28 -0
- package/node_modules/typescript/lib/lib.es2015.generator.d.ts +77 -0
- package/node_modules/typescript/lib/lib.es2015.iterable.d.ts +605 -0
- package/node_modules/typescript/lib/lib.es2015.promise.d.ts +81 -0
- package/node_modules/typescript/lib/lib.es2015.proxy.d.ts +128 -0
- package/node_modules/typescript/lib/lib.es2015.reflect.d.ts +144 -0
- package/node_modules/typescript/lib/lib.es2015.symbol.d.ts +46 -0
- package/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts +326 -0
- package/node_modules/typescript/lib/lib.es2016.array.include.d.ts +116 -0
- package/node_modules/typescript/lib/lib.es2016.d.ts +21 -0
- package/node_modules/typescript/lib/lib.es2016.full.d.ts +23 -0
- package/node_modules/typescript/lib/lib.es2016.intl.d.ts +31 -0
- package/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts +21 -0
- package/node_modules/typescript/lib/lib.es2017.d.ts +26 -0
- package/node_modules/typescript/lib/lib.es2017.date.d.ts +31 -0
- package/node_modules/typescript/lib/lib.es2017.full.d.ts +23 -0
- package/node_modules/typescript/lib/lib.es2017.intl.d.ts +44 -0
- package/node_modules/typescript/lib/lib.es2017.object.d.ts +49 -0
- package/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts +135 -0
- package/node_modules/typescript/lib/lib.es2017.string.d.ts +45 -0
- package/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts +53 -0
- package/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts +77 -0
- package/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts +53 -0
- package/node_modules/typescript/lib/lib.es2018.d.ts +24 -0
- package/node_modules/typescript/lib/lib.es2018.full.d.ts +24 -0
- package/node_modules/typescript/lib/lib.es2018.intl.d.ts +83 -0
- package/node_modules/typescript/lib/lib.es2018.promise.d.ts +30 -0
- package/node_modules/typescript/lib/lib.es2018.regexp.d.ts +37 -0
- package/node_modules/typescript/lib/lib.es2019.array.d.ts +79 -0
- package/node_modules/typescript/lib/lib.es2019.d.ts +24 -0
- package/node_modules/typescript/lib/lib.es2019.full.d.ts +24 -0
- package/node_modules/typescript/lib/lib.es2019.intl.d.ts +23 -0
- package/node_modules/typescript/lib/lib.es2019.object.d.ts +33 -0
- package/node_modules/typescript/lib/lib.es2019.string.d.ts +37 -0
- package/node_modules/typescript/lib/lib.es2019.symbol.d.ts +24 -0
- package/node_modules/typescript/lib/lib.es2020.bigint.d.ts +765 -0
- package/node_modules/typescript/lib/lib.es2020.d.ts +27 -0
- package/node_modules/typescript/lib/lib.es2020.date.d.ts +42 -0
- package/node_modules/typescript/lib/lib.es2020.full.d.ts +24 -0
- package/node_modules/typescript/lib/lib.es2020.intl.d.ts +474 -0
- package/node_modules/typescript/lib/lib.es2020.number.d.ts +28 -0
- package/node_modules/typescript/lib/lib.es2020.promise.d.ts +47 -0
- package/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts +99 -0
- package/node_modules/typescript/lib/lib.es2020.string.d.ts +44 -0
- package/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts +41 -0
- package/node_modules/typescript/lib/lib.es2021.d.ts +23 -0
- package/node_modules/typescript/lib/lib.es2021.full.d.ts +24 -0
- package/node_modules/typescript/lib/lib.es2021.intl.d.ts +166 -0
- package/node_modules/typescript/lib/lib.es2021.promise.d.ts +48 -0
- package/node_modules/typescript/lib/lib.es2021.string.d.ts +33 -0
- package/node_modules/typescript/lib/lib.es2021.weakref.d.ts +78 -0
- package/node_modules/typescript/lib/lib.es2022.array.d.ts +121 -0
- package/node_modules/typescript/lib/lib.es2022.d.ts +25 -0
- package/node_modules/typescript/lib/lib.es2022.error.d.ts +75 -0
- package/node_modules/typescript/lib/lib.es2022.full.d.ts +24 -0
- package/node_modules/typescript/lib/lib.es2022.intl.d.ts +145 -0
- package/node_modules/typescript/lib/lib.es2022.object.d.ts +26 -0
- package/node_modules/typescript/lib/lib.es2022.regexp.d.ts +39 -0
- package/node_modules/typescript/lib/lib.es2022.string.d.ts +25 -0
- package/node_modules/typescript/lib/lib.es2023.array.d.ts +924 -0
- package/node_modules/typescript/lib/lib.es2023.collection.d.ts +21 -0
- package/node_modules/typescript/lib/lib.es2023.d.ts +22 -0
- package/node_modules/typescript/lib/lib.es2023.full.d.ts +24 -0
- package/node_modules/typescript/lib/lib.es2023.intl.d.ts +56 -0
- package/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts +65 -0
- package/node_modules/typescript/lib/lib.es2024.collection.d.ts +29 -0
- package/node_modules/typescript/lib/lib.es2024.d.ts +26 -0
- package/node_modules/typescript/lib/lib.es2024.full.d.ts +24 -0
- package/node_modules/typescript/lib/lib.es2024.object.d.ts +29 -0
- package/node_modules/typescript/lib/lib.es2024.promise.d.ts +35 -0
- package/node_modules/typescript/lib/lib.es2024.regexp.d.ts +25 -0
- package/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts +68 -0
- package/node_modules/typescript/lib/lib.es2024.string.d.ts +29 -0
- package/node_modules/typescript/lib/lib.es5.d.ts +4601 -0
- package/node_modules/typescript/lib/lib.es6.d.ts +23 -0
- package/node_modules/typescript/lib/lib.esnext.array.d.ts +35 -0
- package/node_modules/typescript/lib/lib.esnext.collection.d.ts +96 -0
- package/node_modules/typescript/lib/lib.esnext.d.ts +29 -0
- package/node_modules/typescript/lib/lib.esnext.decorators.d.ts +28 -0
- package/node_modules/typescript/lib/lib.esnext.disposable.d.ts +193 -0
- package/node_modules/typescript/lib/lib.esnext.error.d.ts +24 -0
- package/node_modules/typescript/lib/lib.esnext.float16.d.ts +445 -0
- package/node_modules/typescript/lib/lib.esnext.full.d.ts +24 -0
- package/node_modules/typescript/lib/lib.esnext.intl.d.ts +21 -0
- package/node_modules/typescript/lib/lib.esnext.iterator.d.ts +148 -0
- package/node_modules/typescript/lib/lib.esnext.promise.d.ts +34 -0
- package/node_modules/typescript/lib/lib.esnext.sharedmemory.d.ts +25 -0
- package/node_modules/typescript/lib/lib.scripthost.d.ts +322 -0
- package/node_modules/typescript/lib/lib.webworker.asynciterable.d.ts +41 -0
- package/node_modules/typescript/lib/lib.webworker.d.ts +13150 -0
- package/node_modules/typescript/lib/lib.webworker.importscripts.d.ts +23 -0
- package/node_modules/typescript/lib/lib.webworker.iterable.d.ts +340 -0
- package/node_modules/typescript/lib/pl/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/pt-br/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/ru/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/tr/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/tsc.js +8 -0
- package/node_modules/typescript/lib/tsserver.js +8 -0
- package/node_modules/typescript/lib/tsserverlibrary.d.ts +17 -0
- package/node_modules/typescript/lib/tsserverlibrary.js +21 -0
- package/node_modules/typescript/lib/typesMap.json +497 -0
- package/node_modules/typescript/lib/typescript.d.ts +11437 -0
- package/node_modules/typescript/lib/typescript.js +200276 -0
- package/node_modules/typescript/lib/typingsInstaller.js +8 -0
- package/node_modules/typescript/lib/watchGuard.js +53 -0
- package/node_modules/typescript/lib/zh-cn/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/lib/zh-tw/diagnosticMessages.generated.json +2122 -0
- package/node_modules/typescript/package.json +120 -0
- package/package.json +5 -3
- package/proof/CONTAINMENT-BUILD.txt +6 -6
- package/proof/R34-TASK8-SUPERVISOR-CHECKPOINT.json +29 -0
- package/proof/R34-TASK9-MCP-SURFACE-CHECKPOINT.json +28 -0
- package/scripts/capability-benchmark.mjs +27 -0
- package/scripts/deferred-slot-operation.mjs +4 -2
- package/scripts/final-closure-verify.mjs +10 -10
- package/scripts/final-closure.mjs +11 -11
- package/scripts/gate-windows.ps1 +3 -3
- package/scripts/release-parity.mjs +14 -14
- package/scripts/semantic-preflight.ps1 +73 -0
- package/scripts/tool-surface-snapshot.mjs +73 -0
- package/scripts/windows-gate-evidence.mjs +5 -5
- package/src/audit-verify.mjs +6 -2
- package/src/autonomous-action-reconcile.mjs +142 -0
- package/src/autonomous-context-engine.mjs +255 -0
- package/src/autonomous-live-state.mjs +17 -0
- package/src/autonomous-local-supervisor.mjs +249 -0
- package/src/autonomous-loop-state.mjs +304 -0
- package/src/autonomous-output-contracts.mjs +22 -3
- package/src/autonomous-plan.mjs +181 -0
- package/src/autonomous-planner-contracts.mjs +44 -0
- package/src/autonomous-planner.mjs +91 -6
- package/src/autonomous-policy.mjs +15 -2
- package/src/autonomous-progress.mjs +127 -0
- package/src/autonomous-runtime.mjs +601 -48
- package/src/autonomous-supervisor-host.mjs +70 -0
- package/src/autonomous-supervisor.mjs +31 -8
- package/src/capability-benchmark-runner.mjs +108 -0
- package/src/capability-benchmark.mjs +50 -0
- package/src/coding-mcp-tools.mjs +46 -3
- package/src/coding-output-contracts.mjs +45 -0
- package/src/context-provenance.mjs +86 -0
- package/src/deadbyte-cli.mjs +136 -30
- package/src/document-adapter.mjs +43 -0
- package/src/lsp-stdio-client.mjs +112 -0
- package/src/machine-fs-smoke-client.mjs +2 -1
- package/src/mcp-server.mjs +17 -3
- package/src/observation-smoke-client.mjs +3 -2
- package/src/operator-surface.mjs +37 -0
- package/src/provider-circuit.mjs +125 -0
- package/src/release-generation.mjs +44 -5
- package/src/remote-mcp-autonomous-smoke-client.mjs +53 -14
- package/src/remote-mcp-coding-smoke-client.mjs +5 -4
- package/src/remote-mcp-r24-disarmed-smoke-client.mjs +4 -2
- package/src/remote-mcp-r33-parity-client.mjs +1 -1
- package/src/remote-mcp-r34-parity-client.mjs +177 -0
- package/src/remote-mcp-smoke-client.mjs +2 -1
- package/src/remote-result-journal.mjs +114 -0
- package/src/runtime-update.mjs +58 -8
- package/src/semantic-backend-registry.mjs +39 -0
- package/src/semantic-code.mjs +179 -0
- package/src/semantic-lsp-backend.mjs +183 -0
- package/src/semantic-lsp-config.mjs +112 -0
- package/src/tool-surface-ledger.mjs +92 -0
- package/src/version.mjs +1 -1
- package/test/audit-verify.test.mjs +1 -1
- package/test/autonomous-action-reconcile.test.mjs +106 -0
- package/test/autonomous-adversarial.test.mjs +149 -6
- package/test/autonomous-context-engine.test.mjs +181 -0
- package/test/autonomous-live-state.test.mjs +27 -0
- package/test/autonomous-local-supervisor.test.mjs +403 -0
- package/test/autonomous-loop-state.test.mjs +126 -0
- package/test/autonomous-loop-v2.test.mjs +105 -0
- package/test/autonomous-loop.test.mjs +79 -1
- package/test/autonomous-output-contract.test.mjs +54 -0
- package/test/autonomous-plan.test.mjs +101 -0
- package/test/autonomous-progress.test.mjs +106 -0
- package/test/autonomous-r34-e2e.test.mjs +338 -0
- package/test/autonomous-runtime.test.mjs +3 -3
- package/test/autonomous-supervisor-integration.test.mjs +48 -3
- package/test/capability-benchmark-runner.test.mjs +49 -0
- package/test/capability-benchmark.test.mjs +47 -0
- package/test/cli-entrypoint.test.mjs +12 -0
- package/test/coding-catalog-consistency.test.mjs +24 -0
- package/test/coding-plane.test.mjs +3 -3
- package/test/context-provenance.test.mjs +61 -0
- package/test/controller-r27.test.mjs +4 -3
- package/test/controller.test.mjs +52 -0
- package/test/core.test.mjs +1 -1
- package/test/deferred-slot-operation-behavior.test.mjs +5 -1
- package/test/deferred-slot-operation.test.mjs +2 -1
- package/test/document-adapter.test.mjs +23 -0
- package/test/fixtures/lsp-framed-server.mjs +33 -0
- package/test/fixtures/semantic/cpp/compile_commands.json +4 -0
- package/test/fixtures/semantic/cpp/lib.cpp +2 -0
- package/test/fixtures/semantic/cpp/lib.hpp +2 -0
- package/test/fixtures/semantic/cpp/main.cpp +2 -0
- package/test/fixtures/semantic/python/lib.py +2 -0
- package/test/fixtures/semantic/python/main.py +2 -0
- package/test/fixtures/semantic/rust/Cargo.lock +7 -0
- package/test/fixtures/semantic/rust/Cargo.toml +8 -0
- package/test/fixtures/semantic/rust/src/lib.rs +3 -0
- package/test/fixtures/semantic/rust/src/main.rs +5 -0
- package/test/fixtures/semantic/rust/src/math.rs +3 -0
- package/test/fixtures/semantic/rust/target/.rustc_info.json +1 -0
- package/test/fixtures/semantic/rust/target/CACHEDIR.TAG +3 -0
- package/test/fixtures/semantic/rust/target/debug/.cargo-lock +0 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/dep-test-lib-semantic_rust +0 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/invoked.timestamp +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/test-lib-semantic_rust +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-4c168fa33c79d09c/test-lib-semantic_rust.json +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/dep-test-bin-semantic_rust_bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/invoked.timestamp +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/test-bin-semantic_rust_bin +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-5dcd474439c54a26/test-bin-semantic_rust_bin.json +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/dep-lib-semantic_rust +0 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/invoked.timestamp +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/lib-semantic_rust +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-6212ccd976aa3808/lib-semantic_rust.json +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/bin-semantic_rust_bin +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/bin-semantic_rust_bin.json +1 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/dep-bin-semantic_rust_bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/.fingerprint/semantic_rust-d741378dccdef61c/invoked.timestamp +1 -0
- package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust-4c168fa33c79d09c.rmeta +0 -0
- package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust-6212ccd976aa3808.rmeta +0 -0
- package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust_bin-5dcd474439c54a26.rmeta +0 -0
- package/test/fixtures/semantic/rust/target/debug/deps/libsemantic_rust_bin-d741378dccdef61c.rmeta +0 -0
- package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust-4c168fa33c79d09c.d +5 -0
- package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust-6212ccd976aa3808.d +5 -0
- package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust_bin-5dcd474439c54a26.d +6 -0
- package/test/fixtures/semantic/rust/target/debug/deps/semantic_rust_bin-d741378dccdef61c.d +6 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/dep-graph.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/query-cache.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc-1qb77z00k06rqw4jdkj92spax/work-products.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-1nzlugxi6lq16/s-hmdgo8b6hg-1n6glhc.lock +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/dep-graph.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/metadata.rmeta +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/query-cache.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq-9twkpivsqnjon278x20bddozq/work-products.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust-3s436v7g6f5xm/s-hmdgo8b58k-1ekj4lq.lock +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/dep-graph.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/query-cache.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3-cmu3jai030no72y8u9eurrnjj/work-products.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-1jxcbdeehal7q/s-hmdgo8bxlf-1qr24o3.lock +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/dep-graph.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/query-cache.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt-diy9mqvc2eoiblmhjs3stcgi3/work-products.bin +0 -0
- package/test/fixtures/semantic/rust/target/debug/incremental/semantic_rust_bin-2ocx55p60ni6b/s-hmdgo8bxj8-0ir41qt.lock +0 -0
- package/test/fixtures/semantic/rust/target/flycheck0/stderr +1 -0
- package/test/fixtures/semantic/rust/target/flycheck0/stdout +5 -0
- package/test/fixtures/semantic/typescript/lib.ts +3 -0
- package/test/fixtures/semantic/typescript/main.ts +2 -0
- package/test/fixtures/tool-surface-stdio-server.mjs +14 -0
- package/test/helpers/autonomous-r34-fixture.mjs +120 -0
- package/test/lsp-stdio-client.test.mjs +72 -0
- package/test/multi-file-read.test.mjs +41 -0
- package/test/observation-integration.test.mjs +3 -3
- package/test/production-docs.test.mjs +48 -0
- package/test/prompts-resources.test.mjs +35 -0
- package/test/provider-circuit.test.mjs +93 -0
- package/test/public-autonomous-ingress-budget.test.mjs +28 -0
- package/test/r33-closeout-regression.test.mjs +3 -3
- package/test/r33-finalization.test.mjs +19 -16
- package/test/release-generation.test.mjs +23 -2
- package/test/release-version.test.mjs +24 -17
- package/test/remote-r24-catalog.test.mjs +5 -4
- package/test/remote-result-journal.test.mjs +58 -0
- package/test/remote-session-cli.test.mjs +150 -15
- package/test/runtime-self-update.test.mjs +63 -0
- package/test/semantic-backend-registry.test.mjs +29 -0
- package/test/semantic-code.test.mjs +66 -0
- package/test/semantic-lsp-backend.test.mjs +99 -0
- package/test/semantic-lsp-config.test.mjs +81 -0
- package/test/semantic-lsp-readiness.test.mjs +34 -0
- package/test/semantic-lsp-transient-empty.test.mjs +32 -0
- package/test/semantic-lsp-transient-null.test.mjs +31 -0
- package/test/semantic-multilang.test.mjs +72 -0
- package/test/semantic-runtime-routing.test.mjs +32 -0
- package/test/semantic-server-config-integration.test.mjs +66 -0
- package/test/tool-surface-ledger.test.mjs +59 -0
- package/test/tool-surface-snapshot.test.mjs +17 -0
- package/test/tracer-bullet.test.mjs +77 -0
|
@@ -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
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import { createHash } from 'node:crypto';
|
|
6
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
7
|
+
import { parseSemanticLspConfig, loadSemanticLspBackends, semanticConfigBindingFromEnv } from '../src/semantic-lsp-config.mjs';
|
|
8
|
+
|
|
9
|
+
const H='a'.repeat(64);
|
|
10
|
+
const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
11
|
+
|
|
12
|
+
test('semantic LSP config normalizes explicit pinned server identities',()=>{
|
|
13
|
+
const exe=path.resolve('tools','server.exe');
|
|
14
|
+
const dep=path.resolve('tools','server.js');
|
|
15
|
+
const parsed=parseSemanticLspConfig({schema:'deadbyte.semantic-lsp-config.v1',servers:[{
|
|
16
|
+
id:'pyright',language_id:'python',extensions:['.PY','.pyi'],executable_path:exe,executable_sha256:H,
|
|
17
|
+
args:['server.js','--stdio'],dependencies:[{path:dep,expected_sha256:H}],required:true
|
|
18
|
+
}]});
|
|
19
|
+
assert.deepEqual(parsed.servers[0],{
|
|
20
|
+
id:'pyright',language_id:'python',extensions:['.py','.pyi'],executable_path:exe,executable_sha256:H,args:['server.js','--stdio'],env:{},dependencies:[{path:dep,expectedSha256:H}],initialization_options:{},request_timeout_ms:10000,max_message_bytes:4194304,startup_settle_ms:0,null_result_retry_ms:0,null_result_max_attempts:1,retry_empty_results:false,required:true
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test('semantic LSP config rejects unpinned, relative, duplicate, or ambiguous server declarations',()=>{
|
|
25
|
+
const exe=path.resolve('tools','server.exe');
|
|
26
|
+
assert.throws(()=>parseSemanticLspConfig({schema:'wrong',servers:[]}),/schema/i);
|
|
27
|
+
assert.throws(()=>parseSemanticLspConfig({schema:'deadbyte.semantic-lsp-config.v1',servers:[{id:'python',extensions:['.py'],executable_path:'relative.exe',executable_sha256:H}]}),/absolute/i);
|
|
28
|
+
assert.throws(()=>parseSemanticLspConfig({schema:'deadbyte.semantic-lsp-config.v1',servers:[{id:'python',extensions:['.py'],executable_path:exe,executable_sha256:'bad'}]}),/sha-256/i);
|
|
29
|
+
assert.throws(()=>parseSemanticLspConfig({schema:'deadbyte.semantic-lsp-config.v1',servers:[{id:'a',extensions:['.x'],executable_path:exe,executable_sha256:H},{id:'a',extensions:['.y'],executable_path:exe,executable_sha256:H}]}),/duplicate.*id/i);
|
|
30
|
+
assert.throws(()=>parseSemanticLspConfig({schema:'deadbyte.semantic-lsp-config.v1',servers:[{id:'a',extensions:['.x'],executable_path:exe,executable_sha256:H},{id:'b',extensions:['.X'],executable_path:exe,executable_sha256:H}]}),/extension.*already/i);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('semantic LSP config bounds startup settle to five seconds',()=>{
|
|
34
|
+
const exe=path.resolve('tools','server.exe');
|
|
35
|
+
const make=value=>({schema:'deadbyte.semantic-lsp-config.v1',servers:[{id:'ready',extensions:['.x'],executable_path:exe,executable_sha256:H,startup_settle_ms:value}]});
|
|
36
|
+
assert.equal(parseSemanticLspConfig(make(5000)).servers[0].startup_settle_ms,5000);
|
|
37
|
+
assert.throws(()=>parseSemanticLspConfig(make(-1)),/startup_settle_ms invalid/i);
|
|
38
|
+
assert.throws(()=>parseSemanticLspConfig(make(5001)),/startup_settle_ms invalid/i);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('semantic LSP config bounds transient read retry policy and keeps empty-result retries opt-in',()=>{
|
|
42
|
+
const exe=path.resolve('tools','server.exe');
|
|
43
|
+
const make=extra=>({schema:'deadbyte.semantic-lsp-config.v1',servers:[{id:'retry',extensions:['.x'],executable_path:exe,executable_sha256:H,...extra}]});
|
|
44
|
+
const parsed=parseSemanticLspConfig(make({null_result_retry_ms:100,null_result_max_attempts:10,retry_empty_results:true})).servers[0];
|
|
45
|
+
assert.equal(parsed.null_result_retry_ms,100);assert.equal(parsed.null_result_max_attempts,10);assert.equal(parsed.retry_empty_results,true);
|
|
46
|
+
assert.throws(()=>parseSemanticLspConfig(make({null_result_retry_ms:0,null_result_max_attempts:2})),/retry_ms required/i);
|
|
47
|
+
assert.throws(()=>parseSemanticLspConfig(make({null_result_retry_ms:1001,null_result_max_attempts:2})),/retry_ms invalid/i);
|
|
48
|
+
assert.throws(()=>parseSemanticLspConfig(make({null_result_retry_ms:10,null_result_max_attempts:21})),/max_attempts invalid/i);
|
|
49
|
+
assert.throws(()=>parseSemanticLspConfig(make({retry_empty_results:'yes'})),/retry_empty_results invalid/i);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('semantic LSP config load verifies executable and dependency bytes before producing backends',async()=>{
|
|
53
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-semantic-config-'));
|
|
54
|
+
try{
|
|
55
|
+
const exe=process.execPath;
|
|
56
|
+
const exeSha=sha256(await import('node:fs/promises').then(m=>m.readFile(exe)));
|
|
57
|
+
const dep=path.join(root,'server.js');
|
|
58
|
+
const depBytes=Buffer.from('export default 1;\n','utf8');
|
|
59
|
+
await writeFile(dep,depBytes);
|
|
60
|
+
const configPath=path.join(root,'semantic.json');
|
|
61
|
+
const body={schema:'deadbyte.semantic-lsp-config.v1',servers:[{id:'python',extensions:['.py'],executable_path:exe,executable_sha256:exeSha,args:[dep,'--stdio'],dependencies:[{path:dep,expected_sha256:sha256(depBytes)}],required:true}]};
|
|
62
|
+
await writeFile(configPath,JSON.stringify(body),'utf8');
|
|
63
|
+
const configSha=sha256(Buffer.from(JSON.stringify(body),'utf8'));
|
|
64
|
+
const loaded=await loadSemanticLspBackends({configPath,expectedConfigSha256:configSha,codingRuntime:{}});
|
|
65
|
+
assert.equal(loaded.backends.length,1);
|
|
66
|
+
assert.equal(loaded.backends[0].id,'python');
|
|
67
|
+
assert.deepEqual(loaded.required_ids,['python']);
|
|
68
|
+
await assert.rejects(loadSemanticLspBackends({configPath,expectedConfigSha256:'0'.repeat(64),codingRuntime:{}}),/config SHA-256 mismatch/i);
|
|
69
|
+
body.servers[0].dependencies[0].expected_sha256='0'.repeat(64);
|
|
70
|
+
await writeFile(configPath,JSON.stringify(body),'utf8');
|
|
71
|
+
const tamperedConfigSha=sha256(Buffer.from(JSON.stringify(body),'utf8'));
|
|
72
|
+
await assert.rejects(loadSemanticLspBackends({configPath,expectedConfigSha256:tamperedConfigSha,codingRuntime:{}}),/dependency SHA-256 mismatch/i);
|
|
73
|
+
} finally {await rm(root,{recursive:true,force:true});}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('semantic LSP environment binding requires config path and SHA-256 together',()=>{
|
|
77
|
+
assert.equal(semanticConfigBindingFromEnv({}),null);
|
|
78
|
+
assert.throws(()=>semanticConfigBindingFromEnv({DEADBYTE_SEMANTIC_LSP_CONFIG:'C:/semantic.json'}),/requires.*SHA-256/i);
|
|
79
|
+
assert.throws(()=>semanticConfigBindingFromEnv({DEADBYTE_SEMANTIC_LSP_CONFIG_SHA256:H}),/requires.*config path/i);
|
|
80
|
+
assert.deepEqual(semanticConfigBindingFromEnv({DEADBYTE_SEMANTIC_LSP_CONFIG:'C:/semantic.json',DEADBYTE_SEMANTIC_LSP_CONFIG_SHA256:H}),{configPath:'C:/semantic.json',expectedConfigSha256:H});
|
|
81
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
test('semantic LSP backend honors bounded startup settle before cross-file request',async()=>{
|
|
16
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-lsp-ready-'));
|
|
17
|
+
await writeFile(path.join(root,'main.foo'),'export function main() { return alpha(); }\n','utf8');
|
|
18
|
+
await writeFile(path.join(root,'peer.foo'),'export function alpha() { return 1; }\n','utf8');
|
|
19
|
+
const codingRuntime={
|
|
20
|
+
policy:{roots:{project:{real_path:root,read:true,write:true,exec:false,deny_paths:[]}}},
|
|
21
|
+
async sessionStatus(){return {armed:true,reason:'standing-grant',root_ids:['project']};},
|
|
22
|
+
async tree(){return {truncated:false,entries:[{type:'file',path:'main.foo'},{type:'file',path:'peer.foo'}]};},
|
|
23
|
+
async fileRead({relativePath}){const content=await readFile(path.join(root,relativePath),'utf8');return {status:'ok',content,sha256:sha256(Buffer.from(content,'utf8'))};},
|
|
24
|
+
async textReplace(){throw new Error('not used');}
|
|
25
|
+
};
|
|
26
|
+
try{
|
|
27
|
+
const fixtureSha=sha256(await readFile(fixture));
|
|
28
|
+
const backend=createSemanticLspBackend({id:'fixture-ready',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,readyAfterMs:500},startup_settle_ms:600,request_timeout_ms:2000,max_message_bytes:131072}});
|
|
29
|
+
const started=Date.now();
|
|
30
|
+
const definition=await backend.definition({rootId:'project',relativePath:'main.foo',line:0,column:34,maxResults:10});
|
|
31
|
+
assert.ok(Date.now()-started>=500,'backend returned before configured server readiness boundary');
|
|
32
|
+
assert.ok(definition.locations.some(item=>item.path==='peer.foo'),JSON.stringify(definition.locations));
|
|
33
|
+
} finally {await rm(root,{recursive:true,force:true});}
|
|
34
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
test('semantic LSP backend retries transient empty read results only when explicitly enabled',async()=>{
|
|
16
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-lsp-empty-'));
|
|
17
|
+
await writeFile(path.join(root,'main.foo'),'export function main() { return alpha(); }\n','utf8');
|
|
18
|
+
await writeFile(path.join(root,'peer.foo'),'export function alpha() { return 1; }\n','utf8');
|
|
19
|
+
const codingRuntime={
|
|
20
|
+
policy:{roots:{project:{real_path:root,read:true,write:true,exec:false,deny_paths:[]}}},
|
|
21
|
+
async sessionStatus(){return {armed:true,reason:'standing-grant',root_ids:['project']};},
|
|
22
|
+
async tree(){return {truncated:false,entries:[{type:'file',path:'main.foo'},{type:'file',path:'peer.foo'}]};},
|
|
23
|
+
async fileRead({relativePath}){const content=await readFile(path.join(root,relativePath),'utf8');return {status:'ok',content,sha256:sha256(Buffer.from(content,'utf8'))};},
|
|
24
|
+
async textReplace(){throw new Error('not used');}
|
|
25
|
+
};
|
|
26
|
+
try{
|
|
27
|
+
const fixtureSha=sha256(await readFile(fixture));
|
|
28
|
+
const backend=createSemanticLspBackend({id:'fixture-empty',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,referencesEmptyCount:1},null_result_retry_ms:25,null_result_max_attempts:3,retry_empty_results:true,request_timeout_ms:2000,max_message_bytes:131072}});
|
|
29
|
+
const references=await backend.references({rootId:'project',relativePath:'peer.foo',line:0,column:16,maxResults:20});
|
|
30
|
+
assert.ok(references.locations.some(item=>item.path==='main.foo'),JSON.stringify(references.locations));
|
|
31
|
+
} finally {await rm(root,{recursive:true,force:true});}
|
|
32
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
test('semantic LSP backend retries only transient null read results within configured bound',async()=>{
|
|
16
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-lsp-null-'));
|
|
17
|
+
await writeFile(path.join(root,'main.foo'),'export function alpha() { return 1; }\n','utf8');
|
|
18
|
+
const codingRuntime={
|
|
19
|
+
policy:{roots:{project:{real_path:root,read:true,write:true,exec:false,deny_paths:[]}}},
|
|
20
|
+
async sessionStatus(){return {armed:true,reason:'standing-grant',root_ids:['project']};},
|
|
21
|
+
async tree(){return {truncated:false,entries:[{type:'file',path:'main.foo'}]};},
|
|
22
|
+
async fileRead({relativePath}){const content=await readFile(path.join(root,relativePath),'utf8');return {status:'ok',content,sha256:sha256(Buffer.from(content,'utf8'))};},
|
|
23
|
+
async textReplace(){throw new Error('not used');}
|
|
24
|
+
};
|
|
25
|
+
try{
|
|
26
|
+
const fixtureSha=sha256(await readFile(fixture));
|
|
27
|
+
const backend=createSemanticLspBackend({id:'fixture-null',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',documentSymbolNullCount:1},null_result_retry_ms:25,null_result_max_attempts:3,request_timeout_ms:2000,max_message_bytes:131072}});
|
|
28
|
+
const outline=await backend.outline({rootId:'project',relativePath:'main.foo',maxSymbols:20});
|
|
29
|
+
assert.ok(outline.symbols.some(item=>item.name==='alpha'),JSON.stringify(outline.symbols));
|
|
30
|
+
} finally {await rm(root,{recursive:true,force:true});}
|
|
31
|
+
});
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { cp, 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 fixtureRoot=path.join(here,'fixtures','semantic');
|
|
17
|
+
const semanticConfigPath=process.env.DEADBYTE_R35_SEMANTIC_CONFIG??'';
|
|
18
|
+
const semanticConfigSha256=process.env.DEADBYTE_R35_SEMANTIC_CONFIG_SHA256??'';
|
|
19
|
+
const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
20
|
+
const sha256File=async file=>sha256(await readFile(file));
|
|
21
|
+
|
|
22
|
+
function structured(value,label){
|
|
23
|
+
if(value.isError) throw new Error(`${label}: ${JSON.stringify(value.structuredContent??value.content)}`);
|
|
24
|
+
return value.structuredContent;
|
|
25
|
+
}
|
|
26
|
+
function positionOf(text,needle,occurrence=0){
|
|
27
|
+
let index=-1,start=0;
|
|
28
|
+
for(let i=0;i<=occurrence;i++){index=text.indexOf(needle,start);if(index<0)throw new Error(`missing ${needle} occurrence ${occurrence}`);start=index+needle.length;}
|
|
29
|
+
const before=text.slice(0,index);const lines=before.split('\n');return {line:lines.length-1,column:lines.at(-1).length};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function makeFixture(language){
|
|
33
|
+
const root=await mkdtemp(path.join(os.tmpdir(),`deadbyte-semantic-${language}-`));
|
|
34
|
+
const project=path.join(root,'project');const trust=path.join(root,'trust');
|
|
35
|
+
await cp(path.join(fixtureRoot,language),project,{recursive:true});await mkdir(trust);
|
|
36
|
+
const keys=await generateTrustKeypair({privateKeyPath:path.join(trust,'private.pem'),publicKeyPath:path.join(trust,'public.pem')});
|
|
37
|
+
const policyPath=path.join(root,'coding-policy.json');const leasePath=path.join(root,'coding-lease.json');
|
|
38
|
+
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','target']}},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');
|
|
39
|
+
const policy=await loadCodingPolicy(policyPath);
|
|
40
|
+
await writeFile(leasePath,JSON.stringify({schema:'deadbyte.coding-lease.v1',policy_sha256:policy.policy_sha256,instance_nonce:'d'.repeat(64),root_ids:['project'],armed_at_utc:new Date().toISOString(),expires_at_utc:new Date(Date.now()+3600000).toISOString()}),'utf8');
|
|
41
|
+
const client=new Client({name:`deadbyte-r35-${language}`,version:'0.9.0'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
|
|
42
|
+
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,DEADBYTE_SEMANTIC_LSP_CONFIG:semanticConfigPath,DEADBYTE_SEMANTIC_LSP_CONFIG_SHA256:semanticConfigSha256},stderr:'pipe'});
|
|
43
|
+
return {root,project,client,transport};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const cases=[
|
|
47
|
+
{id:'python',engine:'pyright',outline:'lib.py',use:'main.py',useOccurrence:1,definitionPaths:['lib.py'],referencePath:'main.py',replacement:'def alpha(x: int) -> int:\n return x + 2',replacementNeedle:'return x + 2'},
|
|
48
|
+
{id:'rust',engine:'rust-analyzer',outline:'src/math.rs',use:'src/main.rs',useOccurrence:1,definitionPaths:['src/math.rs'],referencePath:'src/main.rs',replacement:'pub fn alpha(x: i32) -> i32 {\n x + 2\n}',replacementNeedle:'x + 2'},
|
|
49
|
+
{id:'cpp',engine:'clangd',outline:'lib.cpp',use:'main.cpp',useOccurrence:0,definitionPaths:['lib.hpp','lib.cpp'],referencePath:'main.cpp',replacement:'int alpha(int x) { return x + 2; }',replacementNeedle:'return x + 2'}
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
for(const entry of cases){
|
|
53
|
+
test(`R35 ${entry.id} semantic tracer proves outline definition references and receipt-backed replace`,{skip:!(semanticConfigPath&&semanticConfigSha256),timeout:120000},async()=>{
|
|
54
|
+
const f=await makeFixture(entry.id);
|
|
55
|
+
try{
|
|
56
|
+
await f.client.connect(f.transport);
|
|
57
|
+
const outline=structured(await f.client.callTool({name:'coding_symbol_outline',arguments:{root_id:'project',path:entry.outline,max_symbols:100}}),'outline');
|
|
58
|
+
assert.equal(outline.engine,entry.engine);
|
|
59
|
+
const alpha=outline.symbols.find(item=>item.name==='alpha');assert.ok(alpha,'alpha symbol missing');
|
|
60
|
+
const useText=await readFile(path.join(f.project,...entry.use.split('/')),'utf8');const usePos=positionOf(useText,'alpha',entry.useOccurrence);
|
|
61
|
+
const definition=structured(await f.client.callTool({name:'coding_symbol_definition',arguments:{root_id:'project',path:entry.use,line:usePos.line,column:usePos.column,max_results:50}}),'definition');
|
|
62
|
+
assert.ok(definition.locations.some(item=>entry.definitionPaths.includes(item.path)),`definition paths=${definition.locations.map(x=>x.path).join(',')}`);
|
|
63
|
+
const references=structured(await f.client.callTool({name:'coding_symbol_references',arguments:{root_id:'project',path:entry.outline,line:alpha.name_start_line,column:alpha.name_start_column,max_results:100}}),'references');
|
|
64
|
+
assert.ok(references.locations.some(item=>item.path===entry.referencePath),`references=${references.locations.map(x=>x.path).join(',')}`);
|
|
65
|
+
const before=structured(await f.client.callTool({name:'coding_file_read',arguments:{root_id:'project',path:entry.outline,encoding:'utf8'}}),'before');
|
|
66
|
+
const edited=structured(await f.client.callTool({name:'coding_symbol_replace',arguments:{root_id:'project',path:entry.outline,symbol_id:alpha.symbol_id,new_body:entry.replacement,expected_sha256:before.sha256}}),'replace');
|
|
67
|
+
assert.equal(edited.status,'committed');assert.equal(edited.engine,entry.engine);
|
|
68
|
+
const receipt=structured(await f.client.callTool({name:'coding_receipt_verify',arguments:{receipt_id:edited.receipt_id}}),'receipt');assert.equal(receipt.ok,true);
|
|
69
|
+
assert.match(await readFile(path.join(f.project,...entry.outline.split('/')),'utf8'),new RegExp(entry.replacementNeedle.replaceAll('+','\\+')));
|
|
70
|
+
} finally {await f.client.close().catch(()=>{});await rm(f.root,{recursive:true,force:true}).catch(()=>{});}
|
|
71
|
+
});
|
|
72
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createSemanticCodeRuntime } from '../src/semantic-code.mjs';
|
|
4
|
+
|
|
5
|
+
const codingRuntime={};
|
|
6
|
+
const calls=[];
|
|
7
|
+
const fake={
|
|
8
|
+
id:'fixture',extensions:new Set(['.foo']),
|
|
9
|
+
async outline(ctx){calls.push(['outline',ctx]);return {status:'ok',engine:'fixture',symbols:[]};},
|
|
10
|
+
async definition(ctx){calls.push(['definition',ctx]);return {status:'ok',engine:'fixture',locations:[]};},
|
|
11
|
+
async references(ctx){calls.push(['references',ctx]);return {status:'ok',engine:'fixture',locations:[]};},
|
|
12
|
+
async replaceSymbol(ctx){calls.push(['replaceSymbol',ctx]);return {status:'committed',engine:'fixture'};},
|
|
13
|
+
async diagnostics(ctx){calls.push(['diagnostics',ctx]);return {status:'ok',engine:'fixture',diagnostics:[]};}
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
test('semantic runtime routes all operations through an injected backend registry without changing public arguments',async()=>{
|
|
17
|
+
calls.length=0;
|
|
18
|
+
const runtime=createSemanticCodeRuntime({codingRuntime,backends:[fake]});
|
|
19
|
+
assert.equal((await runtime.outline({rootId:'r',relativePath:'src/a.foo',maxSymbols:7})).engine,'fixture');
|
|
20
|
+
assert.equal((await runtime.definition({rootId:'r',relativePath:'src/a.foo',line:1,column:2,maxResults:3})).engine,'fixture');
|
|
21
|
+
assert.equal((await runtime.references({rootId:'r',relativePath:'src/a.foo',line:1,column:2,maxResults:4})).engine,'fixture');
|
|
22
|
+
assert.equal((await runtime.replaceSymbol({rootId:'r',relativePath:'src/a.foo',symbolId:'s',newBody:'x',expectedSha256:'a'.repeat(64)})).engine,'fixture');
|
|
23
|
+
assert.equal((await runtime.diagnostics({rootId:'r',relativePath:'src/a.foo'})).engine,'fixture');
|
|
24
|
+
assert.deepEqual(calls.map(item=>item[0]),['outline','definition','references','replaceSymbol','diagnostics']);
|
|
25
|
+
assert.equal(calls[0][1].rootId,'r');
|
|
26
|
+
assert.equal(calls[0][1].relativePath,'src/a.foo');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('semantic runtime fails closed instead of falling back to text search for unknown extensions',async()=>{
|
|
30
|
+
const runtime=createSemanticCodeRuntime({codingRuntime,backends:[fake]});
|
|
31
|
+
await assert.rejects(runtime.outline({rootId:'r',relativePath:'src/a.rs'}),/unsupported semantic language: \.rs/i);
|
|
32
|
+
});
|
|
@@ -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 cliPath=path.join(repoRoot,'src','deadbyte-cli.mjs');
|
|
16
|
+
const lspFixture=path.join(here,'fixtures','lsp-framed-server.mjs');
|
|
17
|
+
const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
18
|
+
const sha256File=async file=>sha256(await readFile(file));
|
|
19
|
+
|
|
20
|
+
function structured(value,label){
|
|
21
|
+
if(value.isError) throw new Error(`${label} failed: ${JSON.stringify(value.structuredContent??value.content)}`);
|
|
22
|
+
assert.ok(value.structuredContent&&typeof value.structuredContent==='object',`${label} missing structuredContent`);
|
|
23
|
+
return value.structuredContent;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
async function fixture(){
|
|
27
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-semantic-server-'));
|
|
28
|
+
const project=path.join(root,'project');
|
|
29
|
+
const trust=path.join(root,'trust');
|
|
30
|
+
await mkdir(project); await mkdir(trust);
|
|
31
|
+
const keys=await generateTrustKeypair({privateKeyPath:path.join(trust,'private.pem'),publicKeyPath:path.join(trust,'public.pem')});
|
|
32
|
+
await writeFile(path.join(project,'main.foo'),'export function alpha() {}\n','utf8');
|
|
33
|
+
const policyPath=path.join(root,'coding-policy.json');
|
|
34
|
+
const leasePath=path.join(root,'coding-lease.json');
|
|
35
|
+
await writeFile(policyPath,JSON.stringify({
|
|
36
|
+
schema:'deadbyte.coding-policy.v1',enabled:true,lease_file:leasePath,evidence_dir:path.join(root,'evidence'),
|
|
37
|
+
roots:{project:{path:project,read:true,write:true,exec:true,deny_paths:['.git','node_modules']}},
|
|
38
|
+
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}},
|
|
39
|
+
max_read_bytes:524288,max_write_bytes:2097152
|
|
40
|
+
},null,2),'utf8');
|
|
41
|
+
const policy=await loadCodingPolicy(policyPath);
|
|
42
|
+
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');
|
|
43
|
+
const semanticConfigPath=path.join(root,'semantic-lsp.json');
|
|
44
|
+
await writeFile(semanticConfigPath,JSON.stringify({schema:'deadbyte.semantic-lsp-config.v1',servers:[{
|
|
45
|
+
id:'fixture-lsp',extensions:['.foo'],executable_path:process.execPath,executable_sha256:await sha256File(process.execPath),
|
|
46
|
+
args:[lspFixture],dependencies:[{path:lspFixture,expected_sha256:await sha256File(lspFixture)}],required:true
|
|
47
|
+
}]},null,2),'utf8');
|
|
48
|
+
const client=new Client({name:'deadbyte-r35-semantic-config',version:'0.9.0'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
|
|
49
|
+
const transport=new StdioClientTransport({command:process.execPath,args:[cliPath,'mcp'],cwd:repoRoot,env:{...getDefaultEnvironment(),DEADBYTE_SIGNING_KEY:keys.privateKeyPath,DEADBYTE_VERIFY_KEY:keys.publicKeyPath,DEADBYTE_CODING_RUNTIME:'1',DEADBYTE_CODING_POLICY:policyPath,DEADBYTE_SEMANTIC_LSP_CONFIG:semanticConfigPath,DEADBYTE_SEMANTIC_LSP_CONFIG_SHA256:await sha256File(semanticConfigPath)},stderr:'pipe'});
|
|
50
|
+
return {root,client,transport};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
test('MCP server loads pinned external semantic backends from explicit config without changing public tool names',async()=>{
|
|
54
|
+
const f=await fixture();
|
|
55
|
+
try{
|
|
56
|
+
await f.client.connect(f.transport);
|
|
57
|
+
const listed=await f.client.listTools();
|
|
58
|
+
assert.ok(listed.tools.some(tool=>tool.name==='coding_symbol_outline'));
|
|
59
|
+
const outline=structured(await f.client.callTool({name:'coding_symbol_outline',arguments:{root_id:'project',path:'main.foo',max_symbols:10}}),'semantic-outline');
|
|
60
|
+
assert.equal(outline.engine,'fixture-lsp');
|
|
61
|
+
assert.equal(outline.symbols[0].name,'alpha');
|
|
62
|
+
} finally {
|
|
63
|
+
await f.client.close().catch(()=>{});
|
|
64
|
+
await rm(f.root,{recursive:true,force:true}).catch(()=>{});
|
|
65
|
+
}
|
|
66
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { canonicalSchemaHash, snapshotToolSurface, snapshotToolsListResult, diffToolSurface } from '../src/tool-surface-ledger.mjs';
|
|
4
|
+
|
|
5
|
+
const alphaA={
|
|
6
|
+
name:'alpha',
|
|
7
|
+
inputSchema:{type:'object',properties:{x:{type:'string'},n:{type:'integer'}},required:['x'],additionalProperties:false},
|
|
8
|
+
outputSchema:{type:'object',properties:{ok:{type:'boolean'}},required:['ok'],additionalProperties:false}
|
|
9
|
+
};
|
|
10
|
+
const alphaReordered={
|
|
11
|
+
name:'alpha',
|
|
12
|
+
inputSchema:{additionalProperties:false,required:['x'],properties:{n:{type:'integer'},x:{type:'string'}},type:'object'},
|
|
13
|
+
outputSchema:{required:['ok'],properties:{ok:{type:'boolean'}},additionalProperties:false,type:'object'}
|
|
14
|
+
};
|
|
15
|
+
const beta={name:'beta',inputSchema:{type:'object',properties:{}},outputSchema:{type:'object',properties:{value:{type:'string'}}}};
|
|
16
|
+
|
|
17
|
+
test('schema hash is canonical across object key ordering and preserves array ordering',()=>{
|
|
18
|
+
assert.equal(canonicalSchemaHash(alphaA.inputSchema),canonicalSchemaHash(alphaReordered.inputSchema));
|
|
19
|
+
assert.notEqual(
|
|
20
|
+
canonicalSchemaHash({type:'string',enum:['a','b']}),
|
|
21
|
+
canonicalSchemaHash({type:'string',enum:['b','a']})
|
|
22
|
+
);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('tool surface snapshot is deterministic and rejects duplicate or non-JSON schema content',()=>{
|
|
26
|
+
const forward=snapshotToolSurface([alphaA,beta]);
|
|
27
|
+
const reverse=snapshotToolSurface([beta,alphaReordered]);
|
|
28
|
+
assert.equal(forward.schema,'deadbyte.tool-surface.v1');
|
|
29
|
+
assert.deepEqual(forward,reverse);
|
|
30
|
+
assert.deepEqual(forward.tools.map(tool=>tool.name),['alpha','beta']);
|
|
31
|
+
assert.match(forward.surface_sha256,/^[0-9a-f]{64}$/);
|
|
32
|
+
assert.throws(()=>snapshotToolSurface([alphaA,alphaReordered]),/duplicate tool/i);
|
|
33
|
+
assert.throws(()=>canonicalSchemaHash({type:'object',bad:undefined}),/JSON|unsupported|undefined/i);
|
|
34
|
+
assert.throws(()=>canonicalSchemaHash({type:'object',bad:()=>true}),/JSON|unsupported|function/i);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('surface diff classifies removals additions and schema changes without ordering noise',()=>{
|
|
38
|
+
const baseline=snapshotToolSurface([alphaA,beta]);
|
|
39
|
+
const changed=snapshotToolSurface([
|
|
40
|
+
{...alphaReordered,outputSchema:{type:'object',properties:{ok:{type:'boolean'},message:{type:'string'}},required:['ok'],additionalProperties:false}},
|
|
41
|
+
{name:'gamma',inputSchema:{type:'object'},outputSchema:{type:'object'}}
|
|
42
|
+
]);
|
|
43
|
+
const diff=diffToolSurface(baseline,changed);
|
|
44
|
+
assert.deepEqual(diff.unchanged,[]);
|
|
45
|
+
assert.deepEqual(diff.added,['gamma']);
|
|
46
|
+
assert.deepEqual(diff.removed,['beta']);
|
|
47
|
+
assert.deepEqual(diff.schema_changed,['alpha']);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('MCP tools/list result snapshots the exact client-visible schemas and rejects malformed tools',()=>{
|
|
51
|
+
const snapshot=snapshotToolsListResult({tools:[
|
|
52
|
+
{name:'beta',description:'ignored for compatibility identity',inputSchema:beta.inputSchema,outputSchema:beta.outputSchema},
|
|
53
|
+
{name:'alpha',inputSchema:alphaA.inputSchema,outputSchema:alphaA.outputSchema}
|
|
54
|
+
]});
|
|
55
|
+
assert.deepEqual(snapshot.tools.map(tool=>tool.name),['alpha','beta']);
|
|
56
|
+
assert.equal(snapshot.tools[0].input_sha256,canonicalSchemaHash(alphaA.inputSchema));
|
|
57
|
+
assert.throws(()=>snapshotToolsListResult({tools:[{name:'broken',inputSchema:{type:'object'}}]}),/outputSchema|output schema/i);
|
|
58
|
+
assert.throws(()=>snapshotToolsListResult({tools:'not-an-array'}),/tools\/list|tools.*array/i);
|
|
59
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { snapshotStdioServer } from '../scripts/tool-surface-snapshot.mjs';
|
|
6
|
+
|
|
7
|
+
const root=path.resolve(fileURLToPath(new URL('..',import.meta.url)));
|
|
8
|
+
const fixture=path.join(root,'test','fixtures','tool-surface-stdio-server.mjs');
|
|
9
|
+
|
|
10
|
+
test('stdio snapshot negotiates the real MCP server and hashes its client-visible tool schemas',async()=>{
|
|
11
|
+
const snapshot=await snapshotStdioServer({command:process.execPath,args:[fixture],cwd:root});
|
|
12
|
+
assert.equal(snapshot.schema,'deadbyte.tool-surface.v1');
|
|
13
|
+
assert.deepEqual(snapshot.tools.map(tool=>tool.name),['alpha']);
|
|
14
|
+
assert.match(snapshot.tools[0].input_sha256,/^[0-9a-f]{64}$/);
|
|
15
|
+
assert.match(snapshot.tools[0].output_sha256,/^[0-9a-f]{64}$/);
|
|
16
|
+
assert.match(snapshot.surface_sha256,/^[0-9a-f]{64}$/);
|
|
17
|
+
});
|
|
@@ -0,0 +1,77 @@
|
|
|
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 cliPath=path.join(repoRoot,'src','deadbyte-cli.mjs');
|
|
16
|
+
const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
17
|
+
const sha256File=async file=>sha256(await readFile(file));
|
|
18
|
+
|
|
19
|
+
function structured(value,label){
|
|
20
|
+
if(value.isError) throw new Error(`${label} failed: ${JSON.stringify(value.structuredContent??value.content)}`);
|
|
21
|
+
assert.ok(value.structuredContent&&typeof value.structuredContent==='object',`${label} missing structuredContent`);
|
|
22
|
+
return value.structuredContent;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async function fixture(){
|
|
26
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-tracer-'));
|
|
27
|
+
const project=path.join(root,'project');
|
|
28
|
+
const trust=path.join(root,'trust');
|
|
29
|
+
await mkdir(project); await mkdir(trust);
|
|
30
|
+
const keys=await generateTrustKeypair({privateKeyPath:path.join(trust,'private.pem'),publicKeyPath:path.join(trust,'public.pem')});
|
|
31
|
+
await writeFile(path.join(project,'app.mjs'),'export const value = 1;\n','utf8');
|
|
32
|
+
await writeFile(path.join(project,'verify.mjs'),"import { value } from './app.mjs';\nif(value!==2){console.error('expected value=2');process.exit(2)}\nprocess.stdout.write('TRACER_OK\\n');\n",'utf8');
|
|
33
|
+
const policyPath=path.join(root,'coding-policy.json');
|
|
34
|
+
const leasePath=path.join(root,'coding-lease.json');
|
|
35
|
+
await writeFile(policyPath,JSON.stringify({
|
|
36
|
+
schema:'deadbyte.coding-policy.v1',enabled:true,lease_file:leasePath,evidence_dir:path.join(root,'evidence'),
|
|
37
|
+
roots:{project:{path:project,read:true,write:true,exec:true,deny_paths:['.git','node_modules']}},
|
|
38
|
+
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}},
|
|
39
|
+
max_read_bytes:524288,max_write_bytes:2097152
|
|
40
|
+
},null,2),'utf8');
|
|
41
|
+
const policy=await loadCodingPolicy(policyPath);
|
|
42
|
+
await writeFile(leasePath,JSON.stringify({schema:'deadbyte.coding-lease.v1',policy_sha256:policy.policy_sha256,instance_nonce:'b'.repeat(64),root_ids:['project'],armed_at_utc:new Date().toISOString(),expires_at_utc:new Date(Date.now()+3600000).toISOString()}),'utf8');
|
|
43
|
+
const client=new Client({name:'deadbyte-tracer-bullet',version:'0.8.11'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
|
|
44
|
+
const transport=new StdioClientTransport({command:process.execPath,args:[cliPath,'mcp'],cwd:repoRoot,env:{...getDefaultEnvironment(),DEADBYTE_SIGNING_KEY:keys.privateKeyPath,DEADBYTE_VERIFY_KEY:keys.publicKeyPath,DEADBYTE_CODING_RUNTIME:'1',DEADBYTE_CODING_POLICY:policyPath},stderr:'pipe'});
|
|
45
|
+
return {root,project,client,transport};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
test('production tracer bullet negotiates MCP then reads, surgically edits, runs and verifies a real test',async()=>{
|
|
49
|
+
const f=await fixture();
|
|
50
|
+
try{
|
|
51
|
+
await f.client.connect(f.transport);
|
|
52
|
+
assert.equal(f.client.getNegotiatedProtocolVersion(),'2026-07-28');
|
|
53
|
+
const listed=await f.client.listTools();
|
|
54
|
+
const names=new Set(listed.tools.map(tool=>tool.name));
|
|
55
|
+
for(const name of ['coding_file_read','coding_text_replace','coding_command_run','coding_receipt_verify']) assert.ok(names.has(name),`missing ${name}`);
|
|
56
|
+
|
|
57
|
+
const before=structured(await f.client.callTool({name:'coding_file_read',arguments:{root_id:'project',path:'app.mjs',encoding:'utf8'}}),'read-before');
|
|
58
|
+
assert.equal(before.content,'export const value = 1;\n');
|
|
59
|
+
|
|
60
|
+
const edited=structured(await f.client.callTool({name:'coding_text_replace',arguments:{root_id:'project',path:'app.mjs',old_string:'value = 1',new_string:'value = 2',expected_sha256:before.sha256,expected_replacements:1}}),'edit');
|
|
61
|
+
assert.equal(edited.status,'committed');
|
|
62
|
+
const editReceipt=structured(await f.client.callTool({name:'coding_receipt_verify',arguments:{receipt_id:edited.receipt_id}}),'edit-receipt');
|
|
63
|
+
assert.equal(editReceipt.ok,true); assert.equal(editReceipt.signature_valid,true);
|
|
64
|
+
|
|
65
|
+
const scriptHash=await sha256File(path.join(f.project,'verify.mjs'));
|
|
66
|
+
const ran=structured(await f.client.callTool({name:'coding_command_run',arguments:{root_id:'project',command_id:'node_script',script_path:'verify.mjs',script_sha256:scriptHash,args:[],cwd:'.',timeout_ms:30000}}),'run-test');
|
|
67
|
+
assert.equal(ran.status,'passed'); assert.equal(ran.exit_code,0); assert.match(ran.stdout,/TRACER_OK/);
|
|
68
|
+
const runReceipt=structured(await f.client.callTool({name:'coding_receipt_verify',arguments:{receipt_id:ran.receipt_id}}),'run-receipt');
|
|
69
|
+
assert.equal(runReceipt.ok,true); assert.equal(runReceipt.signature_valid,true);
|
|
70
|
+
|
|
71
|
+
const after=structured(await f.client.callTool({name:'coding_file_read',arguments:{root_id:'project',path:'app.mjs',encoding:'utf8'}}),'read-after');
|
|
72
|
+
assert.equal(after.content,'export const value = 2;\n');
|
|
73
|
+
} finally {
|
|
74
|
+
await f.client.close().catch(()=>{});
|
|
75
|
+
await rm(f.root,{recursive:true,force:true}).catch(()=>{});
|
|
76
|
+
}
|
|
77
|
+
});
|