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