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
package/src/mcp-server.mjs
CHANGED
|
@@ -24,6 +24,8 @@ import { createProcessRuntime } from './process-runtime.mjs';
|
|
|
24
24
|
import { registerProcessTools } from './process-mcp-tools.mjs';
|
|
25
25
|
import { createCodingRuntime, loadCodingPolicy } from './coding-plane.mjs';
|
|
26
26
|
import { createCodingTaskRuntime } from './coding-task-runtime.mjs';
|
|
27
|
+
import { createSemanticCodeRuntime } from './semantic-code.mjs';
|
|
28
|
+
import { loadSemanticLspBackends, semanticConfigBindingFromEnv } from './semantic-lsp-config.mjs';
|
|
27
29
|
import { registerCodingTools } from './coding-mcp-tools.mjs';
|
|
28
30
|
import { createMachineFsRuntime } from './machine-fs.mjs';
|
|
29
31
|
import { registerMachineFsTools } from './machine-fs-mcp-tools.mjs';
|
|
@@ -36,6 +38,9 @@ import { startAutonomousSupervisor } from './autonomous-supervisor.mjs';
|
|
|
36
38
|
import { registerAutonomousTools } from './autonomous-mcp-tools.mjs';
|
|
37
39
|
import { createToolAudit, installToolAudit } from './tool-audit.mjs';
|
|
38
40
|
import { createAuditContextProvider } from './audit-context.mjs';
|
|
41
|
+
import { registerOperatorSurface } from './operator-surface.mjs';
|
|
42
|
+
import { capabilityProfileFromEnv, COMPACT_SURFACE_TOOL_LIMIT, R36_CAPABILITY_LEDGER } from './capability-ledger.mjs';
|
|
43
|
+
import { registerCompactGatewayTools } from './compact-gateway-mcp-tools.mjs';
|
|
39
44
|
import {
|
|
40
45
|
containedTransformOutputSchema,
|
|
41
46
|
evidenceVerifyOutputSchema,
|
|
@@ -55,6 +60,7 @@ const verifyKeyPath = process.env.DEADBYTE_VERIFY_KEY ?? defaultPublicKeyPath();
|
|
|
55
60
|
const auditRuntimeMode = process.env.DEADBYTE_AUDIT_RUNTIME ?? '0';
|
|
56
61
|
if (!['0','1'].includes(auditRuntimeMode)) throw new Error('DEADBYTE_AUDIT_RUNTIME must be 0 or 1');
|
|
57
62
|
const runtimeStateRoot = path.resolve(process.env.DEADBYTE_STATE_ROOT || path.join(os.homedir(),'.deadbyte-mcp'));
|
|
63
|
+
const surfaceProfile = capabilityProfileFromEnv(process.env);
|
|
58
64
|
const localPrivilegedPolicyPath = path.join(packageRoot, 'controller', 'deadbyte-host-policy.json');
|
|
59
65
|
let privilegedPolicyPath = process.env.DEADBYTE_PRIVILEGED_POLICY ?? '';
|
|
60
66
|
if (!privilegedPolicyPath) {
|
|
@@ -99,6 +105,11 @@ if (codingRuntimeMode === '1' && !codingPolicyPath) throw new Error('DEADBYTE_CO
|
|
|
99
105
|
const codingPolicy = codingRuntimeMode === '1' ? await loadCodingPolicy(codingPolicyPath) : null;
|
|
100
106
|
const codingRuntime = codingPolicy ? createCodingRuntime({ policy: codingPolicy, signingKeyPath, verifyKeyPath }) : null;
|
|
101
107
|
const codingTaskRuntime = codingRuntime ? createCodingTaskRuntime({ codingRuntime, signingKeyPath, verifyKeyPath }) : null;
|
|
108
|
+
const semanticLspBinding = semanticConfigBindingFromEnv(process.env);
|
|
109
|
+
const semanticLsp = codingRuntime && semanticLspBinding
|
|
110
|
+
? await loadSemanticLspBackends({ ...semanticLspBinding, codingRuntime })
|
|
111
|
+
: { backends: [], required_ids: [] };
|
|
112
|
+
let semanticRuntime = null;
|
|
102
113
|
const machineFsRuntimeMode = process.env.DEADBYTE_MACHINE_FS_RUNTIME ?? '0';
|
|
103
114
|
if (!['0','1'].includes(machineFsRuntimeMode)) throw new Error('DEADBYTE_MACHINE_FS_RUNTIME must be 0 or 1');
|
|
104
115
|
if (machineFsRuntimeMode === '1' && !codingPolicy) throw new Error('DEADBYTE_MACHINE_FS_RUNTIME=1 requires DEADBYTE_CODING_RUNTIME=1');
|
|
@@ -116,6 +127,10 @@ const observationRuntime = observationRuntimeMode === '1'
|
|
|
116
127
|
|
|
117
128
|
const autonomousRuntimeMode = process.env.DEADBYTE_AUTONOMOUS_RUNTIME ?? '0';
|
|
118
129
|
if (!['0','1'].includes(autonomousRuntimeMode)) throw new Error('DEADBYTE_AUTONOMOUS_RUNTIME must be 0 or 1');
|
|
130
|
+
const autonomousSupervisorMode = process.env.DEADBYTE_AUTONOMOUS_SUPERVISOR_MODE ?? 'in_process';
|
|
131
|
+
if (!['in_process','external'].includes(autonomousSupervisorMode)) {
|
|
132
|
+
throw new Error('DEADBYTE_AUTONOMOUS_SUPERVISOR_MODE must be in_process or external');
|
|
133
|
+
}
|
|
119
134
|
if (autonomousRuntimeMode === '1' && !codingRuntime) throw new Error('DEADBYTE_AUTONOMOUS_RUNTIME=1 requires DEADBYTE_CODING_RUNTIME=1');
|
|
120
135
|
const localAutonomousPolicyPath = path.join(packageRoot,'controller','deadbyte-autonomous-policy.json');
|
|
121
136
|
let autonomousPolicyPath = process.env.DEADBYTE_AUTONOMOUS_POLICY ?? '';
|
|
@@ -125,10 +140,12 @@ if (autonomousRuntimeMode === '1' && !autonomousPolicyPath) {
|
|
|
125
140
|
}
|
|
126
141
|
if (autonomousRuntimeMode === '1' && !autonomousPolicyPath) throw new Error('DEADBYTE_AUTONOMOUS_RUNTIME=1 requires an autonomous policy');
|
|
127
142
|
const autonomousPolicy = autonomousRuntimeMode === '1' ? await loadAutonomousPolicy(autonomousPolicyPath,codingPolicy) : null;
|
|
128
|
-
const nativeDiffRuntime = autonomousPolicy ? createNativeDiffRuntime({ policy:autonomousPolicy,codingRuntime,signingKeyPath,verifyKeyPath }) : null;
|
|
143
|
+
const nativeDiffRuntime = autonomousPolicy ? createNativeDiffRuntime({ policy:autonomousPolicy,codingRuntime,machineFsRuntime,signingKeyPath,verifyKeyPath }) : null;
|
|
144
|
+
semanticRuntime = codingRuntime ? createSemanticCodeRuntime({ codingRuntime, backends: semanticLsp.backends, nativeDiffRuntime }) : null;
|
|
129
145
|
const autonomousRuntime = autonomousPolicy ? createAutonomousRuntime({ policy:autonomousPolicy,codingRuntime,nativeDiffRuntime,
|
|
130
|
-
machineFsRuntime,observationRuntime,processRuntime,signingKeyPath,verifyKeyPath }) : null;
|
|
131
|
-
const autonomousSupervisor = autonomousRuntime && autonomousPolicy.planner.backend === 'openai_compatible'
|
|
146
|
+
machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,signingKeyPath,verifyKeyPath }) : null;
|
|
147
|
+
const autonomousSupervisor = autonomousRuntime && autonomousPolicy.planner.backend === 'openai_compatible' &&
|
|
148
|
+
autonomousSupervisorMode === 'in_process'
|
|
132
149
|
? startAutonomousSupervisor({ runtime: autonomousRuntime, policy: autonomousPolicy })
|
|
133
150
|
: null;
|
|
134
151
|
void autonomousSupervisor;
|
|
@@ -156,10 +173,22 @@ function textResult(schema, object, isError = false) {
|
|
|
156
173
|
return structuredToolResult(schema, object, isError);
|
|
157
174
|
}
|
|
158
175
|
|
|
176
|
+
const COMPACT_CODING_DIRECT_TOOLS=new Set([
|
|
177
|
+
'coding_session_status','coding_tree','coding_symbol_replace','coding_file_read','coding_file_write',
|
|
178
|
+
'coding_text_replace','coding_command_run','coding_benchmark_run','coding_receipt_verify',
|
|
179
|
+
'coding_task_submit','coding_task_run','coding_task_status','coding_task_events','coding_task_cancel',
|
|
180
|
+
'coding_task_approve','coding_task_verify'
|
|
181
|
+
]);
|
|
182
|
+
function filteredToolServer(server,allowed){
|
|
183
|
+
return {registerTool(name,...args){if(allowed.has(name)) return server.registerTool(name,...args);}};
|
|
184
|
+
}
|
|
185
|
+
|
|
159
186
|
serveStdio(() => {
|
|
160
187
|
const server = new McpServer({ name: 'deadbyte-mcp', version: DEADBYTE_VERSION });
|
|
188
|
+
registerOperatorSurface(server,{packageRoot,surfaceProfile,compactToolLimit:COMPACT_SURFACE_TOOL_LIMIT});
|
|
161
189
|
if (toolAudit) installToolAudit(server,toolAudit);
|
|
162
190
|
|
|
191
|
+
if (surfaceProfile === 'full') {
|
|
163
192
|
server.registerTool(
|
|
164
193
|
'workspace_open',
|
|
165
194
|
{
|
|
@@ -275,6 +304,8 @@ serveStdio(() => {
|
|
|
275
304
|
}
|
|
276
305
|
);
|
|
277
306
|
|
|
307
|
+
}
|
|
308
|
+
|
|
278
309
|
server.registerTool(
|
|
279
310
|
'evidence_verify',
|
|
280
311
|
{
|
|
@@ -305,23 +336,24 @@ serveStdio(() => {
|
|
|
305
336
|
});
|
|
306
337
|
}
|
|
307
338
|
|
|
308
|
-
if (agentRuntime) {
|
|
339
|
+
if (agentRuntime && surfaceProfile === 'full') {
|
|
309
340
|
registerAgentTools(server, { runtime: agentRuntime, workspacePathFromId });
|
|
310
341
|
}
|
|
311
342
|
|
|
312
|
-
if (processRuntime) {
|
|
343
|
+
if (processRuntime && surfaceProfile === 'full') {
|
|
313
344
|
registerProcessTools(server, { runtime: processRuntime });
|
|
314
345
|
}
|
|
315
346
|
|
|
316
|
-
if (codingRuntime && codingTaskRuntime) {
|
|
317
|
-
|
|
347
|
+
if (codingRuntime && codingTaskRuntime && semanticRuntime) {
|
|
348
|
+
const codingServer=surfaceProfile==='full'?server:filteredToolServer(server,COMPACT_CODING_DIRECT_TOOLS);
|
|
349
|
+
registerCodingTools(codingServer, { codingRuntime, taskRuntime: codingTaskRuntime, semanticRuntime });
|
|
318
350
|
}
|
|
319
351
|
|
|
320
|
-
if (machineFsRuntime) {
|
|
352
|
+
if (machineFsRuntime && surfaceProfile === 'full') {
|
|
321
353
|
registerMachineFsTools(server, { runtime: machineFsRuntime });
|
|
322
354
|
}
|
|
323
355
|
|
|
324
|
-
if (observationRuntime) {
|
|
356
|
+
if (observationRuntime && surfaceProfile === 'full') {
|
|
325
357
|
registerObservationTools(server, { runtime: observationRuntime });
|
|
326
358
|
}
|
|
327
359
|
|
|
@@ -329,6 +361,11 @@ serveStdio(() => {
|
|
|
329
361
|
registerAutonomousTools(server, { autonomousRuntime, nativeDiffRuntime });
|
|
330
362
|
}
|
|
331
363
|
|
|
364
|
+
registerCompactGatewayTools(server,{
|
|
365
|
+
profile:surfaceProfile,ledger:R36_CAPABILITY_LEDGER,codingRuntime,semanticRuntime,machineFsRuntime,
|
|
366
|
+
processRuntime,observationRuntime,machineRuntime
|
|
367
|
+
});
|
|
368
|
+
|
|
332
369
|
if (hostPolicy) {
|
|
333
370
|
server.registerTool(
|
|
334
371
|
'host_file_read',
|
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
import { createHash, sign as cryptoSign, verify as cryptoVerify } from 'node:crypto';
|
|
2
|
+
import { access, mkdir, readFile, readdir, writeFile } from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { canonicalJson } from './canonical-json.mjs';
|
|
5
|
+
import { validatePortableRelativePath } from './path-policy.mjs';
|
|
6
|
+
import { loadPrivateSigningKey, loadPublicVerifyKey } from './trust.mjs';
|
|
7
|
+
import { assertAutonomousArmed } from './autonomous-policy.mjs';
|
|
8
|
+
|
|
9
|
+
export const NATIVE_DIFF_V2_SCHEMA='deadbyte.native-diff.v2';
|
|
10
|
+
export const NATIVE_DIFF_V2_PREIMAGE_SCHEMA='deadbyte.native-diff-preimage.v2';
|
|
11
|
+
export const NATIVE_DIFF_V2_EVENT_SCHEMA='deadbyte.native-diff-event.v2';
|
|
12
|
+
export const NATIVE_DIFF_V2_RECEIPT_SCHEMA='deadbyte.native-diff-receipt.v2';
|
|
13
|
+
const SHA256_RE=/^[0-9a-f]{64}$/;
|
|
14
|
+
const DIFF_ID_RE=/^[0-9a-f]{64}$/;
|
|
15
|
+
const ZERO_HASH='0'.repeat(64);
|
|
16
|
+
const DIFF_DOMAIN=Buffer.from('DEADBYTE-NATIVE-DIFF-V2\0');
|
|
17
|
+
const PREIMAGE_DOMAIN=Buffer.from('DEADBYTE-NATIVE-DIFF-PREIMAGE-V2\0');
|
|
18
|
+
const EVENT_DOMAIN=Buffer.from('DEADBYTE-NATIVE-DIFF-EVENT-V2\0');
|
|
19
|
+
const RECEIPT_DOMAIN=Buffer.from('DEADBYTE-NATIVE-DIFF-RECEIPT-V2\0');
|
|
20
|
+
const sha256Bytes=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
21
|
+
const sha256Object=value=>sha256Bytes(Buffer.from(canonicalJson(value),'utf8'));
|
|
22
|
+
const exists=file=>access(file).then(()=>true,()=>false);
|
|
23
|
+
const emptyDirectoryIdentity=()=>sha256Object({kind:'directory',entries:[]});
|
|
24
|
+
|
|
25
|
+
function signEnvelope(key,domain,body){
|
|
26
|
+
const bytes=Buffer.from(canonicalJson(body),'utf8');
|
|
27
|
+
const signature=cryptoSign(null,Buffer.concat([domain,bytes]),key.privateKey).toString('base64');
|
|
28
|
+
return {...body,attestation:{algorithm:'ed25519',key_id:key.keyId,signature_base64:signature}};
|
|
29
|
+
}
|
|
30
|
+
function verifyEnvelope(key,domain,envelope,label){
|
|
31
|
+
const {attestation,...body}=envelope??{};
|
|
32
|
+
if(attestation?.algorithm!=='ed25519'||attestation?.key_id!==key.keyId||typeof attestation?.signature_base64!=='string') throw new Error(`${label} signature metadata mismatch`);
|
|
33
|
+
const signature=Buffer.from(attestation.signature_base64,'base64');
|
|
34
|
+
if(signature.length!==64||signature.toString('base64')!==attestation.signature_base64) throw new Error(`${label} signature encoding mismatch`);
|
|
35
|
+
const bytes=Buffer.from(canonicalJson(body),'utf8');
|
|
36
|
+
if(!cryptoVerify(null,Buffer.concat([domain,bytes]),key.publicKey,signature)) throw new Error(`${label} signature verification failed`);
|
|
37
|
+
return body;
|
|
38
|
+
}
|
|
39
|
+
function receiptIdFor(diffId,index,phase){return sha256Object({schema:'deadbyte.native-diff-v2-operation-receipt-id.v1',diff_id:diffId,index,phase}).slice(0,24);}
|
|
40
|
+
function portable(value,label='path'){
|
|
41
|
+
if(typeof value!=='string') throw new Error(`native diff ${label} invalid`);
|
|
42
|
+
validatePortableRelativePath(value);
|
|
43
|
+
return value.replaceAll('\\','/');
|
|
44
|
+
}
|
|
45
|
+
function decodeWriteContent(content,encoding){
|
|
46
|
+
if(typeof content!=='string') throw new Error('native diff write content must be string');
|
|
47
|
+
if(encoding==='utf8') return Buffer.from(content,'utf8');
|
|
48
|
+
if(encoding==='base64'&&/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(content)) return Buffer.from(content,'base64');
|
|
49
|
+
throw new Error('native diff write encoding invalid');
|
|
50
|
+
}
|
|
51
|
+
function normalizeRawOperations(operations,policy){
|
|
52
|
+
if(!Array.isArray(operations)||operations.length<1||operations.length>policy.limits.max_files_per_diff) throw new Error(`native diff operations must contain 1-${policy.limits.max_files_per_diff} entries`);
|
|
53
|
+
let payloadBytes=0; const claimed=new Set();
|
|
54
|
+
const claim=(value,label)=>{const key=value.toLowerCase();if(claimed.has(key))throw new Error(`native diff topology path repeated '${value}' (${label})`);claimed.add(key);};
|
|
55
|
+
const normalized=operations.map((raw,index)=>{
|
|
56
|
+
if(!raw||typeof raw!=='object'||Array.isArray(raw)) throw new Error(`native diff operation ${index} malformed`);
|
|
57
|
+
if(raw.kind==='move'){
|
|
58
|
+
const source_path=portable(raw.source_path,'source_path'); const destination_path=portable(raw.destination_path,'destination_path');
|
|
59
|
+
if(source_path.toLowerCase()===destination_path.toLowerCase()) throw new Error('native diff move source and destination must differ');
|
|
60
|
+
claim(source_path,'move source'); claim(destination_path,'move destination');
|
|
61
|
+
if(!SHA256_RE.test(raw.expected_source_identity??'')) throw new Error('native diff move expected_source_identity invalid');
|
|
62
|
+
const expected_destination_identity=raw.expected_destination_identity??'absent';
|
|
63
|
+
if(expected_destination_identity!=='absent'&&!SHA256_RE.test(expected_destination_identity)) throw new Error('native diff move expected_destination_identity invalid');
|
|
64
|
+
if(expected_destination_identity!=='absent') throw new Error('native diff V2 existing-destination replacement is not allowed; use an explicit preconditioned removal before move');
|
|
65
|
+
return {kind:'move',source_path,destination_path,expected_source_identity:raw.expected_source_identity,expected_destination_identity};
|
|
66
|
+
}
|
|
67
|
+
const pathValue=portable(raw.path);
|
|
68
|
+
claim(pathValue,raw.kind??'unknown');
|
|
69
|
+
if(raw.kind==='mkdir') return {kind:'mkdir',path:pathValue,expected:'absent'};
|
|
70
|
+
if(raw.kind==='rmdir'){
|
|
71
|
+
if(!SHA256_RE.test(raw.expected_source_identity??'')) throw new Error('native diff rmdir expected_source_identity invalid');
|
|
72
|
+
return {kind:'rmdir',path:pathValue,expected_source_identity:raw.expected_source_identity};
|
|
73
|
+
}
|
|
74
|
+
if(raw.kind==='write'){
|
|
75
|
+
const encoding=raw.encoding??'utf8'; const bytes=decodeWriteContent(raw.content,encoding); payloadBytes+=bytes.length;
|
|
76
|
+
if(raw.expected_sha256!=='absent'&&!SHA256_RE.test(raw.expected_sha256??'')) throw new Error('native diff write expected_sha256 invalid');
|
|
77
|
+
return {kind:'write',path:pathValue,content:raw.content,encoding,expected_sha256:raw.expected_sha256,content_sha256:sha256Bytes(bytes)};
|
|
78
|
+
}
|
|
79
|
+
if(raw.kind==='replace'){
|
|
80
|
+
if(!SHA256_RE.test(raw.expected_sha256??'')) throw new Error('native diff replace expected_sha256 invalid');
|
|
81
|
+
if(typeof raw.old_string!=='string'||raw.old_string.length<1||raw.old_string.length>262144) throw new Error('native diff old_string invalid');
|
|
82
|
+
if(typeof raw.new_string!=='string'||raw.new_string.length>524288) throw new Error('native diff new_string invalid');
|
|
83
|
+
const expected_replacements=raw.expected_replacements??1;
|
|
84
|
+
if(!Number.isInteger(expected_replacements)||expected_replacements<1||expected_replacements>64) throw new Error('native diff expected_replacements invalid');
|
|
85
|
+
payloadBytes+=Buffer.byteLength(raw.old_string)+Buffer.byteLength(raw.new_string);
|
|
86
|
+
return {kind:'replace',path:pathValue,expected_sha256:raw.expected_sha256,old_string:raw.old_string,new_string:raw.new_string,expected_replacements,old_sha256:sha256Bytes(Buffer.from(raw.old_string)),new_sha256:sha256Bytes(Buffer.from(raw.new_string))};
|
|
87
|
+
}
|
|
88
|
+
if(raw.kind==='delete'){
|
|
89
|
+
if(!SHA256_RE.test(raw.expected_sha256??'')) throw new Error('native diff delete expected_sha256 invalid');
|
|
90
|
+
return {kind:'delete',path:pathValue,expected_sha256:raw.expected_sha256};
|
|
91
|
+
}
|
|
92
|
+
throw new Error(`native diff operation ${index} kind invalid`);
|
|
93
|
+
});
|
|
94
|
+
if(payloadBytes>policy.limits.max_diff_bytes) throw new Error(`native diff payload exceeds ${policy.limits.max_diff_bytes} bytes`);
|
|
95
|
+
return {normalized,payloadBytes};
|
|
96
|
+
}
|
|
97
|
+
function diffContext(policy,diffId){
|
|
98
|
+
if(!DIFF_ID_RE.test(diffId??'')) throw new Error('invalid native diff_id');
|
|
99
|
+
const dir=path.join(policy.evidence_dir,'native-diffs',diffId);
|
|
100
|
+
return {dir,diffPath:path.join(dir,'diff.json'),preimagePath:path.join(dir,'preimage.json'),eventsDir:path.join(dir,'events'),receiptPath:path.join(dir,'apply-receipt.json')};
|
|
101
|
+
}
|
|
102
|
+
async function writeExclusive(file,value){await writeFile(file,`${canonicalJson(value)}\n`,{flag:'wx'});}
|
|
103
|
+
async function readEnvelope(file,key,domain,label){const parsed=JSON.parse(await readFile(file,'utf8'));verifyEnvelope(key,domain,parsed,label);return parsed;}
|
|
104
|
+
|
|
105
|
+
export function createNativeDiffV2Runtime({policy,codingRuntime,machineFsRuntime,signingKeyPath,verifyKeyPath}){
|
|
106
|
+
if(!policy||!codingRuntime?.policy) throw new Error('native diff V2 requires autonomous and coding policy');
|
|
107
|
+
if(!machineFsRuntime?.state||!machineFsRuntime?.removeEmptyDir) throw new Error('native diff V2 requires machine fs topology runtime');
|
|
108
|
+
if(!signingKeyPath||!verifyKeyPath) throw new Error('native diff V2 requires trust keys');
|
|
109
|
+
|
|
110
|
+
async function materializeOperations(rootId,rawOperations){
|
|
111
|
+
if(!policy.root_ids.includes(rootId)) throw new Error(`native diff root '${rootId}' is not allowed`);
|
|
112
|
+
await assertAutonomousArmed(policy,rootId);
|
|
113
|
+
const {normalized,payloadBytes}=normalizeRawOperations(rawOperations,policy);
|
|
114
|
+
const operations=[];
|
|
115
|
+
for(const op of normalized){
|
|
116
|
+
if(op.kind==='mkdir'){
|
|
117
|
+
const state=await machineFsRuntime.state({rootId,relativePath:op.path});
|
|
118
|
+
if(state.exists) throw new Error(`native diff mkdir precondition '${op.path}' expected absent`);
|
|
119
|
+
operations.push({...op,before_identity_sha256:null,after_identity_sha256:emptyDirectoryIdentity()});
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if(op.kind==='move'){
|
|
123
|
+
const source=await machineFsRuntime.state({rootId,relativePath:op.source_path});
|
|
124
|
+
const destination=await machineFsRuntime.state({rootId,relativePath:op.destination_path});
|
|
125
|
+
if(!source.exists||source.identity_sha256!==op.expected_source_identity) throw new Error(`native diff move source identity precondition mismatch '${op.source_path}'`);
|
|
126
|
+
if(destination.exists) throw new Error(`native diff move destination precondition expected absent '${op.destination_path}'`);
|
|
127
|
+
operations.push({...op,source_kind:source.kind,before_source_identity_sha256:source.identity_sha256,before_destination_identity_sha256:null,after_source_identity_sha256:null,after_destination_identity_sha256:source.identity_sha256});
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
if(op.kind==='rmdir'){
|
|
131
|
+
const state=await machineFsRuntime.state({rootId,relativePath:op.path});
|
|
132
|
+
if(!state.exists||state.kind!=='directory'||state.identity_sha256!==op.expected_source_identity) throw new Error(`native diff rmdir identity precondition mismatch '${op.path}'`);
|
|
133
|
+
const page=await machineFsRuntime.list({rootId,relativePath:op.path,limit:1});
|
|
134
|
+
if(page.entries.length!==0) throw new Error(`native diff rmdir requires empty directory '${op.path}'`);
|
|
135
|
+
operations.push({...op,before_identity_sha256:state.identity_sha256,after_identity_sha256:null});
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const current=await codingRuntime.fileState({rootId,relativePath:op.path});
|
|
139
|
+
if(op.expected_sha256==='absent'){
|
|
140
|
+
if(current.exists) throw new Error(`native diff precondition '${op.path}' expected absent, found ${current.sha256}`);
|
|
141
|
+
}else if(!current.exists||current.sha256!==op.expected_sha256) throw new Error(`native diff precondition '${op.path}' mismatch`);
|
|
142
|
+
if(op.kind==='write') operations.push({...op,before_sha256:current.sha256,after_sha256:op.content_sha256});
|
|
143
|
+
else if(op.kind==='delete') operations.push({...op,before_sha256:current.sha256,after_sha256:null});
|
|
144
|
+
else{
|
|
145
|
+
const read=await codingRuntime.fileRead({rootId,relativePath:op.path,encoding:'utf8'});
|
|
146
|
+
const count=read.content.split(op.old_string).length-1;
|
|
147
|
+
if(count!==op.expected_replacements) throw new Error(`native diff replace '${op.path}' expected ${op.expected_replacements} matches, found ${count}`);
|
|
148
|
+
const next=read.content.split(op.old_string).join(op.new_string);
|
|
149
|
+
operations.push({...op,before_sha256:current.sha256,after_sha256:sha256Bytes(Buffer.from(next,'utf8'))});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const finalPresentPaths=[];
|
|
153
|
+
for(const op of operations){
|
|
154
|
+
if(['write','replace','mkdir'].includes(op.kind)) finalPresentPaths.push(op.path);
|
|
155
|
+
else if(op.kind==='move') finalPresentPaths.push(op.destination_path);
|
|
156
|
+
}
|
|
157
|
+
const finalized=operations.map(op=>{
|
|
158
|
+
if(op.kind!=='mkdir') return op;
|
|
159
|
+
const terminal_children=finalPresentPaths
|
|
160
|
+
.filter(candidate=>candidate!==op.path&&path.posix.dirname(candidate)===op.path)
|
|
161
|
+
.map(candidate=>path.posix.basename(candidate))
|
|
162
|
+
.sort((a,b)=>a.localeCompare(b,'en'));
|
|
163
|
+
return {...op,terminal_children};
|
|
164
|
+
});
|
|
165
|
+
return {operations:finalized,payloadBytes};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
async function preview({rootId,operations:rawOperations,title='',applicationScope=null}){
|
|
169
|
+
if(typeof title!=='string'||title.length>160) throw new Error('native diff title must be <=160 characters');
|
|
170
|
+
if(applicationScope!==null&&!SHA256_RE.test(applicationScope)) throw new Error('native diff application_scope must be SHA-256 or null');
|
|
171
|
+
const {operations,payloadBytes}=await materializeOperations(rootId,rawOperations);
|
|
172
|
+
const identity={schema:NATIVE_DIFF_V2_SCHEMA,policy_sha256:policy.policy_sha256,coding_policy_sha256:policy.coding_policy_sha256,root_id:rootId,title,operations,...(applicationScope===null?{}:{application_scope:applicationScope})};
|
|
173
|
+
const diffId=sha256Object(identity); const ctx=diffContext(policy,diffId); const signing=await loadPrivateSigningKey(signingKeyPath);
|
|
174
|
+
const envelope=signEnvelope(signing,DIFF_DOMAIN,{...identity,diff_id:diffId,created_at_utc:new Date().toISOString()});
|
|
175
|
+
await mkdir(ctx.dir,{recursive:true}); await mkdir(ctx.eventsDir,{recursive:true});
|
|
176
|
+
if(await exists(ctx.diffPath)){
|
|
177
|
+
const verifyKey=await loadPublicVerifyKey(verifyKeyPath); const existing=await readEnvelope(ctx.diffPath,verifyKey,DIFF_DOMAIN,'native diff V2');
|
|
178
|
+
const {created_at_utc:_a,attestation:_b,...a}=existing; const {created_at_utc:_c,attestation:_d,...b}=envelope;
|
|
179
|
+
if(canonicalJson(a)!==canonicalJson(b)) throw new Error('native diff V2 id collision');
|
|
180
|
+
}else await writeExclusive(ctx.diffPath,envelope);
|
|
181
|
+
return {status:'ready',schema:NATIVE_DIFF_V2_SCHEMA,diff_id:diffId,root_id:rootId,operation_count:operations.length,payload_bytes:payloadBytes,
|
|
182
|
+
paths:operations.flatMap(op=>op.kind==='move'?[op.source_path,op.destination_path]:[op.path]),
|
|
183
|
+
operations:operations.map(({content,old_string,new_string,...op})=>op)};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
async function loadDiff(diffId){
|
|
187
|
+
const ctx=diffContext(policy,diffId); const verifyKey=await loadPublicVerifyKey(verifyKeyPath); const envelope=await readEnvelope(ctx.diffPath,verifyKey,DIFF_DOMAIN,'native diff V2');
|
|
188
|
+
const {attestation:_a,created_at_utc:_b,diff_id:claimed,...identity}=envelope;
|
|
189
|
+
if(claimed!==diffId||identity.schema!==NATIVE_DIFF_V2_SCHEMA||identity.policy_sha256!==policy.policy_sha256||identity.coding_policy_sha256!==policy.coding_policy_sha256||sha256Object(identity)!==diffId) throw new Error('native diff V2 identity/hash mismatch');
|
|
190
|
+
return {ctx,envelope,identity};
|
|
191
|
+
}
|
|
192
|
+
async function readEvents(ctx){
|
|
193
|
+
const verifyKey=await loadPublicVerifyKey(verifyKeyPath); const names=(await readdir(ctx.eventsDir)).filter(x=>/^\d{6}\.json$/.test(x)).sort(); const events=[]; let previous=ZERO_HASH;
|
|
194
|
+
for(let i=0;i<names.length;i+=1){const expected=`${String(i+1).padStart(6,'0')}.json`;if(names[i]!==expected)throw new Error(`native diff V2 event gap at ${expected}`);const event=await readEnvelope(path.join(ctx.eventsDir,names[i]),verifyKey,EVENT_DOMAIN,'native diff V2 event');const {attestation:_a,event_sha256:claimed,...body}=event;if(event.schema!==NATIVE_DIFF_V2_EVENT_SCHEMA||event.seq!==i+1||event.prev_sha256!==previous||!SHA256_RE.test(claimed??'')||sha256Object(body)!==claimed)throw new Error(`native diff V2 event ${expected} invalid`);events.push(event);previous=claimed;}
|
|
195
|
+
return events;
|
|
196
|
+
}
|
|
197
|
+
async function appendEvent(ctx,events,diffId,type,payload={}){
|
|
198
|
+
const body={schema:NATIVE_DIFF_V2_EVENT_SCHEMA,diff_id:diffId,seq:events.length+1,created_at_utc:new Date().toISOString(),prev_sha256:events.at(-1)?.event_sha256??ZERO_HASH,type,payload};
|
|
199
|
+
const signing=await loadPrivateSigningKey(signingKeyPath); const event=signEnvelope(signing,EVENT_DOMAIN,{...body,event_sha256:sha256Object(body)}); await writeExclusive(path.join(ctx.eventsDir,`${String(event.seq).padStart(6,'0')}.json`),event);events.push(event);return event;
|
|
200
|
+
}
|
|
201
|
+
async function snapshotFor(rootId,op){
|
|
202
|
+
if(['write','replace','delete'].includes(op.kind)){
|
|
203
|
+
const state=await codingRuntime.fileState({rootId,relativePath:op.path});
|
|
204
|
+
if(state.exists){const read=await codingRuntime.fileRead({rootId,relativePath:op.path,encoding:'base64'});return {kind:op.kind,path:op.path,existed:true,sha256:state.sha256,bytes:read.bytes,content_base64:read.content};}
|
|
205
|
+
return {kind:op.kind,path:op.path,existed:false,sha256:null,bytes:0,content_base64:null};
|
|
206
|
+
}
|
|
207
|
+
if(op.kind==='move'){
|
|
208
|
+
const source=await machineFsRuntime.state({rootId,relativePath:op.source_path}); const destination=await machineFsRuntime.state({rootId,relativePath:op.destination_path});
|
|
209
|
+
return {kind:'move',source_path:op.source_path,destination_path:op.destination_path,source_exists:source.exists,source_identity_sha256:source.identity_sha256,destination_exists:destination.exists,destination_identity_sha256:destination.identity_sha256};
|
|
210
|
+
}
|
|
211
|
+
const state=await machineFsRuntime.state({rootId,relativePath:op.path});
|
|
212
|
+
return {kind:op.kind,path:op.path,exists:state.exists,object_kind:state.kind,identity_sha256:state.identity_sha256};
|
|
213
|
+
}
|
|
214
|
+
async function snapshotMatchesBefore(rootId,op,snap){
|
|
215
|
+
if(['write','replace','delete'].includes(op.kind)){
|
|
216
|
+
const state=await codingRuntime.fileState({rootId,relativePath:op.path}); return snap.existed?state.exists&&state.sha256===snap.sha256:!state.exists;
|
|
217
|
+
}
|
|
218
|
+
if(op.kind==='move'){
|
|
219
|
+
const s=await machineFsRuntime.state({rootId,relativePath:op.source_path}); const d=await machineFsRuntime.state({rootId,relativePath:op.destination_path});
|
|
220
|
+
return s.exists===snap.source_exists&&s.identity_sha256===snap.source_identity_sha256&&d.exists===snap.destination_exists&&d.identity_sha256===snap.destination_identity_sha256;
|
|
221
|
+
}
|
|
222
|
+
const s=await machineFsRuntime.state({rootId,relativePath:op.path}); return s.exists===snap.exists&&s.identity_sha256===snap.identity_sha256;
|
|
223
|
+
}
|
|
224
|
+
async function ensurePreimage(ctx,diffId,identity){
|
|
225
|
+
const verifyKey=await loadPublicVerifyKey(verifyKeyPath);
|
|
226
|
+
if(await exists(ctx.preimagePath)){const stored=await readEnvelope(ctx.preimagePath,verifyKey,PREIMAGE_DOMAIN,'native diff V2 preimage');const {attestation:_a,preimage_sha256:claimed,...body}=stored;if(body.schema!==NATIVE_DIFF_V2_PREIMAGE_SCHEMA||body.diff_id!==diffId||!SHA256_RE.test(claimed??'')||sha256Object(body)!==claimed)throw new Error('native diff V2 preimage hash mismatch');return stored;}
|
|
227
|
+
const snapshots=[]; for(const op of identity.operations){const snap=await snapshotFor(identity.root_id,op);if(!(await snapshotMatchesBefore(identity.root_id,op,snap)))throw new Error('native diff V2 preimage changed while capturing');snapshots.push(snap);}
|
|
228
|
+
const body={schema:NATIVE_DIFF_V2_PREIMAGE_SCHEMA,diff_id:diffId,policy_sha256:policy.policy_sha256,root_id:identity.root_id,created_at_utc:new Date().toISOString(),snapshots};
|
|
229
|
+
const signing=await loadPrivateSigningKey(signingKeyPath); const envelope=signEnvelope(signing,PREIMAGE_DOMAIN,{...body,preimage_sha256:sha256Object(body)}); await writeExclusive(ctx.preimagePath,envelope); return envelope;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function fileStateMatches(rootId,op,which){const state=await codingRuntime.fileState({rootId,relativePath:op.path});const expected=which==='before'?op.before_sha256:op.after_sha256;return expected===null?!state.exists:state.exists&&state.sha256===expected;}
|
|
233
|
+
async function topologyStateMatches(rootId,op,which){
|
|
234
|
+
if(op.kind==='move'){
|
|
235
|
+
const s=await machineFsRuntime.state({rootId,relativePath:op.source_path}); const d=await machineFsRuntime.state({rootId,relativePath:op.destination_path});
|
|
236
|
+
if(which==='before') return s.exists&&s.identity_sha256===op.before_source_identity_sha256&&!d.exists;
|
|
237
|
+
return !s.exists&&d.exists&&d.identity_sha256===op.after_destination_identity_sha256;
|
|
238
|
+
}
|
|
239
|
+
const s=await machineFsRuntime.state({rootId,relativePath:op.path}); const expected=which==='before'?op.before_identity_sha256:op.after_identity_sha256;
|
|
240
|
+
return expected===null?!s.exists:s.exists&&s.identity_sha256===expected;
|
|
241
|
+
}
|
|
242
|
+
const stateMatches=(rootId,op,which)=>['write','replace','delete'].includes(op.kind)?fileStateMatches(rootId,op,which):topologyStateMatches(rootId,op,which);
|
|
243
|
+
async function terminalStateMatches(rootId,op){
|
|
244
|
+
if(op.kind!=='mkdir') return stateMatches(rootId,op,'after');
|
|
245
|
+
const state=await machineFsRuntime.state({rootId,relativePath:op.path});
|
|
246
|
+
if(!state.exists||state.kind!=='directory') return false;
|
|
247
|
+
const names=[]; let cursor=null;
|
|
248
|
+
do{
|
|
249
|
+
const page=await machineFsRuntime.list({rootId,relativePath:op.path,limit:1000,cursor});
|
|
250
|
+
names.push(...page.entries.map(item=>path.posix.basename(item.path)));
|
|
251
|
+
cursor=page.next_cursor;
|
|
252
|
+
if(names.length>4096) return false;
|
|
253
|
+
}while(cursor!==null);
|
|
254
|
+
names.sort((a,b)=>a.localeCompare(b,'en'));
|
|
255
|
+
const expected=[...(op.terminal_children??[])].sort((a,b)=>a.localeCompare(b,'en'));
|
|
256
|
+
return canonicalJson(names)===canonicalJson(expected);
|
|
257
|
+
}
|
|
258
|
+
const receiptClass=op=>['mkdir','move','rmdir'].includes(op.kind)?'machine_fs':'coding';
|
|
259
|
+
async function verifyOperationReceipt(op,receiptId){return receiptClass(op)==='coding'?codingRuntime.verifyReceiptDetailed(receiptId):machineFsRuntime.verifyReceipt(receiptId);}
|
|
260
|
+
async function executeOperation(diffId,rootId,op,index,phase='apply'){
|
|
261
|
+
const receiptId=receiptIdFor(diffId,index,phase); const existing=await verifyOperationReceipt(op,receiptId);
|
|
262
|
+
if(existing.ok) return {recovered:true,receipt_id:receiptId,receipt_sha256:existing.receipt_sha256,request_sha256:existing.request_sha256,operation:existing.operation,receipt_class:receiptClass(op)};
|
|
263
|
+
let result;
|
|
264
|
+
if(op.kind==='write') result=await codingRuntime.fileWrite({rootId,relativePath:op.path,content:op.content,encoding:op.encoding,expectedSha256:op.expected_sha256,receiptId});
|
|
265
|
+
else if(op.kind==='replace') result=await codingRuntime.textReplace({rootId,relativePath:op.path,oldString:op.old_string,newString:op.new_string,expectedSha256:op.expected_sha256,expectedReplacements:op.expected_replacements,receiptId});
|
|
266
|
+
else if(op.kind==='delete') result=await codingRuntime.fileDelete({rootId,relativePath:op.path,expectedSha256:op.expected_sha256,receiptId});
|
|
267
|
+
else if(op.kind==='mkdir') result=await machineFsRuntime.mkdir({rootId,relativePath:op.path,receiptId});
|
|
268
|
+
else if(op.kind==='move') result=await machineFsRuntime.move({rootId,sourcePath:op.source_path,destinationPath:op.destination_path,expectedSourceIdentity:op.expected_source_identity,receiptId});
|
|
269
|
+
else result=await machineFsRuntime.removeEmptyDir({rootId,relativePath:op.path,expectedSourceIdentity:op.expected_source_identity,receiptId});
|
|
270
|
+
const checked=await verifyOperationReceipt(op,receiptId); if(!checked.ok||checked.receipt_sha256!==result.receipt_sha256||checked.request_sha256!==result.request_sha256)throw new Error(`native diff V2 operation receipt verification failed index ${index}`);
|
|
271
|
+
return {recovered:false,receipt_id:receiptId,receipt_sha256:checked.receipt_sha256,request_sha256:checked.request_sha256,operation:checked.operation,receipt_class:receiptClass(op)};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async function rollbackToPreimage(diffId,identity,preimage){
|
|
275
|
+
const receipts=[];
|
|
276
|
+
for(let index=identity.operations.length-1;index>=0;index-=1){
|
|
277
|
+
const op=identity.operations[index]; const snap=preimage.snapshots[index];
|
|
278
|
+
if(await snapshotMatchesBefore(identity.root_id,op,snap)) continue;
|
|
279
|
+
if(!(await stateMatches(identity.root_id,op,'after'))) throw new Error(`native diff V2 rollback_conflict index ${index}`);
|
|
280
|
+
const receiptId=receiptIdFor(diffId,index,'rollback'); let result; let klass=receiptClass(op);
|
|
281
|
+
if(['write','replace','delete'].includes(op.kind)){
|
|
282
|
+
const current=await codingRuntime.fileState({rootId:identity.root_id,relativePath:op.path});
|
|
283
|
+
if(snap.existed) result=await codingRuntime.fileWrite({rootId:identity.root_id,relativePath:op.path,content:snap.content_base64,encoding:'base64',expectedSha256:current.exists?current.sha256:'absent',receiptId});
|
|
284
|
+
else result=await codingRuntime.fileDelete({rootId:identity.root_id,relativePath:op.path,expectedSha256:current.sha256,receiptId});
|
|
285
|
+
}else if(op.kind==='mkdir'){
|
|
286
|
+
result=await machineFsRuntime.removeEmptyDir({rootId:identity.root_id,relativePath:op.path,expectedSourceIdentity:op.after_identity_sha256,receiptId});
|
|
287
|
+
}else if(op.kind==='move'){
|
|
288
|
+
result=await machineFsRuntime.move({rootId:identity.root_id,sourcePath:op.destination_path,destinationPath:op.source_path,expectedSourceIdentity:op.after_destination_identity_sha256,receiptId});
|
|
289
|
+
}else{
|
|
290
|
+
result=await machineFsRuntime.mkdir({rootId:identity.root_id,relativePath:op.path,receiptId});
|
|
291
|
+
const restored=await machineFsRuntime.state({rootId:identity.root_id,relativePath:op.path});
|
|
292
|
+
if(!restored.exists||restored.identity_sha256!==snap.identity_sha256) throw new Error(`native diff V2 rmdir rollback identity mismatch '${op.path}'`);
|
|
293
|
+
}
|
|
294
|
+
receipts.push({index,receipt_class:klass,receipt_id:receiptId,receipt_sha256:result.receipt_sha256});
|
|
295
|
+
}
|
|
296
|
+
return receipts;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
async function createApplyReceipt(ctx,diffId,identity,preimage,events){
|
|
300
|
+
const committed=events.filter(e=>e.type==='operation_committed'); if(committed.length!==identity.operations.length)throw new Error('native diff V2 cannot receipt incomplete transaction');
|
|
301
|
+
const finalStates=[];
|
|
302
|
+
for(const op of identity.operations){
|
|
303
|
+
if(!(await terminalStateMatches(identity.root_id,op))) throw new Error(`native diff V2 final state mismatch '${op.path??op.source_path}'`);
|
|
304
|
+
if(op.kind==='move') finalStates.push({kind:'move',source_path:op.source_path,destination_path:op.destination_path,source_exists:false,destination_identity_sha256:op.after_destination_identity_sha256});
|
|
305
|
+
else if(op.kind==='mkdir') finalStates.push({kind:'mkdir',path:op.path,exists:true,terminal_children:op.terminal_children??[]});
|
|
306
|
+
else finalStates.push({kind:op.kind,path:op.path,exists:op.kind!=='delete'&&op.kind!=='rmdir',sha256:op.after_sha256??null,identity_sha256:op.after_identity_sha256??null});
|
|
307
|
+
}
|
|
308
|
+
const body={schema:NATIVE_DIFF_V2_RECEIPT_SCHEMA,diff_id:diffId,policy_sha256:policy.policy_sha256,coding_policy_sha256:policy.coding_policy_sha256,preimage_sha256:preimage.preimage_sha256,event_head_sha256:events.at(-1)?.event_sha256??ZERO_HASH,completed_at_utc:new Date().toISOString(),operation_receipts:committed.map(e=>({index:e.payload.index,kind:e.payload.kind,receipt_class:e.payload.receipt_class,receipt_id:e.payload.receipt_id,receipt_sha256:e.payload.receipt_sha256,request_sha256:e.payload.request_sha256})),final_states:finalStates};
|
|
309
|
+
const receiptSha=sha256Object(body); const signing=await loadPrivateSigningKey(signingKeyPath); const receipt=signEnvelope(signing,RECEIPT_DOMAIN,{...body,receipt_sha256:receiptSha}); await writeExclusive(ctx.receiptPath,receipt); await appendEvent(ctx,events,diffId,'transaction_completed',{receipt_sha256:receiptSha}); return receipt;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
async function apply({diffId,expectedOperationCount=null}){
|
|
313
|
+
const {ctx,identity}=await loadDiff(diffId);
|
|
314
|
+
if(expectedOperationCount!==null&&(!Number.isInteger(expectedOperationCount)||expectedOperationCount<1||expectedOperationCount>policy.limits.max_files_per_diff||identity.operations.length!==expectedOperationCount))throw new Error(`native diff V2 operation count mismatch: expected ${String(expectedOperationCount)}, signed ${identity.operations.length}`);
|
|
315
|
+
await assertAutonomousArmed(policy,identity.root_id); const codingStatus=await codingRuntime.sessionStatus(); if(!codingStatus.armed)throw new Error(`coding plane is disarmed: ${codingStatus.reason}`);
|
|
316
|
+
if(await exists(ctx.receiptPath)){const checked=await verify({diffId});if(!checked.ok)throw new Error(`existing native diff V2 receipt invalid: ${checked.reason}`);return {status:'existing',diff_id:diffId,receipt_sha256:checked.receipt_sha256,operation_count:identity.operations.length,current_state_matches:checked.current_state_matches};}
|
|
317
|
+
const preimage=await ensurePreimage(ctx,diffId,identity); const events=await readEvents(ctx); if(!events.some(e=>e.type==='transaction_started'))await appendEvent(ctx,events,diffId,'transaction_started',{operation_count:identity.operations.length,preimage_sha256:preimage.preimage_sha256});
|
|
318
|
+
try{
|
|
319
|
+
for(let index=0;index<identity.operations.length;index+=1){const op=identity.operations[index];const prior=events.find(e=>e.type==='operation_committed'&&e.payload?.index===index);if(prior){if(!(await stateMatches(identity.root_id,op,'after')))throw new Error(`native diff V2 committed state changed index ${index}`);continue;}let executed;if(await stateMatches(identity.root_id,op,'after')){const receiptId=receiptIdFor(diffId,index,'apply');const checked=await verifyOperationReceipt(op,receiptId);if(!checked.ok)throw new Error(`native diff V2 unreceipted mutation index ${index}`);executed={recovered:true,receipt_id:receiptId,receipt_sha256:checked.receipt_sha256,request_sha256:checked.request_sha256,operation:checked.operation,receipt_class:receiptClass(op)};}else if(await stateMatches(identity.root_id,op,'before')) executed=await executeOperation(diffId,identity.root_id,op,index);else throw new Error(`native diff V2 concurrent state conflict index ${index}`);if(!(await stateMatches(identity.root_id,op,'after')))throw new Error(`native diff V2 post-operation mismatch index ${index}`);await appendEvent(ctx,events,diffId,'operation_committed',{index,kind:op.kind,path:op.path??null,source_path:op.source_path??null,destination_path:op.destination_path??null,receipt_class:executed.receipt_class,receipt_id:executed.receipt_id,receipt_sha256:executed.receipt_sha256,request_sha256:executed.request_sha256,recovered:executed.recovered});}
|
|
320
|
+
}catch(error){try{const rollbackReceipts=await rollbackToPreimage(diffId,identity,preimage);await appendEvent(ctx,events,diffId,'transaction_rolled_back',{reason:String(error).slice(0,2048),rollback_receipts:rollbackReceipts});}catch(rollbackError){await appendEvent(ctx,events,diffId,'transaction_paused',{reason:String(error).slice(0,1024),rollback_error:String(rollbackError).slice(0,1024)}).catch(()=>{});throw new Error(`native diff V2 apply failed and rollback incomplete: ${String(error)}; ${String(rollbackError)}`);}throw new Error(`native diff V2 apply rolled back: ${String(error)}`);}
|
|
321
|
+
const receipt=await createApplyReceipt(ctx,diffId,identity,preimage,events);return {status:'committed',diff_id:diffId,receipt_sha256:receipt.receipt_sha256,operation_count:identity.operations.length,operation_receipts:receipt.operation_receipts.map(x=>({index:x.index,kind:x.kind,receipt_class:x.receipt_class,receipt_id:x.receipt_id,receipt_sha256:x.receipt_sha256}))};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
async function verify({diffId}){
|
|
325
|
+
try{
|
|
326
|
+
const {ctx,identity}=await loadDiff(diffId);const verifyKey=await loadPublicVerifyKey(verifyKeyPath);const preimage=await readEnvelope(ctx.preimagePath,verifyKey,PREIMAGE_DOMAIN,'native diff V2 preimage');const events=await readEvents(ctx);const receipt=await readEnvelope(ctx.receiptPath,verifyKey,RECEIPT_DOMAIN,'native diff V2 receipt');const {attestation:_a,receipt_sha256:claimed,...body}=receipt;
|
|
327
|
+
if(body.schema!==NATIVE_DIFF_V2_RECEIPT_SCHEMA||body.diff_id!==diffId||body.policy_sha256!==policy.policy_sha256||body.coding_policy_sha256!==policy.coding_policy_sha256||!SHA256_RE.test(claimed??'')||sha256Object(body)!==claimed)return {ok:false,reason:'native diff V2 receipt identity/hash mismatch'};
|
|
328
|
+
const completion=events.at(-1);if(completion?.type!=='transaction_completed'||completion.prev_sha256!==receipt.event_head_sha256||completion.payload?.receipt_sha256!==claimed||receipt.preimage_sha256!==preimage.preimage_sha256)return {ok:false,reason:'native diff V2 receipt/event/preimage binding mismatch'};
|
|
329
|
+
if(!Array.isArray(receipt.operation_receipts)||receipt.operation_receipts.length!==identity.operations.length)return {ok:false,reason:'native diff V2 operation receipt count mismatch'};
|
|
330
|
+
let verified=0,codingVerified=0;for(let index=0;index<identity.operations.length;index+=1){const op=identity.operations[index];const bound=receipt.operation_receipts.find(x=>x.index===index);if(!bound||bound.kind!==op.kind||bound.receipt_class!==receiptClass(op))return {ok:false,reason:`native diff V2 receipt binding mismatch index ${index}`};const checked=await verifyOperationReceipt(op,bound.receipt_id);if(!checked.ok||checked.receipt_sha256!==bound.receipt_sha256||checked.request_sha256!==bound.request_sha256)return {ok:false,reason:`native diff V2 operation receipt invalid index ${index}`};verified+=1;if(bound.receipt_class==='coding')codingVerified+=1;}
|
|
331
|
+
let currentMatches=true;for(const op of identity.operations)if(!(await terminalStateMatches(identity.root_id,op)))currentMatches=false;
|
|
332
|
+
return {ok:true,diff_id:diffId,receipt_sha256:claimed,signature_valid:true,root_id:identity.root_id,operation_count:identity.operations.length,coding_receipts_verified:codingVerified,operation_receipts_verified:verified,final_states:receipt.final_states,current_state_matches:currentMatches,journal_head_sha256:completion.event_sha256};
|
|
333
|
+
}catch(error){return {ok:false,reason:String(error).slice(0,2048)};}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return Object.freeze({preview,apply,verify,policy});
|
|
337
|
+
}
|
package/src/native-diff.mjs
CHANGED
|
@@ -5,6 +5,7 @@ import { canonicalJson } from './canonical-json.mjs';
|
|
|
5
5
|
import { validatePortableRelativePath } from './path-policy.mjs';
|
|
6
6
|
import { loadPrivateSigningKey, loadPublicVerifyKey } from './trust.mjs';
|
|
7
7
|
import { assertAutonomousArmed } from './autonomous-policy.mjs';
|
|
8
|
+
import { createNativeDiffV2Runtime, NATIVE_DIFF_V2_SCHEMA } from './native-diff-v2.mjs';
|
|
8
9
|
|
|
9
10
|
export const NATIVE_DIFF_SCHEMA = 'deadbyte.native-diff.v1';
|
|
10
11
|
export const NATIVE_DIFF_PREIMAGE_SCHEMA = 'deadbyte.native-diff-preimage.v1';
|
|
@@ -97,7 +98,7 @@ async function readEnvelope(file, key, domain, label) {
|
|
|
97
98
|
async function writeExclusive(file, value) {
|
|
98
99
|
await writeFile(file, `${canonicalJson(value)}\n`, { flag:'wx' });
|
|
99
100
|
}
|
|
100
|
-
|
|
101
|
+
function createNativeDiffRuntimeV1({ policy, codingRuntime, signingKeyPath, verifyKeyPath }) {
|
|
101
102
|
if (!policy || !codingRuntime?.policy) throw new Error('native diff runtime requires autonomous and coding policy');
|
|
102
103
|
if (!signingKeyPath || !verifyKeyPath) throw new Error('native diff runtime requires trust keys');
|
|
103
104
|
|
|
@@ -288,8 +289,11 @@ export function createNativeDiffRuntime({ policy, codingRuntime, signingKeyPath,
|
|
|
288
289
|
return receipt;
|
|
289
290
|
}
|
|
290
291
|
|
|
291
|
-
async function apply({ diffId }) {
|
|
292
|
+
async function apply({ diffId, expectedOperationCount = null }) {
|
|
292
293
|
const { ctx, identity } = await loadDiff(diffId);
|
|
294
|
+
if (expectedOperationCount !== null && (!Number.isInteger(expectedOperationCount) || expectedOperationCount < 1 || expectedOperationCount > policy.limits.max_files_per_diff || identity.operations.length !== expectedOperationCount)) {
|
|
295
|
+
throw new Error(`native diff operation count mismatch: expected ${String(expectedOperationCount)}, signed ${identity.operations.length}`);
|
|
296
|
+
}
|
|
293
297
|
await assertAutonomousArmed(policy, identity.root_id);
|
|
294
298
|
const codingStatus = await codingRuntime.sessionStatus();
|
|
295
299
|
if (!codingStatus.armed) throw new Error(`coding plane is disarmed: ${codingStatus.reason}`);
|
|
@@ -401,3 +405,47 @@ export function createNativeDiffRuntime({ policy, codingRuntime, signingKeyPath,
|
|
|
401
405
|
|
|
402
406
|
return Object.freeze({ preview, apply, verify, policy });
|
|
403
407
|
}
|
|
408
|
+
|
|
409
|
+
export { NATIVE_DIFF_V2_SCHEMA };
|
|
410
|
+
|
|
411
|
+
export function createNativeDiffRuntime(options) {
|
|
412
|
+
const v1=createNativeDiffRuntimeV1(options);
|
|
413
|
+
const v2=options.machineFsRuntime ? createNativeDiffV2Runtime(options) : null;
|
|
414
|
+
const isTopology=operations=>Array.isArray(operations)&&operations.some(op=>['mkdir','move','rmdir'].includes(op?.kind));
|
|
415
|
+
const diffPath=diffId=>{
|
|
416
|
+
if(!/^[0-9a-f]{64}$/.test(diffId??'')) throw new Error('invalid native diff_id');
|
|
417
|
+
return path.join(options.policy.evidence_dir,'native-diffs',diffId,'diff.json');
|
|
418
|
+
};
|
|
419
|
+
async function schemaFor(diffId){
|
|
420
|
+
const parsed=JSON.parse(await readFile(diffPath(diffId),'utf8'));
|
|
421
|
+
return parsed?.schema;
|
|
422
|
+
}
|
|
423
|
+
async function preview(args){
|
|
424
|
+
if(!isTopology(args?.operations)) return v1.preview(args);
|
|
425
|
+
if(!v2) throw new Error('native diff V2 topology requires machine fs runtime');
|
|
426
|
+
return v2.preview(args);
|
|
427
|
+
}
|
|
428
|
+
async function apply(args){
|
|
429
|
+
const schema=await schemaFor(args?.diffId);
|
|
430
|
+
if(schema===NATIVE_DIFF_SCHEMA) return v1.apply(args);
|
|
431
|
+
if(schema===NATIVE_DIFF_V2_SCHEMA){
|
|
432
|
+
if(!v2) throw new Error('native diff V2 topology requires machine fs runtime');
|
|
433
|
+
return v2.apply(args);
|
|
434
|
+
}
|
|
435
|
+
throw new Error(`unsupported native diff schema: ${String(schema)}`);
|
|
436
|
+
}
|
|
437
|
+
async function verify(args){
|
|
438
|
+
try {
|
|
439
|
+
const schema=await schemaFor(args?.diffId);
|
|
440
|
+
if(schema===NATIVE_DIFF_SCHEMA) return v1.verify(args);
|
|
441
|
+
if(schema===NATIVE_DIFF_V2_SCHEMA){
|
|
442
|
+
if(!v2) return {ok:false,reason:'native diff V2 topology requires machine fs runtime'};
|
|
443
|
+
return v2.verify(args);
|
|
444
|
+
}
|
|
445
|
+
return {ok:false,reason:`unsupported native diff schema: ${String(schema)}`};
|
|
446
|
+
} catch(error) {
|
|
447
|
+
return {ok:false,reason:String(error).slice(0,2048)};
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return Object.freeze({preview,apply,verify,policy:options.policy});
|
|
451
|
+
}
|
|
@@ -53,8 +53,9 @@ const transport=new StdioClientTransport({command:process.execPath,args:[serverP
|
|
|
53
53
|
const stderr=[]; transport.stderr?.on('data',chunk=>stderr.push(Buffer.from(chunk)));
|
|
54
54
|
const base=['contained_transform','evidence_verify','file_read','proof_execute','workspace_open'];
|
|
55
55
|
const machine=['machine_list','machine_ping','machine_revoke','machine_status'];
|
|
56
|
-
const coding=['coding_benchmark_run','coding_command_run','coding_file_read','coding_file_write','coding_receipt_verify','coding_search',
|
|
57
|
-
'coding_session_status','coding_stat','
|
|
56
|
+
const coding=['coding_benchmark_run','coding_command_run','coding_file_read','coding_file_write','coding_files_read','coding_receipt_verify','coding_search',
|
|
57
|
+
'coding_session_status','coding_stat','coding_symbol_definition','coding_symbol_diagnostics','coding_symbol_implementations','coding_symbol_outline','coding_symbol_references','coding_symbol_rename_preview','coding_symbol_replace',
|
|
58
|
+
'coding_task_approve','coding_task_cancel','coding_task_events','coding_task_run','coding_task_status',
|
|
58
59
|
'coding_task_submit','coding_task_verify','coding_text_replace','coding_tree'];
|
|
59
60
|
const observation=['machine_process_list','machine_search_cancel','machine_search_page','machine_search_start','machine_search_status','machine_system_status'];
|
|
60
61
|
const expected=[...base,...machine,...coding,...observation].sort();
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import * as z from 'zod/v4';
|
|
4
|
+
|
|
5
|
+
function userMessage(text){return {messages:[{role:'user',content:{type:'text',text}}]};}
|
|
6
|
+
function workflow(goal,verb){
|
|
7
|
+
return [
|
|
8
|
+
`${verb}: ${goal}`,
|
|
9
|
+
'Read deadbyte://context only if domain vocabulary or invariants are needed.',
|
|
10
|
+
'Inspect the smallest relevant source/evidence slice; prefer semantic navigation or bounded search over whole-repo reads.',
|
|
11
|
+
'State the acceptance condition, reproduce the current behavior, then make one surgical change.',
|
|
12
|
+
'Verify with the narrow test first, then relevant regression gates. If a tool fails, change the hypothesis instead of retrying blindly.',
|
|
13
|
+
'Report observed outcome and remaining blockers; never call a claim verified without evidence.'
|
|
14
|
+
].join('\n');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function registerOperatorSurface(server,{packageRoot,surfaceProfile='full',compactToolLimit=42}){
|
|
18
|
+
if(!server||!packageRoot) throw new Error('operator surface requires server and packageRoot');
|
|
19
|
+
if(!['full','compact'].includes(surfaceProfile)) throw new Error('operator surface profile must be full or compact');
|
|
20
|
+
const contextPath=path.join(packageRoot,'CONTEXT.md');
|
|
21
|
+
const architecturePath=path.join(packageRoot,'docs','ADR-0001-PRODUCTION-BASELINE-SEAMS.md');
|
|
22
|
+
const argSchema=z.strictObject({goal:z.string().min(1).max(2000)});
|
|
23
|
+
for(const [name,title,verb] of [
|
|
24
|
+
['deadbyte.review','Review','Review the requested code or change'],
|
|
25
|
+
['deadbyte.patch','Patch','Patch the requested behavior'],
|
|
26
|
+
['deadbyte.diagnose','Diagnose','Diagnose the reported failure'],
|
|
27
|
+
['deadbyte.run-tests','Run tests','Verify the requested behavior with tests']
|
|
28
|
+
]){
|
|
29
|
+
server.registerPrompt(name,{title,description:`Compact DEADBYTE ${title.toLowerCase()} workflow with evidence-first verification.`,argsSchema:argSchema},
|
|
30
|
+
async ({goal})=>userMessage(workflow(goal,verb)));
|
|
31
|
+
}
|
|
32
|
+
server.registerResource('deadbyte-context','deadbyte://context',{
|
|
33
|
+
title:'DEADBYTE MCP Context',description:'Canonical production vocabulary, context discipline, and Final-baseline invariants.',mimeType:'text/markdown'
|
|
34
|
+
},async uri=>({contents:[{uri:uri.href,mimeType:'text/markdown',text:await readFile(contextPath,'utf8')}]}));
|
|
35
|
+
server.registerResource('deadbyte-architecture','deadbyte://architecture',{
|
|
36
|
+
title:'DEADBYTE MCP Architecture',description:'Production module seams, tracer bullet, policy, telemetry, semantic and remote decisions.',mimeType:'text/markdown'
|
|
37
|
+
},async uri=>({contents:[{uri:uri.href,mimeType:'text/markdown',text:await readFile(architecturePath,'utf8')}]}));
|
|
38
|
+
server.registerResource('deadbyte-surface-profile','deadbyte://surface-profile',{
|
|
39
|
+
title:'DEADBYTE MCP Surface Profile',description:'Active R36 MCP surface profile and compact tool ceiling.',mimeType:'application/json'
|
|
40
|
+
},async uri=>({contents:[{uri:uri.href,mimeType:'application/json',text:JSON.stringify({
|
|
41
|
+
schema:'deadbyte.surface-profile.v1',profile:surfaceProfile,compact_tool_limit:compactToolLimit
|
|
42
|
+
})}]}));
|
|
43
|
+
}
|