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
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import test from 'node:test';
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
|
-
import {
|
|
4
|
+
import { createHash } from 'node:crypto';
|
|
5
5
|
|
|
6
6
|
const root = new URL('../', import.meta.url);
|
|
7
7
|
const text = rel => readFile(new URL(rel, root), 'utf8');
|
|
8
8
|
|
|
9
|
-
test('
|
|
9
|
+
test('R35 successor release authority agrees on V0.9.0 / R35 identity', async () => {
|
|
10
10
|
const pkg = JSON.parse(await text('package.json'));
|
|
11
|
-
const [version, controller, gate, readme, architecture, controllerReadme, deferred, parity, closure, closureVerify] = await Promise.all([
|
|
11
|
+
const [version, controller, gate, readme, architecture, controllerReadme, deferred, parity, closure, closureVerify, windowsGate, semanticConfig] = await Promise.all([
|
|
12
12
|
text('src/version.mjs'),
|
|
13
13
|
text('controller/deadbyte-controller.ps1'),
|
|
14
14
|
text('scripts/gate-windows.ps1'),
|
|
@@ -16,20 +16,27 @@ test('R33 patch successor release authority agrees on V0.8.9 / R33 identity', as
|
|
|
16
16
|
text('docs/ARCHITECTURE.md'),
|
|
17
17
|
text('controller/README.TXT'),
|
|
18
18
|
text('scripts/deferred-slot-operation.mjs'),
|
|
19
|
-
text('src/remote-mcp-
|
|
19
|
+
text('src/remote-mcp-r34-parity-client.mjs'),
|
|
20
20
|
text('scripts/final-closure.mjs'),
|
|
21
|
-
text('scripts/final-closure-verify.mjs')
|
|
21
|
+
text('scripts/final-closure-verify.mjs'),
|
|
22
|
+
text('scripts/windows-gate-evidence.mjs'),
|
|
23
|
+
text('controller/deadbyte-semantic-lsp-config.json')
|
|
22
24
|
]);
|
|
23
|
-
assert.equal(pkg.version, '0.
|
|
24
|
-
assert.match(version, /DEADBYTE_VERSION = '0\.
|
|
25
|
-
assert.match(controller, /CONTROLLER V0\.
|
|
26
|
-
assert.match(gate, /DEADBYTE V0\.
|
|
27
|
-
assert.match(readme, /^DEADBYTE MCP V0\.
|
|
28
|
-
assert.match(architecture, /^# DEADBYTE MCP V0\.
|
|
29
|
-
assert.match(controllerReadme, /^DEADBYTE MCP V0\.
|
|
30
|
-
assert.match(controllerReadme, /
|
|
31
|
-
assert.match(deferred, /--expected-version','0\.
|
|
32
|
-
assert.match(parity, /version:'0\.
|
|
33
|
-
assert.match(closure, /version:'0\.
|
|
34
|
-
assert.match(closureVerify, /DEADBYTE V0\.
|
|
25
|
+
assert.equal(pkg.version, '0.9.0');
|
|
26
|
+
assert.match(version, /DEADBYTE_VERSION = '0\.9\.0'/);
|
|
27
|
+
assert.match(controller, /CONTROLLER V0\.9\.0 \/ R35/);
|
|
28
|
+
assert.match(gate, /DEADBYTE V0\.9\.0 \/ R35 WINDOWS BATCH GATE: PASS/);
|
|
29
|
+
assert.match(readme, /^DEADBYTE MCP V0\.9\.0 \/ R35 PRODUCTION BASELINE$/m);
|
|
30
|
+
assert.match(architecture, /^# DEADBYTE MCP V0\.9\.0 \/ R35 ARCHITECTURE$/m);
|
|
31
|
+
assert.match(controllerReadme, /^DEADBYTE MCP V0\.9\.0 \/ R35 CONTROLLER$/m);
|
|
32
|
+
assert.match(controllerReadme, /73-tool public catalog/);
|
|
33
|
+
assert.match(deferred, /--expected-version','0\.9\.0'/);
|
|
34
|
+
assert.match(parity, /version:'0\.9\.0'/);
|
|
35
|
+
assert.match(closure, /version:'0\.9\.0'/);
|
|
36
|
+
assert.match(closureVerify, /DEADBYTE V0\.9\.0 \/ R35 WINDOWS BATCH GATE: PASS/);
|
|
37
|
+
assert.match(windowsGate, /schema:'deadbyte\.r35-windows-gate\.v1'/);
|
|
38
|
+
assert.equal(createHash('sha256').update(Buffer.from(semanticConfig,'utf8')).digest('hex'), 'd274b099a298c1033fea8f1e8849751693bbc0448778d619400acb82d4f53a3b');
|
|
39
|
+
assert.match(deferred, /--semantic-lsp-config/);
|
|
40
|
+
assert.match(deferred, /--semantic-lsp-config-sha256/);
|
|
41
|
+
assert.match(deferred, /deadbyte-semantic-lsp-config\.json/);
|
|
35
42
|
});
|
|
@@ -66,10 +66,11 @@ test('R32 remote gate accepts observation only with machine plus coding configur
|
|
|
66
66
|
assert.match(source, /observation_runtime: observationRuntime/);
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
test('
|
|
69
|
+
test('R34 disarmed public gate requires the exact canonical 73-tool catalog', async () => {
|
|
70
70
|
const disarmedPath = fileURLToPath(new URL('../src/remote-mcp-r24-disarmed-smoke-client.mjs', import.meta.url));
|
|
71
71
|
const source = await readFile(disarmedPath, 'utf8');
|
|
72
|
-
assert.match(source, /
|
|
73
|
-
assert.match(source, /
|
|
74
|
-
assert.
|
|
72
|
+
assert.match(source, /R34_EXPECTED_TOOLS/);
|
|
73
|
+
assert.match(source, /JSON\.stringify\(names\).*JSON\.stringify\(R34_EXPECTED_TOOLS\)/s);
|
|
74
|
+
assert.match(source, /tool_count:R34_EXPECTED_TOOLS\.length/);
|
|
75
|
+
assert.doesNotMatch(source, /listed\.tools\.length !== 68/);
|
|
75
76
|
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { openRemoteResultJournal, parseRemoteResultCursor } from '../src/remote-result-journal.mjs';
|
|
7
|
+
|
|
8
|
+
const H=c=>c.repeat(64);
|
|
9
|
+
const session='a'.repeat(24);
|
|
10
|
+
const item=(requestId,payload,status='ok')=>({request_id:requestId,tool:'coding_tree',status,
|
|
11
|
+
observed_at_utc:'2026-09-17T00:00:00.000Z',payload_sha256:payload});
|
|
12
|
+
|
|
13
|
+
test('remote result journal is monotonic, restart-safe, and suppresses duplicate terminal results',async()=>{
|
|
14
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r35-remote-results-'));
|
|
15
|
+
const file=path.join(root,'journal.json');
|
|
16
|
+
try{
|
|
17
|
+
const first=await openRemoteResultJournal({filePath:file,sessionId:session,maxEntries:8});
|
|
18
|
+
const a=await first.recordTerminal(item('req-1',H('1')));
|
|
19
|
+
const duplicate=await first.recordTerminal(item('req-1',H('1')));
|
|
20
|
+
const b=await first.recordTerminal(item('req-2',H('2'),'error'));
|
|
21
|
+
assert.equal(a.event.seq,1);assert.equal(duplicate.duplicate,true);assert.equal(duplicate.event.seq,1);
|
|
22
|
+
assert.equal(b.event.seq,2);assert.equal(first.cursor(),'r1:'+session+':2');
|
|
23
|
+
|
|
24
|
+
const restarted=await openRemoteResultJournal({filePath:file,sessionId:session,maxEntries:8});
|
|
25
|
+
const c=await restarted.recordTerminal(item('req-3',H('3')));
|
|
26
|
+
assert.equal(c.event.seq,3);
|
|
27
|
+
const replay=await restarted.replayAfter('r1:'+session+':1',{limit:8});
|
|
28
|
+
assert.deepEqual(replay.events.map(event=>event.seq),[2,3]);
|
|
29
|
+
assert.equal(replay.next_cursor,'r1:'+session+':3');
|
|
30
|
+
}finally{await rm(root,{recursive:true,force:true});}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('bounded retention rejects stale cursor and never stores raw payload bytes',async()=>{
|
|
34
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r35-remote-retention-'));
|
|
35
|
+
const file=path.join(root,'journal.json');
|
|
36
|
+
try{
|
|
37
|
+
const journal=await openRemoteResultJournal({filePath:file,sessionId:session,maxEntries:2});
|
|
38
|
+
await journal.recordTerminal(item('req-1',H('1')));
|
|
39
|
+
await journal.recordTerminal(item('req-2',H('2')));
|
|
40
|
+
await journal.recordTerminal(item('req-3',H('3')));
|
|
41
|
+
await assert.rejects(journal.replayAfter('r1:'+session+':0',{limit:8}),/cursor_outside_retention/);
|
|
42
|
+
const text=await readFile(file,'utf8');
|
|
43
|
+
assert.doesNotMatch(text,/stdout|stderr|payload\s*:/i);
|
|
44
|
+
const stored=JSON.parse(text);
|
|
45
|
+
assert.deepEqual(stored.events.map(event=>event.seq),[2,3]);
|
|
46
|
+
assert.equal(stored.next_seq,4);
|
|
47
|
+
}finally{await rm(root,{recursive:true,force:true});}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('cursor parser rejects foreign sessions and malformed cursors',async()=>{
|
|
51
|
+
assert.deepEqual(parseRemoteResultCursor('r1:'+session+':42'),{session_id:session,seq:42});
|
|
52
|
+
assert.throws(()=>parseRemoteResultCursor('bad'),/cursor/i);
|
|
53
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r35-remote-cursor-'));
|
|
54
|
+
try{
|
|
55
|
+
const journal=await openRemoteResultJournal({filePath:path.join(root,'j.json'),sessionId:session,maxEntries:8});
|
|
56
|
+
await assert.rejects(journal.replayAfter('r1:'+'b'.repeat(24)+':0',{limit:8}),/cursor session mismatch/);
|
|
57
|
+
}finally{await rm(root,{recursive:true,force:true});}
|
|
58
|
+
});
|
|
@@ -18,7 +18,7 @@ async function fixture({failCommand=''}={}){
|
|
|
18
18
|
const trace=path.join(dir,'trace.txt');
|
|
19
19
|
await mkdir(bin,{recursive:true});
|
|
20
20
|
const launcher=path.join(bin,'DEADBYTE-MCP.ps1');
|
|
21
|
-
const ps1=`param([string]$Command)\
|
|
21
|
+
const ps1=`param([string]$Command)\n$ErrorActionPreference='Stop'\nfor($i=0;$i -lt 20;$i++){ try { [IO.File]::AppendAllText($env:DEADBYTE_REMOTE_TEST_TRACE,(\"$Command\" + [Environment]::NewLine),[Text.Encoding]::UTF8); break } catch { if($i -eq 19){ throw }; Start-Sleep -Milliseconds 10 } }\nif ($env:DEADBYTE_REMOTE_TEST_FAIL -and $Command -eq $env:DEADBYTE_REMOTE_TEST_FAIL) { Write-Error \"forced $Command failure\"; exit 9 }\nswitch ($Command) {\n 'start' { Write-Host 'DEADBYTE MCP = ONLINE' }\n 'processstatus' { Write-Host 'Process plane : ARMED [standing-grant]' }\n 'codingstatus' { Write-Host 'Coding plane : ARMED [standing-grant]' }\n 'autonomousstatus' { Write-Host 'Autonomous : ARMED [standing-grant]' }\n 'hoststatus' { Write-Host 'Host plane : ARMED [standing-grant]' }\n 'park' { Write-Host 'DEADBYTE MCP = PARKED' }\n default { Write-Host \"$Command OK\" }\n}\nexit 0\n`;
|
|
22
22
|
await writeFile(launcher,ps1,'utf8');
|
|
23
23
|
return {dir,state,trace,env:{...process.env,DEADBYTE_STATE_ROOT:state,DEADBYTE_REMOTE_TEST_TRACE:trace,DEADBYTE_REMOTE_TEST_FAIL:failCommand}};
|
|
24
24
|
}
|
|
@@ -34,7 +34,7 @@ async function traceCommands(file,{read=readFile,retryDelayMs=10,maxAttempts=20}
|
|
|
34
34
|
}
|
|
35
35
|
return [];
|
|
36
36
|
}
|
|
37
|
-
async function waitFor(file,predicate,{timeoutMs=
|
|
37
|
+
async function waitFor(file,predicate,{timeoutMs=12000}={}){
|
|
38
38
|
const deadline=Date.now()+timeoutMs;
|
|
39
39
|
while(Date.now()<deadline){
|
|
40
40
|
const commands=await traceCommands(file);
|
|
@@ -65,36 +65,151 @@ async function collect(child){
|
|
|
65
65
|
|
|
66
66
|
const winTest=isWindows?test:test.skip;
|
|
67
67
|
|
|
68
|
-
winTest('bare remote
|
|
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.
|
|
74
|
+
const ready=await waitFor(fx.trace,commands=>commands.slice(0,9).join(',')==='start,armprocess,armcoding,armautonomous,armhost,processstatus,codingstatus,autonomousstatus,hoststatus');
|
|
75
75
|
assert.deepEqual(ready.slice(0,9),[
|
|
76
76
|
'start','armprocess','armcoding','armautonomous','armhost',
|
|
77
77
|
'processstatus','codingstatus','autonomousstatus','hoststatus'
|
|
78
78
|
]);
|
|
79
79
|
assert.equal(child.exitCode,null,'remote session must remain foreground after becoming ready');
|
|
80
80
|
const tailDeadline=Date.now()+3000;
|
|
81
|
-
while(Date.now()<tailDeadline
|
|
82
|
-
assert.match(output.stdout
|
|
81
|
+
while(Date.now()<tailDeadline&&!/\[LOG\] Live tool results/.test(output.stdout)) await sleep(50);
|
|
82
|
+
assert.match(output.stdout,/\[OK\] ONLINE/);
|
|
83
|
+
assert.match(output.stdout,/\[OK\] Authority ARMED: process, coding, autonomous, host/);
|
|
84
|
+
assert.match(output.stdout,/\[LOG\] Live tool results\. Ctrl\+C disconnects and revokes authority\./);
|
|
85
|
+
assert.doesNotMatch(output.stdout,/Process plane\s*:/);
|
|
86
|
+
assert.doesNotMatch(output.stdout,/Coding plane\s*:/);
|
|
83
87
|
const auditDir=path.join(fx.state,'audit');
|
|
88
|
+
const runtimeLogs=path.join(fx.state,'runtime','logs');
|
|
84
89
|
await mkdir(auditDir,{recursive:true});
|
|
85
|
-
await
|
|
90
|
+
await mkdir(runtimeLogs,{recursive:true});
|
|
91
|
+
const marker=JSON.parse(await readFile(path.join(fx.state,'runtime','remote-session.json'),'utf8'));
|
|
92
|
+
assert.match(String(marker.result_session_id||''),/^[0-9a-f]{24}$/);
|
|
93
|
+
const auditEvents=[
|
|
94
|
+
{seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'abcdef1234567890'},
|
|
95
|
+
{seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false}},
|
|
96
|
+
{seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false}},
|
|
97
|
+
{seq:3,event_type:'tool.request',tool:'coding_file_read',request_id:'fedcba9876543210'},
|
|
98
|
+
{seq:4,event_type:'tool.result',tool:'coding_file_read',request_id:'fedcba9876543210',outcome:{is_error:true}}
|
|
99
|
+
];
|
|
100
|
+
await writeFile(path.join(auditDir,'segment-00000001.jsonl'),`${auditEvents.map(event=>JSON.stringify(event)).join('\n')}\n`,'utf8');
|
|
101
|
+
await writeFile(path.join(runtimeLogs,'bridge.stdout.log'),[
|
|
102
|
+
'[TOOL IN ] 2026-09-16T00:00:00.000Z #000001 coding_tree {}',
|
|
103
|
+
'[TOOL OUT] 2026-09-16T00:00:00.001Z #000001 coding_tree {"is_error":false}',
|
|
104
|
+
'[TOOL OUT] 2026-09-16T00:00:00.002Z #000002 coding_file_read {"is_error":true}'
|
|
105
|
+
].join('\n')+'\n','utf8');
|
|
86
106
|
const logDeadline=Date.now()+3000;
|
|
87
|
-
while(Date.now()<logDeadline&&!/\[
|
|
88
|
-
assert.match(output.stdout,/\[
|
|
107
|
+
while(Date.now()<logDeadline&&!/\[ERR\] coding_file_read/.test(output.stdout)) await sleep(50);
|
|
108
|
+
assert.match(output.stdout,/\[OK\] coding_tree \[cursor r1:[0-9a-f]{24}:1\]/);
|
|
109
|
+
assert.match(output.stdout,/\[ERR\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/);
|
|
110
|
+
assert.equal((output.stdout.match(/\[OK\] coding_tree/g)||[]).length,1,'duplicate terminal result must print once');
|
|
111
|
+
const resultJournal=JSON.parse(await readFile(path.join(fx.state,'runtime','remote-results',`${marker.result_session_id}.json`),'utf8'));
|
|
112
|
+
assert.deepEqual(resultJournal.events.map(event=>event.seq),[1,2]);
|
|
113
|
+
assert.equal(resultJournal.events[0].request_id,'abcdef1234567890');
|
|
114
|
+
assert.ok(resultJournal.events.every(event=>/^[0-9a-f]{64}$/.test(event.payload_sha256)));
|
|
115
|
+
assert.doesNotMatch(JSON.stringify(resultJournal),/TOOL IN|TOOL OUT|stdout_excerpt|stderr_excerpt/);
|
|
116
|
+
assert.doesNotMatch(output.stdout,/abcdef12|fedcba98/);
|
|
117
|
+
assert.doesNotMatch(output.stdout,/tool\.request/);
|
|
118
|
+
assert.doesNotMatch(output.stdout,/BRIDGE\.STDOUT/);
|
|
119
|
+
assert.doesNotMatch(output.stdout,/\[TOOL IN \]|\[TOOL OUT\]/);
|
|
120
|
+
assert.doesNotMatch(output.stdout,/payload bytes=/);
|
|
89
121
|
child.stdin.end();
|
|
90
122
|
const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
|
|
91
123
|
assert.equal(ended.timeout,undefined,'remote session did not exit after foreground input closed');
|
|
92
124
|
const commands=await traceCommands(fx.trace);
|
|
93
125
|
assert.deepEqual(commands.slice(-5),['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park']);
|
|
94
|
-
assert.match(output.stdout
|
|
95
|
-
assert.match(output.stdout,/Live
|
|
96
|
-
|
|
97
|
-
|
|
126
|
+
assert.match(output.stdout,/^DEADBYTE MCP$/m);
|
|
127
|
+
assert.match(output.stdout,/Live tool results/i);
|
|
128
|
+
assert.doesNotMatch(output.stdout,/disarmautonomous OK|disarmcoding OK|disarmprocess OK|disarmhost OK|DEADBYTE MCP = PARKED/);
|
|
129
|
+
const withoutApprovedEmoji=output.stdout.replace(/[📜📥📤✅❌⚠♻🛡]/gu,'');
|
|
130
|
+
assert.doesNotMatch(withoutApprovedEmoji,/\p{Extended_Pictographic}/u,'human live stream may use only the approved semantic emoji set');
|
|
131
|
+
}finally{
|
|
132
|
+
if(child?.exitCode===null) child.kill();
|
|
133
|
+
await rm(fx.dir,{recursive:true,force:true});
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
winTest('remote --resume replays only terminal results after the cursor before starting a new live session',async()=>{
|
|
138
|
+
const fx=await fixture();
|
|
139
|
+
let first=null,second=null;
|
|
140
|
+
try{
|
|
141
|
+
first=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
|
|
142
|
+
const firstOutput=await collect(first);
|
|
143
|
+
await waitFor(fx.trace,commands=>commands.includes('hoststatus'));
|
|
144
|
+
const liveDeadline=Date.now()+3000;
|
|
145
|
+
while(Date.now()<liveDeadline&&!/\[LOG\] Live tool results/.test(firstOutput.stdout)) await sleep(50);
|
|
146
|
+
const auditDir=path.join(fx.state,'audit');await mkdir(auditDir,{recursive:true});
|
|
147
|
+
const auditFile=path.join(auditDir,'segment-00000001.jsonl');
|
|
148
|
+
await writeFile(auditFile,JSON.stringify({seq:1,event_type:'tool.result',tool:'coding_tree',request_id:'resume-request-1',outcome:{is_error:false}})+'\n','utf8');
|
|
149
|
+
let deadline=Date.now()+3000;
|
|
150
|
+
while(Date.now()<deadline&&!/coding_tree \[cursor r1:[0-9a-f]{24}:1\]/.test(firstOutput.stdout)) await sleep(50);
|
|
151
|
+
const cursor1=firstOutput.stdout.match(/coding_tree \[cursor (r1:[0-9a-f]{24}:1)\]/)?.[1];
|
|
152
|
+
assert.ok(cursor1,'first result cursor missing');
|
|
153
|
+
await writeFile(auditFile,JSON.stringify({seq:2,event_type:'tool.result',tool:'coding_file_read',request_id:'resume-request-2',outcome:{is_error:false}})+'\n',{encoding:'utf8',flag:'a'});
|
|
154
|
+
deadline=Date.now()+3000;
|
|
155
|
+
while(Date.now()<deadline&&!/coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/.test(firstOutput.stdout)) await sleep(50);
|
|
156
|
+
first.stdin.end();
|
|
157
|
+
const firstEnded=await Promise.race([firstOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
|
|
158
|
+
assert.equal(firstEnded.timeout,undefined);
|
|
159
|
+
|
|
160
|
+
second=spawn(process.execPath,[cliPath,'remote','--resume',cursor1],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
|
|
161
|
+
const secondOutput=await collect(second);
|
|
162
|
+
deadline=Date.now()+5000;
|
|
163
|
+
while(Date.now()<deadline&&(!/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/.test(secondOutput.stdout)||
|
|
164
|
+
!/\[LOG\] Live tool results/.test(secondOutput.stdout))) await sleep(50);
|
|
165
|
+
assert.match(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/);
|
|
166
|
+
assert.doesNotMatch(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_tree/);
|
|
167
|
+
const replayIndex=secondOutput.stdout.indexOf('[REPLAY]');
|
|
168
|
+
const liveIndex=secondOutput.stdout.indexOf('[LOG] Live tool results');
|
|
169
|
+
assert.ok(replayIndex>=0&&liveIndex>replayIndex,'resume replay must happen before new live tail');
|
|
170
|
+
second.stdin.end();
|
|
171
|
+
const secondEnded=await Promise.race([secondOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
|
|
172
|
+
assert.equal(secondEnded.timeout,undefined);
|
|
173
|
+
assert.equal(secondEnded.code,0,secondOutput.stderr);
|
|
174
|
+
}finally{
|
|
175
|
+
if(first?.exitCode===null) first.kill();if(second?.exitCode===null) second.kill();
|
|
176
|
+
await rm(fx.dir,{recursive:true,force:true});
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
winTest('remote --verbose preserves detailed audit and bridge log streaming for debugging',async()=>{
|
|
181
|
+
const fx=await fixture();
|
|
182
|
+
let child=null;
|
|
183
|
+
try{
|
|
184
|
+
child=spawn(process.execPath,[cliPath,'remote','--verbose'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
|
|
185
|
+
const output=await collect(child);
|
|
186
|
+
const ready=await waitFor(fx.trace,commands=>commands.slice(0,9).join(',')==='start,armprocess,armcoding,armautonomous,armhost,processstatus,codingstatus,autonomousstatus,hoststatus');
|
|
187
|
+
assert.equal(ready.length>=9,true);
|
|
188
|
+
const liveDeadline=Date.now()+3000;
|
|
189
|
+
while(Date.now()<liveDeadline&&!/Live logs active/.test(output.stdout)) await sleep(50);
|
|
190
|
+
assert.match(output.stdout,/Live logs active/);
|
|
191
|
+
const auditDir=path.join(fx.state,'audit');
|
|
192
|
+
const runtimeLogs=path.join(fx.state,'runtime','logs');
|
|
193
|
+
await mkdir(auditDir,{recursive:true});
|
|
194
|
+
await mkdir(runtimeLogs,{recursive:true});
|
|
195
|
+
await writeFile(path.join(auditDir,'segment-00000001.jsonl'),[
|
|
196
|
+
JSON.stringify({seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'abcdef1234567890'}),
|
|
197
|
+
JSON.stringify({seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false}})
|
|
198
|
+
].join('\n')+'\n','utf8');
|
|
199
|
+
await writeFile(path.join(runtimeLogs,'bridge.stdout.log'),[
|
|
200
|
+
'[TOOL IN ] 2026-09-16T00:00:00.000Z #000001 coding_tree {}',
|
|
201
|
+
'[TOOL OUT] 2026-09-16T00:00:00.001Z #000001 coding_tree {"is_error":false}'
|
|
202
|
+
].join('\n')+'\n','utf8');
|
|
203
|
+
const deadline=Date.now()+3000;
|
|
204
|
+
while(Date.now()<deadline&&!/\[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_tree/.test(output.stdout)) await sleep(50);
|
|
205
|
+
assert.match(output.stdout,/\[AUDIT #1\] tool\.request coding_tree abcdef12/);
|
|
206
|
+
assert.match(output.stdout,/\[AUDIT #2\] tool\.result coding_tree abcdef12/);
|
|
207
|
+
assert.match(output.stdout,/\[BRIDGE\.STDOUT\] \[TOOL IN \].*coding_tree/);
|
|
208
|
+
assert.match(output.stdout,/\[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_tree/);
|
|
209
|
+
child.stdin.end();
|
|
210
|
+
const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
|
|
211
|
+
assert.equal(ended.timeout,undefined,'verbose remote session did not exit after input closed');
|
|
212
|
+
assert.equal(ended.code,0,output.stderr);
|
|
98
213
|
}finally{
|
|
99
214
|
if(child?.exitCode===null) child.kill();
|
|
100
215
|
await rm(fx.dir,{recursive:true,force:true});
|
|
@@ -105,9 +220,9 @@ winTest('detached guardian revokes authority, parks, and removes the session mar
|
|
|
105
220
|
const fx=await fixture();
|
|
106
221
|
let child=null;
|
|
107
222
|
try{
|
|
108
|
-
child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['
|
|
223
|
+
child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
|
|
109
224
|
const output=await collect(child);
|
|
110
|
-
const ready=await waitFor(fx.trace,commands=>commands.
|
|
225
|
+
const ready=await waitFor(fx.trace,commands=>commands.slice(0,9).join(',')==='start,armprocess,armcoding,armautonomous,armhost,processstatus,codingstatus,autonomousstatus,hoststatus');
|
|
111
226
|
assert.deepEqual(ready.slice(0,9),[
|
|
112
227
|
'start','armprocess','armcoding','armautonomous','armhost',
|
|
113
228
|
'processstatus','codingstatus','autonomousstatus','hoststatus'
|
|
@@ -170,6 +285,7 @@ winTest('bare remote recovers a stale crashed session before arming a new one',a
|
|
|
170
285
|
const ready=await waitFor(fx.trace,commands=>commands.includes('hoststatus'));
|
|
171
286
|
assert.deepEqual(ready.slice(0,5),['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park']);
|
|
172
287
|
assert.equal(ready[5],'start');
|
|
288
|
+
assert.match(output.stdout,/♻️ \[RECOVERY\] Stale remote session pid=2147483000; revoking authority before restart\./);
|
|
173
289
|
child.stdin.end();
|
|
174
290
|
const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
|
|
175
291
|
assert.equal(ended.timeout,undefined);
|
|
@@ -180,6 +296,25 @@ winTest('bare remote recovers a stale crashed session before arming a new one',a
|
|
|
180
296
|
}
|
|
181
297
|
});
|
|
182
298
|
|
|
299
|
+
winTest('remote warning lines use the approved warning emoji without changing the warning token',async()=>{
|
|
300
|
+
const fx=await fixture();
|
|
301
|
+
let child=null;
|
|
302
|
+
try{
|
|
303
|
+
child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
|
|
304
|
+
const output=await collect(child);
|
|
305
|
+
await waitFor(fx.trace,commands=>commands.includes('hoststatus'));
|
|
306
|
+
const markerPath=path.join(fx.state,'runtime','remote-session.json');
|
|
307
|
+
await writeFile(markerPath,'{invalid-json\n','utf8');
|
|
308
|
+
child.stdin.end();
|
|
309
|
+
const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
|
|
310
|
+
assert.equal(ended.timeout,undefined,'remote session did not exit after warning fixture');
|
|
311
|
+
assert.match(output.stderr,/⚠️ \[WARN\] remote session marker cleanup:/);
|
|
312
|
+
}finally{
|
|
313
|
+
if(child?.exitCode===null) child.kill();
|
|
314
|
+
await rm(fx.dir,{recursive:true,force:true});
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
183
318
|
winTest('bare remote refuses a second live foreground session without touching authority',async()=>{
|
|
184
319
|
const fx=await fixture();
|
|
185
320
|
let child=null;
|
|
@@ -206,6 +206,40 @@ test('R31 slot-update CLI binds process-policy bootstrap and machine-FS enable e
|
|
|
206
206
|
assert.equal(parsed.enableMachineFs,true);
|
|
207
207
|
});
|
|
208
208
|
|
|
209
|
+
test('R35 slot-update CLI binds semantic LSP config as one exact path plus SHA-256 pair', () => {
|
|
210
|
+
const base=['--stage','stage','--development-root','dev','--expected-version','0.9.0','--expected-manifest',hex('a')];
|
|
211
|
+
assert.throws(() => parseUpdateArgs([...base,'--semantic-lsp-config','C:/candidate/semantic.json']), /semantic LSP config.*pair/i);
|
|
212
|
+
assert.throws(() => parseUpdateArgs([...base,'--semantic-lsp-config-sha256',hex('b')]), /semantic LSP config.*pair/i);
|
|
213
|
+
const parsed=parseUpdateArgs([...base,'--semantic-lsp-config','C:/candidate/semantic.json','--semantic-lsp-config-sha256',hex('b')]);
|
|
214
|
+
assert.equal(parsed.semanticLspBootstrap.path,path.resolve('C:/candidate/semantic.json'));
|
|
215
|
+
assert.equal(parsed.semanticLspBootstrap.sha256,hex('b'));
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test('R35 semantic LSP bootstrap accepts only exact pinned semantic config bytes', async () => {
|
|
219
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r35-semantic-bootstrap-'));
|
|
220
|
+
const file=path.join(root,'semantic.json');
|
|
221
|
+
const config={schema:'deadbyte.semantic-lsp-config.v1',servers:[]};
|
|
222
|
+
const bytes=Buffer.from(`${JSON.stringify(config)}\n`,'utf8');
|
|
223
|
+
await writeFile(file,bytes);
|
|
224
|
+
assert.equal(typeof runtimeUpdate.prepareSemanticLspConfigBootstrap,'function');
|
|
225
|
+
const accepted=await runtimeUpdate.prepareSemanticLspConfigBootstrap({path:file,sha256:sha(bytes)});
|
|
226
|
+
assert.equal(accepted.path,path.resolve(file));
|
|
227
|
+
assert.equal(accepted.sha256,sha(bytes));
|
|
228
|
+
await assert.rejects(runtimeUpdate.prepareSemanticLspConfigBootstrap({path:file,sha256:hex('f')}),/semantic LSP config.*SHA-256 mismatch/i);
|
|
229
|
+
const bad=path.join(root,'bad.json');
|
|
230
|
+
const badBytes=Buffer.from(`${JSON.stringify({schema:'wrong',servers:[]})}\n`,'utf8');
|
|
231
|
+
await writeFile(bad,badBytes);
|
|
232
|
+
await assert.rejects(runtimeUpdate.prepareSemanticLspConfigBootstrap({path:bad,sha256:sha(badBytes)}),/semantic LSP config schema/i);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
test('R35 updater threads pinned semantic LSP config into successor generation', async () => {
|
|
236
|
+
const source=await readFile(new URL('../src/runtime-update.mjs',import.meta.url),'utf8');
|
|
237
|
+
assert.match(source,/prepareSemanticLspConfigBootstrap\(semanticLspBootstrap\)/);
|
|
238
|
+
assert.match(source,/SemanticLspConfigFile=semanticBootstrap\.path/);
|
|
239
|
+
assert.match(source,/SemanticLspConfigSha256=semanticBootstrap\.sha256/);
|
|
240
|
+
assert.match(source,/semanticLspBootstrap:args\.semanticLspBootstrap/);
|
|
241
|
+
});
|
|
242
|
+
|
|
209
243
|
test('R32 slot-update CLI enables observation only by explicit flag', () => {
|
|
210
244
|
const base=['--stage','stage','--development-root','dev','--expected-version','0.8.6','--expected-manifest',hex('a')];
|
|
211
245
|
const plain=parseUpdateArgs(base);
|
|
@@ -215,6 +249,35 @@ test('R32 slot-update CLI enables observation only by explicit flag', () => {
|
|
|
215
249
|
assert.throws(() => parseUpdateArgs([...base,'--enable-observation','--enable-observation']),/duplicate self-update argument/i);
|
|
216
250
|
});
|
|
217
251
|
|
|
252
|
+
test('R34 slot-update CLI enables the out-of-band supervisor only by explicit flag', () => {
|
|
253
|
+
const base=['--stage','stage','--development-root','dev','--expected-version','0.8.11','--expected-manifest',hex('a')];
|
|
254
|
+
const plain=parseUpdateArgs(base);
|
|
255
|
+
assert.equal(plain.enableAutonomousSupervisor,false);
|
|
256
|
+
const enabled=parseUpdateArgs([...base,'--enable-autonomous-supervisor']);
|
|
257
|
+
assert.equal(enabled.enableAutonomousSupervisor,true);
|
|
258
|
+
assert.throws(() => parseUpdateArgs([...base,'--enable-autonomous-supervisor','--enable-autonomous-supervisor']),/duplicate self-update argument/i);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
test('R34 supervisor bootstrap derives exact release-bound script identity from trusted Bridge executable', async () => {
|
|
262
|
+
assert.equal(typeof runtimeUpdate.prepareAutonomousSupervisorSpec,'function');
|
|
263
|
+
const base=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r34-supervisor-bootstrap-'));
|
|
264
|
+
const release=path.join(base,'release'),src=path.join(release,'src'); await mkdir(src,{recursive:true});
|
|
265
|
+
const script=Buffer.from('console.log("supervisor-r34")\n','utf8');
|
|
266
|
+
await writeFile(path.join(src,'autonomous-supervisor-host.mjs'),script);
|
|
267
|
+
const nodeHash=sha(await readFile(process.execPath));
|
|
268
|
+
const config={AutonomousRuntimeEnabled:true,AutonomousSupervisorEnabled:false,
|
|
269
|
+
Bridge:{FilePath:process.execPath,FileSha256:nodeHash}};
|
|
270
|
+
const bound=await runtimeUpdate.prepareAutonomousSupervisorSpec(config,{releaseRoot:release,enable:true});
|
|
271
|
+
assert.equal(bound.AutonomousSupervisorEnabled,true);
|
|
272
|
+
assert.deepEqual(bound.Supervisor,{
|
|
273
|
+
FilePath:process.execPath,FileSha256:nodeHash,Arguments:'src\\autonomous-supervisor-host.mjs',
|
|
274
|
+
WorkingDirectory:path.resolve(release),ScriptPath:path.join(path.resolve(release),'src','autonomous-supervisor-host.mjs'),ScriptSha256:sha(script)
|
|
275
|
+
});
|
|
276
|
+
const untouched=await runtimeUpdate.prepareAutonomousSupervisorSpec(config,{releaseRoot:release,enable:false});
|
|
277
|
+
assert.equal(untouched.AutonomousSupervisorEnabled,false);
|
|
278
|
+
assert.equal(untouched.Supervisor,undefined);
|
|
279
|
+
});
|
|
280
|
+
|
|
218
281
|
test('R31 process-policy bootstrap accepts only an exact pinned enabled process policy', async () => {
|
|
219
282
|
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r31-process-bootstrap-'));
|
|
220
283
|
const file=path.join(root,'process-policy.json');
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createSemanticBackendRegistry } from '../src/semantic-backend-registry.mjs';
|
|
4
|
+
|
|
5
|
+
const backend=(id,extensions)=>({id,extensions:new Set(extensions),outline(){},definition(){},references(){},replaceSymbol(){},diagnostics(){}});
|
|
6
|
+
|
|
7
|
+
test('semantic backend registry resolves normalized extensions and exposes stable languages',()=>{
|
|
8
|
+
const ts=backend('typescript',['.ts','.tsx']);
|
|
9
|
+
const py=backend('python',['.py']);
|
|
10
|
+
const registry=createSemanticBackendRegistry({backends:[py,ts]});
|
|
11
|
+
assert.equal(registry.backendForPath('SRC/MAIN.TS'),ts);
|
|
12
|
+
assert.equal(registry.backendForPath('pkg/mod.py'),py);
|
|
13
|
+
assert.deepEqual(registry.languages(),[
|
|
14
|
+
{id:'python',extensions:['.py']},
|
|
15
|
+
{id:'typescript',extensions:['.ts','.tsx']}
|
|
16
|
+
]);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('semantic backend registry fails closed for unsupported languages',()=>{
|
|
20
|
+
const registry=createSemanticBackendRegistry({backends:[backend('typescript',['.ts'])]});
|
|
21
|
+
assert.throws(()=>registry.backendForPath('main.rs'),/unsupported semantic language: \.rs/i);
|
|
22
|
+
assert.throws(()=>registry.backendForPath('README'),/unsupported semantic language: <none>/i);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('semantic backend registry rejects duplicate ids, extension ownership, and incomplete backends',()=>{
|
|
26
|
+
assert.throws(()=>createSemanticBackendRegistry({backends:[backend('a',['.x']),backend('a',['.y'])]}),/duplicate semantic backend id/i);
|
|
27
|
+
assert.throws(()=>createSemanticBackendRegistry({backends:[backend('a',['.x']),backend('b',['.X'])]}),/semantic extension.*already owned/i);
|
|
28
|
+
assert.throws(()=>createSemanticBackendRegistry({backends:[{id:'bad',extensions:new Set(['.x'])}]}),/missing method.*outline/i);
|
|
29
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
|
+
import { Client } from '@modelcontextprotocol/client';
|
|
9
|
+
import { StdioClientTransport, getDefaultEnvironment } from '@modelcontextprotocol/client/stdio';
|
|
10
|
+
import { generateTrustKeypair } from '../src/trust.mjs';
|
|
11
|
+
import { loadCodingPolicy } from '../src/coding-plane.mjs';
|
|
12
|
+
|
|
13
|
+
const here=path.dirname(fileURLToPath(import.meta.url));
|
|
14
|
+
const repoRoot=path.resolve(here,'..');
|
|
15
|
+
const serverPath=path.join(repoRoot,'src','mcp-server.mjs');
|
|
16
|
+
const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
17
|
+
const sha256File=async file=>sha256(await readFile(file));
|
|
18
|
+
function structured(value,label){if(value.isError)throw new Error(`${label}: ${JSON.stringify(value.structuredContent??value.content)}`);return value.structuredContent;}
|
|
19
|
+
|
|
20
|
+
async function fixture(){
|
|
21
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-semantic-'));
|
|
22
|
+
const project=path.join(root,'project'); const trust=path.join(root,'trust');
|
|
23
|
+
await mkdir(project); await mkdir(trust);
|
|
24
|
+
const keys=await generateTrustKeypair({privateKeyPath:path.join(trust,'private.pem'),publicKeyPath:path.join(trust,'public.pem')});
|
|
25
|
+
const math=`export function add(a: number, b: number) {\n return a + b;\n}\n\nexport function twice(x: number) {\n return add(x, x);\n}\n`;
|
|
26
|
+
const main=`import { add } from './math.js';\nexport const total = add(2, 3);\n`;
|
|
27
|
+
await writeFile(path.join(project,'math.ts'),math,'utf8'); await writeFile(path.join(project,'main.ts'),main,'utf8');
|
|
28
|
+
await writeFile(path.join(project,'tsconfig.json'),JSON.stringify({compilerOptions:{target:'ES2022',module:'NodeNext',moduleResolution:'NodeNext',strict:true},include:['*.ts']},null,2),'utf8');
|
|
29
|
+
const policyPath=path.join(root,'coding-policy.json'); const leasePath=path.join(root,'coding-lease.json');
|
|
30
|
+
await writeFile(policyPath,JSON.stringify({schema:'deadbyte.coding-policy.v1',enabled:true,lease_file:leasePath,evidence_dir:path.join(root,'evidence'),roots:{project:{path:project,read:true,write:true,exec:true,deny_paths:['.git','node_modules']}},commands:{node_script:{kind:'script',executable:process.execPath,executable_sha256:await sha256File(process.execPath),root_ids:['project'],prefix_args:[],extensions:['.mjs','.js'],timeout_ms:30000,max_output_bytes:262144}},max_read_bytes:524288,max_write_bytes:2097152},null,2),'utf8');
|
|
31
|
+
const policy=await loadCodingPolicy(policyPath);
|
|
32
|
+
await writeFile(leasePath,JSON.stringify({schema:'deadbyte.coding-lease.v1',policy_sha256:policy.policy_sha256,instance_nonce:'c'.repeat(64),root_ids:['project'],armed_at_utc:new Date().toISOString(),expires_at_utc:new Date(Date.now()+3600000).toISOString()}),'utf8');
|
|
33
|
+
const client=new Client({name:'deadbyte-semantic-test',version:'0.8.11'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
|
|
34
|
+
const transport=new StdioClientTransport({command:process.execPath,args:[serverPath],cwd:repoRoot,env:{...getDefaultEnvironment(),DEADBYTE_SIGNING_KEY:keys.privateKeyPath,DEADBYTE_VERIFY_KEY:keys.publicKeyPath,DEADBYTE_CODING_RUNTIME:'1',DEADBYTE_CODING_POLICY:policyPath},stderr:'pipe'});
|
|
35
|
+
return {root,project,client,transport,math,main};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
test('semantic tools provide outline, definition, references and receipt-backed edit by symbol',async()=>{
|
|
39
|
+
const f=await fixture();
|
|
40
|
+
try{
|
|
41
|
+
await f.client.connect(f.transport);
|
|
42
|
+
const names=new Set((await f.client.listTools()).tools.map(t=>t.name));
|
|
43
|
+
for(const name of ['coding_symbol_outline','coding_symbol_definition','coding_symbol_references','coding_symbol_replace']) assert.ok(names.has(name),`missing semantic tool ${name}`);
|
|
44
|
+
|
|
45
|
+
const outline=structured(await f.client.callTool({name:'coding_symbol_outline',arguments:{root_id:'project',path:'math.ts',max_symbols:100}}),'outline');
|
|
46
|
+
assert.equal(outline.status,'ok');
|
|
47
|
+
const add=outline.symbols.find(s=>s.name==='add'&&s.kind==='function');
|
|
48
|
+
assert.ok(add,'add function missing from outline'); assert.match(add.symbol_id,/^[0-9a-f]{64}$/);
|
|
49
|
+
|
|
50
|
+
const useColumn=f.main.split('\n')[1].indexOf('add');
|
|
51
|
+
const definition=structured(await f.client.callTool({name:'coding_symbol_definition',arguments:{root_id:'project',path:'main.ts',line:1,column:useColumn,max_results:20}}),'definition');
|
|
52
|
+
assert.ok(definition.locations.some(x=>x.path==='math.ts'&&x.name==='add'));
|
|
53
|
+
|
|
54
|
+
const references=structured(await f.client.callTool({name:'coding_symbol_references',arguments:{root_id:'project',path:'math.ts',line:add.name_start_line,column:add.name_start_column,max_results:50}}),'references');
|
|
55
|
+
assert.ok(references.locations.some(x=>x.path==='main.ts'));
|
|
56
|
+
assert.ok(references.locations.some(x=>x.path==='math.ts'&&x.start_line===5));
|
|
57
|
+
|
|
58
|
+
const before=structured(await f.client.callTool({name:'coding_file_read',arguments:{root_id:'project',path:'math.ts',encoding:'utf8'}}),'before');
|
|
59
|
+
const replacement='export function add(a: number, b: number) {\n return a - b;\n}';
|
|
60
|
+
const edited=structured(await f.client.callTool({name:'coding_symbol_replace',arguments:{root_id:'project',path:'math.ts',symbol_id:add.symbol_id,new_body:replacement,expected_sha256:before.sha256}}),'replace-symbol');
|
|
61
|
+
assert.equal(edited.status,'committed'); assert.equal(edited.symbol_name,'add');
|
|
62
|
+
const verified=structured(await f.client.callTool({name:'coding_receipt_verify',arguments:{receipt_id:edited.receipt_id}}),'receipt');
|
|
63
|
+
assert.equal(verified.ok,true); assert.equal(verified.signature_valid,true);
|
|
64
|
+
assert.match(await readFile(path.join(f.project,'math.ts'),'utf8'),/return a - b/);
|
|
65
|
+
} finally {await f.client.close().catch(()=>{}); await rm(f.root,{recursive:true,force:true}).catch(()=>{});}
|
|
66
|
+
});
|