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/deadbyte-cli.mjs
CHANGED
|
@@ -1,36 +1,46 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { lstat, mkdir, open, readFile, readdir, rm, stat, writeFile } from 'node:fs/promises';
|
|
3
3
|
import { spawn, spawnSync } from 'node:child_process';
|
|
4
|
-
import { randomBytes } from 'node:crypto';
|
|
4
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
5
5
|
import os from 'node:os';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { setTimeout as sleep } from 'node:timers/promises';
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { defaultPublicKeyPath } from './trust.mjs';
|
|
10
10
|
import { verifyAuditChain } from './audit-verify.mjs';
|
|
11
|
+
import { openRemoteResultJournal, parseRemoteResultCursor } from './remote-result-journal.mjs';
|
|
12
|
+
import { createLiveActivityTracker, formatCompactAuditEvent, formatRemoteLifecycle } from './remote-live-log.mjs';
|
|
11
13
|
|
|
12
14
|
const REMOTE_COMMANDS=new Set([
|
|
13
15
|
'menu','start','resume','park','stop','restart','status','url','test','fulltest','toggle','clean','machinetest',
|
|
14
16
|
'armprocess','disarmprocess','processstatus','armhost','disarmhost','hoststatus','hosttest',
|
|
15
17
|
'armcoding','disarmcoding','codingstatus','codingtest','armautonomous','disarmautonomous','autonomousstatus','autonomoustest'
|
|
16
18
|
]);
|
|
17
|
-
const SESSION_START=['start','armprocess','armcoding','armautonomous'
|
|
19
|
+
const SESSION_START=['start','armprocess','armcoding','armautonomous'];
|
|
18
20
|
const SESSION_STATUS=[
|
|
19
21
|
['processstatus',/^Process plane\s*:\s*ARMED\b/m],
|
|
20
22
|
['codingstatus',/^Coding plane\s*:\s*ARMED\b/m],
|
|
21
23
|
['autonomousstatus',/^Autonomous\s*:\s*ARMED\b/m],
|
|
22
|
-
['hoststatus',/^Host plane\s*:\s*
|
|
24
|
+
['hoststatus',/^Host plane\s*:\s*DISARMED\b/m]
|
|
23
25
|
];
|
|
24
26
|
const SESSION_CLEANUP=['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park'];
|
|
27
|
+
const SUPERVISOR_COMMANDS=Object.freeze({
|
|
28
|
+
start:'supervisorstart',stop:'supervisorstop',status:'supervisorstatus',recover:'supervisorrecover'
|
|
29
|
+
});
|
|
25
30
|
|
|
26
31
|
function stateRoot(){return path.resolve(process.env.DEADBYTE_STATE_ROOT||path.join(os.homedir(),'.deadbyte-mcp'));}
|
|
27
32
|
async function requireRegular(file,label){const info=await lstat(file);if(!info.isFile()||info.isSymbolicLink()) throw new Error(`${label} must be a regular non-symlink file`);return file;}
|
|
28
33
|
function printHelp(){
|
|
29
34
|
process.stdout.write([
|
|
30
35
|
'DEADBYTE MCP CLI','',
|
|
31
|
-
' npx deadbyte-mcp@latest
|
|
36
|
+
' npx deadbyte-mcp@latest mcp # stdio MCP server for local clients',
|
|
37
|
+
' npx deadbyte-mcp@latest remote # compact foreground device session',
|
|
38
|
+
' npx deadbyte-mcp@latest remote --verbose # detailed audit + bridge logs',
|
|
39
|
+
' npx deadbyte-mcp@latest remote --resume <cursor> # replay missed compact results, then reconnect',
|
|
32
40
|
' npx deadbyte-mcp@latest remote status',
|
|
33
41
|
' npx deadbyte-mcp@latest remote restart',
|
|
42
|
+
' npx deadbyte-mcp@latest supervisor status',
|
|
43
|
+
' npx deadbyte-mcp@latest supervisor recover',
|
|
34
44
|
' npx deadbyte-mcp@latest audit verify',
|
|
35
45
|
' npx deadbyte-mcp@latest audit status',''
|
|
36
46
|
].join('\n'));
|
|
@@ -43,7 +53,7 @@ async function remoteContext(){
|
|
|
43
53
|
const powershell=await requireRegular(path.join(systemRoot,'System32','WindowsPowerShell','v1.0','powershell.exe'),'Windows PowerShell');
|
|
44
54
|
return {root,launcher,powershell};
|
|
45
55
|
}
|
|
46
|
-
function invokeController(ctx,command,{capture=false,allowFailure=false}={}){
|
|
56
|
+
function invokeController(ctx,command,{capture=false,allowFailure=false,echoCaptured=true}={}){
|
|
47
57
|
const result=spawnSync(ctx.powershell,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',ctx.launcher,command],{
|
|
48
58
|
stdio:capture?['ignore','pipe','pipe']:'inherit',encoding:capture?'utf8':undefined,windowsHide:false,shell:false
|
|
49
59
|
});
|
|
@@ -51,7 +61,7 @@ function invokeController(ctx,command,{capture=false,allowFailure=false}={}){
|
|
|
51
61
|
const status=Number.isInteger(result.status)?result.status:1;
|
|
52
62
|
const stdout=capture?String(result.stdout||''):'';
|
|
53
63
|
const stderr=capture?String(result.stderr||''):'';
|
|
54
|
-
if(capture){if(stdout) process.stdout.write(stdout);if(stderr) process.stderr.write(stderr);}
|
|
64
|
+
if(capture&&echoCaptured){if(stdout) process.stdout.write(stdout);if(stderr) process.stderr.write(stderr);}
|
|
55
65
|
if(status!==0&&!allowFailure) throw new Error(`remote controller '${command}' failed exit=${status}`);
|
|
56
66
|
return {status,stdout,stderr};
|
|
57
67
|
}
|
|
@@ -68,11 +78,12 @@ async function listLogFiles(root){
|
|
|
68
78
|
}
|
|
69
79
|
return files;
|
|
70
80
|
}
|
|
71
|
-
function formatLogLine(file,line){
|
|
81
|
+
function formatLogLine(file,line,{verbose=false,activityTracker=null}={}){
|
|
72
82
|
if(!line) return null;
|
|
73
83
|
if(/^segment-\d{8}\.jsonl$/.test(path.basename(file))){
|
|
74
84
|
try{
|
|
75
85
|
const event=JSON.parse(line);
|
|
86
|
+
if(!verbose) return activityTracker?activityTracker.observe(event):formatCompactAuditEvent(event);
|
|
76
87
|
const seq=Number.isInteger(event.seq)?`#${event.seq}`:'#?';
|
|
77
88
|
const request=typeof event.request_id==='string'?` ${event.request_id.slice(0,8)}`:'';
|
|
78
89
|
const tool=typeof event.tool==='string'?` ${event.tool}`:'';
|
|
@@ -84,8 +95,9 @@ function formatLogLine(file,line){
|
|
|
84
95
|
else marker='📤 ';
|
|
85
96
|
}
|
|
86
97
|
return `${marker}[AUDIT ${seq}] ${event.event_type||'event'}${tool}${request}`;
|
|
87
|
-
}catch{return
|
|
98
|
+
}catch{return verbose?`[AUDIT] ${line}`:null;}
|
|
88
99
|
}
|
|
100
|
+
if(!verbose) return null;
|
|
89
101
|
const label=path.basename(file).replace(/\.log$/i,'').toUpperCase();
|
|
90
102
|
let marker='';
|
|
91
103
|
if(/\[TOOL IN \]/.test(line)) marker='📥 ';
|
|
@@ -96,6 +108,31 @@ function formatLogLine(file,line){
|
|
|
96
108
|
}
|
|
97
109
|
return `${marker}[${label}] ${line}`;
|
|
98
110
|
}
|
|
111
|
+
function remoteResultJournalPath(root,sessionId){return path.join(root,'runtime','remote-results',`${sessionId}.json`);}
|
|
112
|
+
function auditTerminalResult(file,line){
|
|
113
|
+
if(!/^segment-\d{8}\.jsonl$/.test(path.basename(file))||!line) return null;
|
|
114
|
+
let event;try{event=JSON.parse(line);}catch{return null;}
|
|
115
|
+
if(event?.event_type!=='tool.result'||typeof event.request_id!=='string'||!event.request_id||typeof event.tool!=='string'||!event.tool) return null;
|
|
116
|
+
const observed=Number.isFinite(Date.parse(event.created_at_utc))?new Date(Date.parse(event.created_at_utc)).toISOString():new Date().toISOString();
|
|
117
|
+
return {request_id:event.request_id,tool:event.tool,status:event.outcome?.is_error===true?'error':'ok',observed_at_utc:observed,
|
|
118
|
+
payload_sha256:createHash('sha256').update(Buffer.from(line,'utf8')).digest('hex')};
|
|
119
|
+
}
|
|
120
|
+
async function replayRemoteResults(root,cursor,{verbose=false}={}){
|
|
121
|
+
const parsed=parseRemoteResultCursor(cursor);
|
|
122
|
+
const file=remoteResultJournalPath(root,parsed.session_id);
|
|
123
|
+
await requireRegular(file,'remote result journal');
|
|
124
|
+
const journal=await openRemoteResultJournal({filePath:file,sessionId:parsed.session_id,maxEntries:2048});
|
|
125
|
+
let next=cursor;
|
|
126
|
+
for(;;){
|
|
127
|
+
const page=await journal.replayAfter(next,{limit:200});
|
|
128
|
+
for(const event of page.events){
|
|
129
|
+
const marker=event.status==='error'?'[ERR]':'[OK]';
|
|
130
|
+
process.stdout.write(`${verbose?'[REPLAY] ': '[REPLAY] '}${marker} ${event.tool} [cursor r1:${event.session_id}:${event.seq}]\n`);
|
|
131
|
+
}
|
|
132
|
+
next=page.next_cursor;
|
|
133
|
+
if(!page.has_more) return next;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
99
136
|
async function readAppend(file,offset){
|
|
100
137
|
let info;try{info=await stat(file);}catch(error){if(error?.code==='ENOENT') return {offset:0,text:''};throw error;}
|
|
101
138
|
let start=offset;
|
|
@@ -107,28 +144,45 @@ async function readAppend(file,offset){
|
|
|
107
144
|
try{await handle.read(buffer,0,length,start);}finally{await handle.close();}
|
|
108
145
|
return {offset:info.size,text:buffer.toString('utf8')};
|
|
109
146
|
}
|
|
110
|
-
async function
|
|
147
|
+
async function snapshotRemoteLogOffsets(root){
|
|
111
148
|
const offsets=new Map();
|
|
112
149
|
for(const file of await listLogFiles(root)){
|
|
113
150
|
try{offsets.set(file,(await stat(file)).size);}catch{}
|
|
114
151
|
}
|
|
115
|
-
|
|
152
|
+
return offsets;
|
|
153
|
+
}
|
|
154
|
+
async function tailRemoteLogs(root,signal,{verbose=false,journal=null,offsets=null,activityTracker=null}={}){
|
|
155
|
+
process.stdout.write(verbose
|
|
156
|
+
?'📜 [LOG] Live logs active. Press Ctrl+C to disconnect and revoke authority.\n'
|
|
157
|
+
:'[LOG] Live activity. Ctrl+C disconnects and revokes authority.\n');
|
|
158
|
+
const activeOffsets=offsets??await snapshotRemoteLogOffsets(root);
|
|
116
159
|
while(!signal.aborted){
|
|
117
160
|
for(const file of await listLogFiles(root)){
|
|
118
|
-
const prior=
|
|
161
|
+
const prior=activeOffsets.has(file)?activeOffsets.get(file):0;
|
|
119
162
|
const next=await readAppend(file,prior);
|
|
120
|
-
|
|
163
|
+
activeOffsets.set(file,next.offset);
|
|
121
164
|
for(const line of next.text.split(/\r?\n/)){
|
|
122
|
-
const
|
|
123
|
-
|
|
165
|
+
const terminal=auditTerminalResult(file,line);
|
|
166
|
+
let recorded=null;
|
|
167
|
+
if(terminal&&journal) recorded=await journal.recordTerminal(terminal);
|
|
168
|
+
if(recorded?.duplicate&&!verbose) continue;
|
|
169
|
+
const formatted=formatLogLine(file,line,{verbose,activityTracker});
|
|
170
|
+
if(!formatted) continue;
|
|
171
|
+
if(!verbose&&recorded) process.stdout.write(`${formatted} [cursor ${recorded.cursor}]\n`);
|
|
172
|
+
else process.stdout.write(`${formatted}\n`);
|
|
124
173
|
}
|
|
125
174
|
}
|
|
126
175
|
try{await sleep(250,null,{signal});}catch(error){if(error?.name!=='AbortError') throw error;}
|
|
127
176
|
}
|
|
128
177
|
}
|
|
129
|
-
async function cleanupRemoteSession(ctx){
|
|
178
|
+
async function cleanupRemoteSession(ctx,{verbose=false}={}){
|
|
130
179
|
for(const command of SESSION_CLEANUP){
|
|
131
|
-
try{
|
|
180
|
+
try{
|
|
181
|
+
const result=invokeController(ctx,command,verbose
|
|
182
|
+
?{allowFailure:true}
|
|
183
|
+
:{allowFailure:true,capture:true,echoCaptured:false});
|
|
184
|
+
if(result.status!==0) process.stderr.write(`⚠️ [WARN] cleanup ${command} exit=${result.status}\n`);
|
|
185
|
+
}
|
|
132
186
|
catch(error){process.stderr.write(`⚠️ [WARN] cleanup ${command}: ${String(error?.message||error)}\n`);}
|
|
133
187
|
}
|
|
134
188
|
}
|
|
@@ -150,7 +204,8 @@ async function readRemoteSessionMarker(root){
|
|
|
150
204
|
if(value?.schema==='deadbyte.remote-session.v2'){
|
|
151
205
|
if(!Number.isInteger(value?.owner_pid)||value.owner_pid<1||
|
|
152
206
|
!/^[0-9a-f]{64}$/.test(String(value?.session_nonce||''))||
|
|
153
|
-
!Number.isInteger(value?.guardian_pid)||value.guardian_pid<1
|
|
207
|
+
!Number.isInteger(value?.guardian_pid)||value.guardian_pid<1||
|
|
208
|
+
(value.result_session_id!==undefined&&!/^[0-9a-f]{24}$/.test(String(value.result_session_id)))) throw new Error('remote session marker schema invalid');
|
|
154
209
|
return value;
|
|
155
210
|
}
|
|
156
211
|
throw new Error('remote session marker schema invalid');
|
|
@@ -177,7 +232,9 @@ async function recoverRemoteSession(ctx){
|
|
|
177
232
|
async function claimRemoteSession(ctx){
|
|
178
233
|
const dir=path.join(ctx.root,'runtime');await mkdir(dir,{recursive:true});
|
|
179
234
|
const nonce=randomBytes(32).toString('hex');
|
|
180
|
-
const
|
|
235
|
+
const resultSessionId=randomBytes(12).toString('hex');
|
|
236
|
+
const marker={schema:'deadbyte.remote-session.v2',owner_pid:process.pid,guardian_pid:0,session_nonce:nonce,
|
|
237
|
+
result_session_id:resultSessionId,started_at_utc:new Date().toISOString()};
|
|
181
238
|
const markerPath=remoteSessionMarker(ctx.root);
|
|
182
239
|
try{await writeFile(markerPath,`${JSON.stringify(marker)}\n`,{encoding:'utf8',flag:'wx'});}
|
|
183
240
|
catch(error){if(error?.code==='EEXIST') throw new Error('remote session already claimed');throw error;}
|
|
@@ -202,44 +259,96 @@ async function releaseRemoteSession(ctx,marker){
|
|
|
202
259
|
const same=current?.schema==='deadbyte.remote-session.v2'&¤t.owner_pid===marker.owner_pid&¤t.session_nonce===marker.session_nonce;
|
|
203
260
|
if(same) await rm(remoteSessionMarker(ctx.root),{force:true});
|
|
204
261
|
}
|
|
205
|
-
async function runRemoteSession(){
|
|
262
|
+
async function runRemoteSession({verbose=false,resumeCursor=null}={}){
|
|
206
263
|
const ctx=await remoteContext();
|
|
264
|
+
if(resumeCursor!==null) await replayRemoteResults(ctx.root,resumeCursor,{verbose});
|
|
207
265
|
await recoverRemoteSession(ctx);
|
|
208
266
|
const marker=await claimRemoteSession(ctx);
|
|
267
|
+
const resultJournal=await openRemoteResultJournal({
|
|
268
|
+
filePath:remoteResultJournalPath(ctx.root,marker.result_session_id),sessionId:marker.result_session_id,maxEntries:2048
|
|
269
|
+
});
|
|
270
|
+
const activityTracker=createLiveActivityTracker();
|
|
209
271
|
const aborter=new AbortController();
|
|
210
272
|
const abort=()=>aborter.abort();
|
|
211
273
|
const watchStdin=!process.stdin.isTTY;
|
|
212
274
|
process.once('SIGINT',abort);process.once('SIGTERM',abort);
|
|
213
275
|
if(watchStdin){process.stdin.once('end',abort);process.stdin.once('close',abort);process.stdin.resume();}
|
|
214
276
|
let ready=false;
|
|
277
|
+
let logTask=null;
|
|
215
278
|
try{
|
|
216
|
-
process.stdout.write('DEADBYTE MCP DEVICE SESSION\n');
|
|
217
|
-
process.stdout.write('
|
|
218
|
-
|
|
219
|
-
process.stdout.write('
|
|
279
|
+
if(verbose) process.stdout.write('DEADBYTE MCP DEVICE SESSION\n');
|
|
280
|
+
else process.stdout.write('DEADBYTE MCP\n');
|
|
281
|
+
process.stdout.write(`${formatRemoteLifecycle('device_start')}\n`);
|
|
282
|
+
process.stdout.write(`${formatRemoteLifecycle(resumeCursor!==null?'session_restored':'session_new')}\n`);
|
|
283
|
+
const logOffsets=await snapshotRemoteLogOffsets(ctx.root);
|
|
284
|
+
logTask=tailRemoteLogs(ctx.root,aborter.signal,{verbose,journal:resultJournal,offsets:logOffsets,activityTracker});
|
|
285
|
+
if(verbose) process.stdout.write('[INFO] Starting local + remote runtime...\n');
|
|
286
|
+
else process.stdout.write('[BOOT] Starting local + remote runtime...\n');
|
|
287
|
+
const started=[];
|
|
288
|
+
for(const command of SESSION_START){
|
|
289
|
+
if(!verbose){
|
|
290
|
+
if(command==='start') process.stdout.write('[BOOT] Starting bridge/runtime...\n');
|
|
291
|
+
else process.stdout.write(`🔐 [AUTH] Arming ${command.slice(3)}...\n`);
|
|
292
|
+
}
|
|
293
|
+
const controllerResult=invokeController(ctx,command,verbose?{}:{capture:true,echoCaptured:false});
|
|
294
|
+
started.push(controllerResult);
|
|
295
|
+
if(command==='start'){
|
|
296
|
+
process.stdout.write(`${formatRemoteLifecycle('bridge_connected')}\n`);
|
|
297
|
+
process.stdout.write(`${formatRemoteLifecycle('cloud_connected')}\n`);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
if(!verbose){
|
|
301
|
+
const startText=started[0]?.stdout||'';
|
|
302
|
+
const url=startText.match(/^URL\s*:\s*(\S+)/m)?.[1]||'';
|
|
303
|
+
process.stdout.write('[OK] ONLINE\n');
|
|
304
|
+
process.stdout.write(`${formatRemoteLifecycle('ready')}\n`);
|
|
305
|
+
if(url) process.stdout.write(`URL: ${url}\n`);
|
|
306
|
+
process.stdout.write('🔐 [AUTH] Verifying process, coding, autonomous; host must stay DISARMED...\n');
|
|
307
|
+
}else process.stdout.write('🛡️ [AUTHORITY] Verifying runtime planes; host must stay DISARMED...\n');
|
|
220
308
|
for(const [command,pattern] of SESSION_STATUS){
|
|
221
|
-
const result=invokeController(ctx,command,{capture:true});
|
|
222
|
-
if(!pattern.test(result.stdout)) throw new Error(`remote session authority verification failed: ${command}
|
|
309
|
+
const result=invokeController(ctx,command,{capture:true,echoCaptured:verbose});
|
|
310
|
+
if(!pattern.test(result.stdout)) throw new Error(`remote session authority verification failed: ${command} state mismatch`);
|
|
223
311
|
}
|
|
224
312
|
ready=true;
|
|
225
|
-
process.stdout.write('[DEVICE] DEADBYTE MCP online;
|
|
226
|
-
|
|
313
|
+
if(verbose) process.stdout.write('[DEVICE] DEADBYTE MCP online; process/coding/autonomous ARMED; host DISARMED.\n');
|
|
314
|
+
else process.stdout.write('🔐 [AUTH] ARMED: process, coding, autonomous | host DISARMED\n');
|
|
315
|
+
await logTask;
|
|
227
316
|
}finally{
|
|
317
|
+
const wasAborted=aborter.signal.aborted;
|
|
318
|
+
aborter.abort();
|
|
319
|
+
if(logTask) await logTask.catch(()=>{});
|
|
320
|
+
if(!verbose){for(const line of activityTracker.reconcileInterrupted('session_end')) process.stdout.write(`${line}\n`);}
|
|
228
321
|
process.removeListener('SIGINT',abort);process.removeListener('SIGTERM',abort);
|
|
229
322
|
if(watchStdin){process.stdin.removeListener('end',abort);process.stdin.removeListener('close',abort);process.stdin.pause();}
|
|
230
|
-
|
|
231
|
-
|
|
323
|
+
process.stdout.write(`${formatRemoteLifecycle('cleanup')}\n`);
|
|
324
|
+
if(ready||!wasAborted) process.stdout.write(verbose?'[INFO] Closing remote device session and revoking authority...\n':'[INFO] Disconnecting; revoking authority...\n');
|
|
325
|
+
await cleanupRemoteSession(ctx,{verbose});
|
|
232
326
|
await releaseRemoteSession(ctx,marker);
|
|
233
327
|
}
|
|
234
328
|
}
|
|
235
329
|
async function runRemote(args){
|
|
236
330
|
if(args.length===0){await runRemoteSession();return;}
|
|
237
|
-
if(args.length
|
|
331
|
+
if(args.length===1&&args[0]==='--verbose'){await runRemoteSession({verbose:true});return;}
|
|
332
|
+
if(args.length===2&&args[0]==='--resume'){await runRemoteSession({resumeCursor:args[1]});return;}
|
|
333
|
+
if(args.length===3&&args[0]==='--verbose'&&args[1]==='--resume'){
|
|
334
|
+
await runRemoteSession({verbose:true,resumeCursor:args[2]});return;
|
|
335
|
+
}
|
|
336
|
+
if(args.length===3&&args[0]==='--resume'&&args[2]==='--verbose'){
|
|
337
|
+
await runRemoteSession({verbose:true,resumeCursor:args[1]});return;
|
|
338
|
+
}
|
|
339
|
+
if(args.length>1) throw new Error('remote accepts one controller command, --verbose, or --resume <cursor>');
|
|
238
340
|
const command=args[0];if(!REMOTE_COMMANDS.has(command)) throw new Error(`unsupported remote command '${command}'`);
|
|
239
341
|
const ctx=await remoteContext();
|
|
240
342
|
const result=invokeController(ctx,command,{allowFailure:true});
|
|
241
343
|
process.exitCode=result.status;
|
|
242
344
|
}
|
|
345
|
+
async function runSupervisor(args){
|
|
346
|
+
const action=args[0]||'status';
|
|
347
|
+
if(args.length>1||!Object.hasOwn(SUPERVISOR_COMMANDS,action)) throw new Error(`unsupported supervisor command '${action}'`);
|
|
348
|
+
const ctx=await remoteContext();
|
|
349
|
+
const result=invokeController(ctx,SUPERVISOR_COMMANDS[action],{allowFailure:true});
|
|
350
|
+
process.exitCode=result.status;
|
|
351
|
+
}
|
|
243
352
|
async function runAudit(args){
|
|
244
353
|
const command=args[0]||'status';if(args.length>1) throw new Error('audit accepts one command');
|
|
245
354
|
if(!['verify','status'].includes(command)) throw new Error(`unsupported audit command '${command}'`);
|
|
@@ -251,7 +360,13 @@ async function runAudit(args){
|
|
|
251
360
|
async function main(argv){
|
|
252
361
|
const [command,...rest]=argv;
|
|
253
362
|
if(!command||command==='help'||command==='--help'||command==='-h'){printHelp();return;}
|
|
363
|
+
if(command==='mcp'){
|
|
364
|
+
if(rest.length) throw new Error('mcp accepts no arguments');
|
|
365
|
+
await import('./mcp-server.mjs');
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
254
368
|
if(command==='remote'){await runRemote(rest);return;}
|
|
369
|
+
if(command==='supervisor'){await runSupervisor(rest);return;}
|
|
255
370
|
if(command==='audit'){await runAudit(rest);return;}
|
|
256
371
|
throw new Error(`unknown command '${command}'`);
|
|
257
372
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
const ID=/^[A-Za-z0-9._-]{1,64}$/;
|
|
2
|
+
const OP=/^[a-z][a-z0-9._-]{0,63}$/;
|
|
3
|
+
const MIME=/^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+$/;
|
|
4
|
+
function bound(value,name,min,max){if(!Number.isInteger(value)||value<min||value>max)throw new Error(`${name} must be an integer in [${min}, ${max}]`);return value;}
|
|
5
|
+
function validateDescriptor(value){
|
|
6
|
+
if(!value||typeof value!=='object'||Array.isArray(value))throw new Error('document adapter must be an object');
|
|
7
|
+
if(!ID.test(value.id??''))throw new Error('document adapter id invalid');
|
|
8
|
+
if(!OP.test(value.operation??''))throw new Error('document adapter operation invalid');
|
|
9
|
+
if(!Array.isArray(value.inputMime)||value.inputMime.length<1||value.inputMime.length>16||value.inputMime.some(x=>typeof x!=='string'||!MIME.test(x)))throw new Error('document adapter inputMime invalid');
|
|
10
|
+
if(typeof value.outputMime!=='string'||!MIME.test(value.outputMime))throw new Error('document adapter outputMime invalid');
|
|
11
|
+
if(typeof value.transform!=='function')throw new Error('document adapter transform must be a function');
|
|
12
|
+
return {id:value.id,operation:value.operation,inputMime:[...new Set(value.inputMime)],outputMime:value.outputMime,transform:value.transform};
|
|
13
|
+
}
|
|
14
|
+
function metadataObject(value){
|
|
15
|
+
if(value===undefined)return {};
|
|
16
|
+
if(!value||typeof value!=='object'||Array.isArray(value))throw new Error('document adapter metadata must be an object');
|
|
17
|
+
JSON.stringify(value);
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
export function createDocumentAdapterRegistry({maxInputBytes=8*1024*1024,maxOutputBytes=16*1024*1024}={}){
|
|
21
|
+
bound(maxInputBytes,'maxInputBytes',1,64*1024*1024); bound(maxOutputBytes,'maxOutputBytes',1,128*1024*1024);
|
|
22
|
+
const adapters=new Map();
|
|
23
|
+
function register(value){
|
|
24
|
+
const adapter=validateDescriptor(value);
|
|
25
|
+
if(adapters.has(adapter.id))throw new Error(`document adapter '${adapter.id}' already registered`);
|
|
26
|
+
adapters.set(adapter.id,adapter);
|
|
27
|
+
return {id:adapter.id};
|
|
28
|
+
}
|
|
29
|
+
function list(){return [...adapters.values()].map(a=>({id:a.id,operation:a.operation,input_mime:[...a.inputMime],output_mime:a.outputMime})).sort((a,b)=>a.id.localeCompare(b.id));}
|
|
30
|
+
async function run({adapterId,operation,inputMime,bytes}){
|
|
31
|
+
const adapter=adapters.get(adapterId);
|
|
32
|
+
if(!adapter)throw new Error(`document adapter '${adapterId}' is not registered`);
|
|
33
|
+
if(operation!==adapter.operation)throw new Error(`document adapter operation mismatch: expected ${adapter.operation}`);
|
|
34
|
+
if(!adapter.inputMime.includes(inputMime))throw new Error(`document adapter input MIME denied: ${inputMime}`);
|
|
35
|
+
if(!Buffer.isBuffer(bytes))throw new Error('document adapter input bytes must be a Buffer');
|
|
36
|
+
if(bytes.length>maxInputBytes)throw new Error(`document adapter input exceeds ${maxInputBytes} byte limit`);
|
|
37
|
+
const result=await adapter.transform({bytes:Buffer.from(bytes),inputMime,operation});
|
|
38
|
+
if(!result||!Buffer.isBuffer(result.bytes))throw new Error('document adapter transform must return Buffer bytes');
|
|
39
|
+
if(result.bytes.length>maxOutputBytes)throw new Error(`document adapter output exceeds ${maxOutputBytes} byte limit`);
|
|
40
|
+
return {status:'ok',adapter_id:adapter.id,operation:adapter.operation,input_mime:inputMime,output_mime:adapter.outputMime,bytes:Buffer.from(result.bytes),metadata:metadataObject(result.metadata)};
|
|
41
|
+
}
|
|
42
|
+
return Object.freeze({register,list,run});
|
|
43
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
|
|
5
|
+
const HEX64=/^[0-9a-f]{64}$/;
|
|
6
|
+
const sha256File=file=>createHash('sha256').update(readFileSync(file)).digest('hex');
|
|
7
|
+
const frame=value=>{const body=Buffer.from(JSON.stringify(value),'utf8');return Buffer.concat([Buffer.from(`Content-Length: ${body.length}\r\n\r\n`,'ascii'),body]);};
|
|
8
|
+
|
|
9
|
+
export function createLspStdioClient({executablePath,expectedSha256,args=[],cwd,env={},dependencies=[],requestTimeoutMs=10000,maxMessageBytes=4*1024*1024}){
|
|
10
|
+
if(typeof executablePath!=='string'||executablePath.length<1) throw new Error('LSP executable path missing');
|
|
11
|
+
if(!HEX64.test(expectedSha256??'')) throw new Error('LSP executable SHA-256 invalid');
|
|
12
|
+
const actual=sha256File(executablePath);
|
|
13
|
+
if(actual!==expectedSha256) throw new Error(`LSP executable SHA-256 mismatch: expected ${expectedSha256}, found ${actual}`);
|
|
14
|
+
if(!Array.isArray(dependencies)) throw new Error('LSP dependencies must be an array');
|
|
15
|
+
for(const dependency of dependencies){
|
|
16
|
+
if(!dependency||typeof dependency!=='object'||typeof dependency.path!=='string'||dependency.path.length<1||!HEX64.test(dependency.expectedSha256??'')) throw new Error('LSP dependency identity invalid');
|
|
17
|
+
const observed=sha256File(dependency.path);
|
|
18
|
+
if(observed!==dependency.expectedSha256) throw new Error(`LSP dependency SHA-256 mismatch: expected ${dependency.expectedSha256}, found ${observed}`);
|
|
19
|
+
}
|
|
20
|
+
if(!Array.isArray(args)||args.some(item=>typeof item!=='string')) throw new Error('LSP args must be strings');
|
|
21
|
+
if(!Number.isInteger(requestTimeoutMs)||requestTimeoutMs<1) throw new Error('LSP request timeout invalid');
|
|
22
|
+
if(!Number.isInteger(maxMessageBytes)||maxMessageBytes<256) throw new Error('LSP max message bytes invalid');
|
|
23
|
+
const child=spawn(executablePath,args,{cwd,env:{...env},stdio:['pipe','pipe','pipe'],shell:false,windowsHide:true});
|
|
24
|
+
let input=Buffer.alloc(0);
|
|
25
|
+
let nextId=1;
|
|
26
|
+
let closed=false;
|
|
27
|
+
let expectedExit=false;
|
|
28
|
+
let initialized=false;
|
|
29
|
+
let fatalError=null;
|
|
30
|
+
const pending=new Map();
|
|
31
|
+
|
|
32
|
+
const rejectAll=error=>{
|
|
33
|
+
if(!fatalError) fatalError=error;
|
|
34
|
+
for(const entry of pending.values()) { clearTimeout(entry.timer); entry.reject(error); }
|
|
35
|
+
pending.clear();
|
|
36
|
+
};
|
|
37
|
+
const fail=error=>{
|
|
38
|
+
rejectAll(error instanceof Error?error:new Error(String(error)));
|
|
39
|
+
if(!child.killed) child.kill();
|
|
40
|
+
};
|
|
41
|
+
const dispatch=message=>{
|
|
42
|
+
if(!message||typeof message!=='object') return;
|
|
43
|
+
if(message.id===undefined||message.id===null) return;
|
|
44
|
+
const entry=pending.get(message.id);
|
|
45
|
+
if(!entry) return;
|
|
46
|
+
pending.delete(message.id); clearTimeout(entry.timer);
|
|
47
|
+
if(message.error) entry.reject(new Error(`LSP error ${message.error.code??''}: ${message.error.message??'unknown'}`));
|
|
48
|
+
else entry.resolve(message.result);
|
|
49
|
+
};
|
|
50
|
+
const drain=()=>{
|
|
51
|
+
while(input.length>0){
|
|
52
|
+
const marker=input.indexOf('\r\n\r\n');
|
|
53
|
+
if(marker<0){ if(input.length>8192) fail(new Error('LSP header exceeds 8192 bytes')); return; }
|
|
54
|
+
const header=input.subarray(0,marker).toString('ascii');
|
|
55
|
+
const match=/(?:^|\r\n)Content-Length:\s*(\d+)\s*(?:\r\n|$)/i.exec(header);
|
|
56
|
+
if(!match){ fail(new Error('LSP Content-Length header missing')); return; }
|
|
57
|
+
const size=Number(match[1]);
|
|
58
|
+
if(!Number.isSafeInteger(size)||size<0){ fail(new Error('LSP Content-Length invalid')); return; }
|
|
59
|
+
if(size>maxMessageBytes){ fail(new Error(`LSP message exceeds ${maxMessageBytes} bytes`)); return; }
|
|
60
|
+
const start=marker+4;
|
|
61
|
+
if(input.length<start+size) return;
|
|
62
|
+
const body=input.subarray(start,start+size); input=input.subarray(start+size);
|
|
63
|
+
let parsed;
|
|
64
|
+
try { parsed=JSON.parse(body.toString('utf8')); }
|
|
65
|
+
catch { fail(new Error('LSP message JSON invalid')); return; }
|
|
66
|
+
dispatch(parsed);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
child.stdout.on('data',chunk=>{ if(closed) return; input=Buffer.concat([input,chunk]); drain(); });
|
|
70
|
+
child.on('error',error=>rejectAll(new Error(`LSP process error: ${error.message}`)));
|
|
71
|
+
child.on('exit',(code,signal)=>{
|
|
72
|
+
closed=true;
|
|
73
|
+
if(!expectedExit) rejectAll(new Error(`LSP process exited unexpectedly with code ${code===null?'null':code}${signal?` signal ${signal}`:''}`));
|
|
74
|
+
else rejectAll(new Error('LSP process closed'));
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const send=value=>{
|
|
78
|
+
if(fatalError) throw fatalError;
|
|
79
|
+
if(closed||child.stdin.destroyed) throw new Error('LSP process is closed');
|
|
80
|
+
child.stdin.write(frame(value));
|
|
81
|
+
};
|
|
82
|
+
const request=(method,params=undefined)=>{
|
|
83
|
+
if(typeof method!=='string'||method.length<1) return Promise.reject(new Error('LSP request method missing'));
|
|
84
|
+
if(fatalError) return Promise.reject(fatalError);
|
|
85
|
+
const id=nextId++;
|
|
86
|
+
return new Promise((resolve,reject)=>{
|
|
87
|
+
const timer=setTimeout(()=>{pending.delete(id);reject(new Error(`LSP request timeout after ${requestTimeoutMs}ms: ${method}`));},requestTimeoutMs);
|
|
88
|
+
pending.set(id,{resolve,reject,timer,method});
|
|
89
|
+
try { const message={jsonrpc:'2.0',id,method}; if(params!==undefined) message.params=params; send(message); }
|
|
90
|
+
catch(error){clearTimeout(timer);pending.delete(id);reject(error);}
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
const notify=(method,params=undefined)=>{const message={jsonrpc:'2.0',method};if(params!==undefined)message.params=params;send(message);};
|
|
94
|
+
const initialize=async params=>{
|
|
95
|
+
const result=await request('initialize',params??{});
|
|
96
|
+
initialized=true;
|
|
97
|
+
notify('initialized',{});
|
|
98
|
+
return result;
|
|
99
|
+
};
|
|
100
|
+
const shutdown=async()=>{
|
|
101
|
+
if(expectedExit||closed) return;
|
|
102
|
+
expectedExit=true;
|
|
103
|
+
let shutdownError=null;
|
|
104
|
+
try { if(initialized) await request('shutdown'); }
|
|
105
|
+
catch(error){ shutdownError=error; }
|
|
106
|
+
try { if(!closed) notify('exit'); } catch {}
|
|
107
|
+
if(!closed) await new Promise(resolve=>{const timer=setTimeout(()=>{if(!child.killed)child.kill();resolve();},250);child.once('exit',()=>{clearTimeout(timer);resolve();});});
|
|
108
|
+
closed=true;
|
|
109
|
+
if(shutdownError) throw shutdownError;
|
|
110
|
+
};
|
|
111
|
+
return Object.freeze({initialize,notify,request,shutdown});
|
|
112
|
+
}
|
|
@@ -58,8 +58,9 @@ const stderrChunks = [];
|
|
|
58
58
|
transport.stderr?.on('data', chunk => stderrChunks.push(Buffer.from(chunk)));
|
|
59
59
|
const baseTools = ['contained_transform','evidence_verify','file_read','proof_execute','workspace_open'];
|
|
60
60
|
const codingTools = [
|
|
61
|
-
'coding_benchmark_run','coding_command_run','coding_file_read','coding_file_write',
|
|
61
|
+
'coding_benchmark_run','coding_command_run','coding_file_read','coding_file_write','coding_files_read',
|
|
62
62
|
'coding_receipt_verify','coding_search','coding_session_status','coding_stat',
|
|
63
|
+
'coding_symbol_definition','coding_symbol_diagnostics','coding_symbol_implementations','coding_symbol_outline','coding_symbol_references','coding_symbol_rename_preview','coding_symbol_replace',
|
|
63
64
|
'coding_task_approve','coding_task_cancel','coding_task_events','coding_task_run',
|
|
64
65
|
'coding_task_status','coding_task_submit','coding_task_verify','coding_text_replace','coding_tree'
|
|
65
66
|
];
|
package/src/machine-fs.mjs
CHANGED
|
@@ -168,9 +168,10 @@ function decodeCursor(cursor) {
|
|
|
168
168
|
|
|
169
169
|
function encodeCursor(name) { return Buffer.from(name, 'utf8').toString('base64url'); }
|
|
170
170
|
|
|
171
|
-
async function signReceipt(policy, signingKeyPath, grant, operation, requestSha256, body) {
|
|
171
|
+
async function signReceipt(policy, signingKeyPath, grant, operation, requestSha256, body, requestedReceiptId = null) {
|
|
172
172
|
await fsMkdir(path.join(policy.evidence_dir, 'machine-fs'), { recursive: true });
|
|
173
|
-
const receiptId = randomBytes(12).toString('hex');
|
|
173
|
+
const receiptId = requestedReceiptId ?? randomBytes(12).toString('hex');
|
|
174
|
+
if (!RECEIPT_ID_RE.test(receiptId)) throw new Error('machine fs receipt id must be 24 lowercase hex characters');
|
|
174
175
|
const core = {
|
|
175
176
|
schema: MACHINE_FS_RECEIPT_SCHEMA, receipt_id: receiptId,
|
|
176
177
|
policy_sha256: policy.policy_sha256, grant_instance_nonce: grant.instance_nonce,
|
|
@@ -311,7 +312,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
311
312
|
};
|
|
312
313
|
}
|
|
313
314
|
|
|
314
|
-
async function writePath({ rootId, relativePath, content, encoding = 'utf8', expectedSha256 }) {
|
|
315
|
+
async function writePath({ rootId, relativePath, content, encoding = 'utf8', expectedSha256, receiptId = null }) {
|
|
315
316
|
const grant = await assertCodingArmed(policy, rootId);
|
|
316
317
|
const target = await resolveTarget(policy, grant, rootId, relativePath, 'write');
|
|
317
318
|
const bytes = decodeContent(content, encoding);
|
|
@@ -325,7 +326,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
325
326
|
const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_write', request, {
|
|
326
327
|
root_id: rootId, path: target.relative, started_at_utc: started, completed_at_utc: nowUtc(),
|
|
327
328
|
before_sha256: before.sha256, after_sha256: after.sha256, bytes: after.bytes
|
|
328
|
-
});
|
|
329
|
+
}, receiptId);
|
|
329
330
|
return {
|
|
330
331
|
status: 'committed', root_id: rootId, path: target.relative,
|
|
331
332
|
previous_sha256: before.sha256, sha256: after.sha256, bytes: after.bytes,
|
|
@@ -368,7 +369,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
368
369
|
receipt_id: signed.receipt.receipt_id, receipt_sha256: signed.receipt.receipt_sha256, request_sha256: request
|
|
369
370
|
};
|
|
370
371
|
}
|
|
371
|
-
async function mkdirPath({ rootId, relativePath }) {
|
|
372
|
+
async function mkdirPath({ rootId, relativePath, receiptId = null }) {
|
|
372
373
|
const grant = await assertCodingArmed(policy, rootId);
|
|
373
374
|
const target = await resolveTarget(policy, grant, rootId, relativePath, 'write');
|
|
374
375
|
try { await lstat(target.lexical); throw new Error('machine fs mkdir precondition mismatch: expected absent'); }
|
|
@@ -382,7 +383,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
382
383
|
const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_mkdir', request, {
|
|
383
384
|
root_id: rootId, path: target.relative, started_at_utc: started, completed_at_utc: nowUtc(),
|
|
384
385
|
before_identity_sha256: null, after_identity_sha256: identity.identity_sha256
|
|
385
|
-
});
|
|
386
|
+
}, receiptId);
|
|
386
387
|
return {
|
|
387
388
|
status: 'committed', root_id: rootId, path: target.relative, identity_sha256: identity.identity_sha256,
|
|
388
389
|
receipt_id: signed.receipt.receipt_id, receipt_sha256: signed.receipt.receipt_sha256, request_sha256: request
|
|
@@ -392,7 +393,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
392
393
|
throw error;
|
|
393
394
|
}
|
|
394
395
|
}
|
|
395
|
-
async function movePath({ rootId, sourcePath, destinationPath, expectedSourceIdentity }) {
|
|
396
|
+
async function movePath({ rootId, sourcePath, destinationPath, expectedSourceIdentity, receiptId = null }) {
|
|
396
397
|
if (!SHA256_RE.test(expectedSourceIdentity ?? '')) throw new Error('machine fs expected_source_identity must be lowercase SHA-256');
|
|
397
398
|
const grant = await assertCodingArmed(policy, rootId);
|
|
398
399
|
const source = await resolveExisting(policy, grant, rootId, sourcePath, 'write', false);
|
|
@@ -415,7 +416,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
415
416
|
const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_move', request, {
|
|
416
417
|
root_id: rootId, source_path: source.relative, destination_path: destination.relative,
|
|
417
418
|
started_at_utc: started, completed_at_utc: nowUtc(), source_identity_sha256: expectedSourceIdentity
|
|
418
|
-
});
|
|
419
|
+
}, receiptId);
|
|
419
420
|
return {
|
|
420
421
|
status: 'committed', root_id: rootId, source_path: source.relative, destination_path: destination.relative,
|
|
421
422
|
identity_sha256: expectedSourceIdentity, receipt_id: signed.receipt.receipt_id,
|
|
@@ -460,6 +461,46 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
460
461
|
}
|
|
461
462
|
}
|
|
462
463
|
|
|
464
|
+
async function statePath({ rootId, relativePath }) {
|
|
465
|
+
try {
|
|
466
|
+
const value = await statPath({ rootId, relativePath, hash: true });
|
|
467
|
+
return { exists: true, root_id: rootId, path: value.path, kind: value.kind, bytes: value.bytes,
|
|
468
|
+
sha256: value.sha256, identity_sha256: value.identity_sha256 };
|
|
469
|
+
} catch (error) {
|
|
470
|
+
if (error?.code === 'ENOENT') return { exists: false, root_id: rootId, path: relativePath, kind: null, bytes: 0, sha256: null, identity_sha256: null };
|
|
471
|
+
throw error;
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
async function removeEmptyDir({ rootId, relativePath, expectedSourceIdentity, receiptId = null }) {
|
|
476
|
+
if (!SHA256_RE.test(expectedSourceIdentity ?? '')) throw new Error('machine fs expected_source_identity must be lowercase SHA-256');
|
|
477
|
+
const grant = await assertCodingArmed(policy, rootId);
|
|
478
|
+
const source = await resolveExisting(policy, grant, rootId, relativePath, 'write', false);
|
|
479
|
+
const before = await objectIdentity(source.resolved);
|
|
480
|
+
if (before.kind !== 'directory' || before.entries.length !== 0) throw new Error('machine fs rmdir requires an empty directory');
|
|
481
|
+
if (before.identity_sha256 !== expectedSourceIdentity) throw new Error(`machine fs source identity mismatch: expected ${expectedSourceIdentity}, found ${before.identity_sha256}`);
|
|
482
|
+
const request = requestSha('machine_fs_rmdir_empty', { root_id: rootId, path: source.relative, expected_source_identity: expectedSourceIdentity });
|
|
483
|
+
const started = nowUtc();
|
|
484
|
+
const race = await objectIdentity(source.resolved);
|
|
485
|
+
if (race.kind !== 'directory' || race.entries.length !== 0 || race.identity_sha256 !== expectedSourceIdentity) {
|
|
486
|
+
throw new Error('machine fs rmdir precondition changed before commit');
|
|
487
|
+
}
|
|
488
|
+
await rmdir(source.lexical);
|
|
489
|
+
try {
|
|
490
|
+
try { await lstat(source.lexical); throw new Error('machine fs rmdir post-commit path still exists'); }
|
|
491
|
+
catch (error) { if (error?.code !== 'ENOENT') throw error; }
|
|
492
|
+
const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_rmdir_empty', request, {
|
|
493
|
+
root_id: rootId, path: source.relative, started_at_utc: started, completed_at_utc: nowUtc(),
|
|
494
|
+
before_identity_sha256: expectedSourceIdentity, after_identity_sha256: null
|
|
495
|
+
}, receiptId);
|
|
496
|
+
return { status: 'committed', root_id: rootId, path: source.relative, identity_sha256: expectedSourceIdentity,
|
|
497
|
+
receipt_id: signed.receipt.receipt_id, receipt_sha256: signed.receipt.receipt_sha256, request_sha256: request };
|
|
498
|
+
} catch (error) {
|
|
499
|
+
await fsMkdir(source.lexical, { recursive: false }).catch(() => {});
|
|
500
|
+
throw error;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
463
504
|
return Object.freeze({
|
|
464
505
|
policy,
|
|
465
506
|
stat: statPath,
|
|
@@ -470,6 +511,8 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
|
|
|
470
511
|
move: movePath,
|
|
471
512
|
mkdir: mkdirPath,
|
|
472
513
|
delete: deletePath,
|
|
514
|
+
state: statePath,
|
|
515
|
+
removeEmptyDir,
|
|
473
516
|
verifyReceipt: receiptId => verifyMachineFsReceiptFile({ policy, verifyKeyPath, receiptId })
|
|
474
517
|
});
|
|
475
518
|
}
|