deadbyte-mcp 0.14.0 → 0.15.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/AGENTS.md +11 -18
- package/CONTEXT.md +3 -3
- package/MANIFEST.SHA256 +104 -53
- package/R43-PARENT.json +20 -0
- package/R44-DONORS.json +99 -0
- package/R44-PARENT.json +18 -0
- package/README.txt +7 -2
- package/controller/README.TXT +4 -5
- package/controller/deadbyte-controller.ps1 +1 -1
- package/docs/ARCHITECTURE.md +8 -1
- package/docs/R44-ARCHITECTURE.md +37 -0
- package/package.json +13 -8
- package/scripts/deferred-slot-operation-r43.mjs +126 -0
- package/scripts/deferred-slot-operation-r44.mjs +126 -0
- package/scripts/final-closure-r43.mjs +115 -0
- package/scripts/final-closure-r44.mjs +121 -0
- package/scripts/final-closure-verify-r43.mjs +213 -0
- package/scripts/final-closure-verify-r44.mjs +220 -0
- package/scripts/finalize-r43.mjs +217 -0
- package/scripts/finalize-r44.mjs +217 -0
- package/scripts/full-regression-r43.mjs +20 -0
- package/scripts/full-regression-r44.mjs +20 -0
- package/scripts/gate-windows-r43.ps1 +36 -0
- package/scripts/gate-windows-r44.ps1 +36 -0
- package/scripts/release-parity-r43.mjs +218 -0
- package/scripts/release-parity-r44.mjs +242 -0
- package/scripts/release-parity-tests-r43.ps1 +8 -0
- package/scripts/release-parity-tests-r44.ps1 +8 -0
- package/scripts/verify-r43-parent.mjs +126 -0
- package/scripts/verify-r44-parent.mjs +142 -0
- package/scripts/windows-gate-evidence-r43.mjs +55 -0
- package/scripts/windows-gate-evidence-r44.mjs +55 -0
- package/src/agent-backend-r44.mjs +254 -0
- package/src/autonomous-output-contracts.mjs +1 -1
- package/src/autonomous-policy.mjs +41 -4
- package/src/autonomous-runtime.mjs +25 -12
- package/src/autonomous-supervisor-host.mjs +12 -2
- package/src/capability-ledger.mjs +2 -1
- package/src/codex-app-server-r44.mjs +154 -0
- package/src/coding-plane.mjs +66 -19
- package/src/durable-job-r44.mjs +145 -0
- package/src/external-job-provider-r44.mjs +126 -0
- package/src/host-plane.mjs +27 -6
- package/src/job-supervisor-host-r44.mjs +112 -0
- package/src/machine-fs-smoke-client.mjs +1 -1
- package/src/machine-fs.mjs +21 -10
- package/src/mcp-host-smoke-client.mjs +1 -1
- package/src/mcp-server.mjs +20 -3
- package/src/mcp-smoke-client.mjs +1 -1
- package/src/native-diff-v2.mjs +3 -3
- package/src/native-diff.mjs +3 -2
- package/src/observation-smoke-client.mjs +1 -1
- package/src/operator-surface.mjs +2 -2
- package/src/process-policy.mjs +19 -0
- package/src/process-runtime.mjs +5 -2
- package/src/process-smoke-client.mjs +2 -2
- package/src/provider-circuit.mjs +8 -2
- package/src/r44-compact-disarmed-probe.mjs +74 -0
- package/src/r44-full-surface-probe.mjs +34 -0
- package/src/remote-device-r44.mjs +205 -0
- package/src/remote-mcp-autonomous-smoke-client.mjs +4 -4
- package/src/remote-mcp-r44-parity-client.mjs +203 -0
- package/src/remote-mcp-smoke-client.mjs +7 -4
- package/src/runtime-update.mjs +64 -31
- package/src/skill-mcp-tools-r44.mjs +37 -0
- package/src/skill-plane-r44.mjs +203 -0
- package/src/tunnel-stdio-compat-smoke.mjs +1 -1
- package/src/version.mjs +1 -1
- package/test/agent-backend-r44.test.mjs +115 -0
- package/test/agent-runtime.test.mjs +3 -3
- package/test/autonomous-loop.test.mjs +97 -11
- package/test/autonomous-runtime.test.mjs +2 -2
- package/test/capability-ledger-r36.test.mjs +3 -3
- package/test/cli-entrypoint.test.mjs +1 -1
- package/test/codex-app-server-r44.test.mjs +115 -0
- package/test/codex-autonomous-r44.test.mjs +87 -0
- package/test/coding-plane.test.mjs +2 -2
- package/test/coding-runtime.test.mjs +36 -1
- package/test/compact-catalog-r36.test.mjs +3 -3
- package/test/compact-max-catalog-r40.test.mjs +4 -2
- package/test/compact-max-catalog-r44.test.mjs +97 -0
- package/test/core.test.mjs +1 -1
- package/test/durable-job-r44.test.mjs +75 -0
- package/test/external-job-provider-r44.test.mjs +46 -0
- package/test/full-max-catalog-r40.test.mjs +5 -3
- package/test/full-max-catalog-r44.test.mjs +91 -0
- package/test/host-plane.test.mjs +15 -1
- package/test/native-diff.test.mjs +28 -0
- package/test/output-schema.test.mjs +2 -2
- package/test/process-policy.test.mjs +22 -1
- package/test/prompts-resources.test.mjs +1 -1
- package/test/r33-closeout-regression.test.mjs +13 -30
- package/test/r33-finalization.test.mjs +7 -7
- package/test/r43-finalization.test.mjs +31 -0
- package/test/r43-finalizer.test.mjs +34 -0
- package/test/r43-parent.test.mjs +29 -0
- package/test/r44-finalization.test.mjs +58 -0
- package/test/r44-finalizer.test.mjs +48 -0
- package/test/r44-parent.test.mjs +25 -0
- package/test/release-version.test.mjs +53 -19
- package/test/remote-device-r44.test.mjs +104 -0
- package/test/runtime-self-update.test.mjs +42 -0
- package/test/skill-mcp-r44.test.mjs +38 -0
- package/test/skill-plane-r44.test.mjs +93 -0
- package/test/standing-grants.test.mjs +5 -1
package/R44-DONORS.json
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "deadbyte.r44-donors.v1",
|
|
3
|
+
"observed_at_utc": "2026-09-21T00:00:00+07:00",
|
|
4
|
+
"policy": "reference-and-selective-port-only",
|
|
5
|
+
"donors": [
|
|
6
|
+
{
|
|
7
|
+
"id": "desktop-commander-mcp",
|
|
8
|
+
"url": "https://github.com/wonderwhy-er/DesktopCommanderMCP",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"source_available": true,
|
|
11
|
+
"use": "implementation-reference",
|
|
12
|
+
"adopt": [
|
|
13
|
+
"interactive process/session UX",
|
|
14
|
+
"bounded output pagination",
|
|
15
|
+
"filesystem/search ergonomics",
|
|
16
|
+
"local audit history",
|
|
17
|
+
"remote-device lessons"
|
|
18
|
+
],
|
|
19
|
+
"reject": [
|
|
20
|
+
"raw arbitrary authority widening",
|
|
21
|
+
"PID-as-authority",
|
|
22
|
+
"in-memory-only persistence assumptions",
|
|
23
|
+
"untyped background lifetime"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "remote-desktop-commander",
|
|
28
|
+
"url": "https://github.com/desktop-commander/remote-desktop-commander",
|
|
29
|
+
"license": "repository-docs/manifests-public; hosted-service-proprietary",
|
|
30
|
+
"source_available": false,
|
|
31
|
+
"use": "protocol-and-product-contract-reference",
|
|
32
|
+
"adopt": [
|
|
33
|
+
"OAuth2 PKCE client authorization",
|
|
34
|
+
"OAuth device authorization pairing",
|
|
35
|
+
"multi-machine naming/routing",
|
|
36
|
+
"device revoke semantics",
|
|
37
|
+
"Streamable HTTP remote MCP shape"
|
|
38
|
+
],
|
|
39
|
+
"reject": [
|
|
40
|
+
"hosted relay dependency",
|
|
41
|
+
"online status without end-to-end reachability proof",
|
|
42
|
+
"remote authority mirroring local user permissions without DEADBYTE policy"
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": "desktop-commander-skills",
|
|
47
|
+
"url": "https://github.com/desktop-commander/skills",
|
|
48
|
+
"license": "repository-specific",
|
|
49
|
+
"source_available": true,
|
|
50
|
+
"use": "format-and-workflow-reference",
|
|
51
|
+
"adopt": [
|
|
52
|
+
"SKILL.md progressive disclosure",
|
|
53
|
+
"small metadata-first catalog",
|
|
54
|
+
"references/scripts separation"
|
|
55
|
+
],
|
|
56
|
+
"extend": [
|
|
57
|
+
"content-addressed manifest",
|
|
58
|
+
"declared capability requirements",
|
|
59
|
+
"declared authority planes",
|
|
60
|
+
"resource hashes",
|
|
61
|
+
"provenance",
|
|
62
|
+
"cryptographic verification"
|
|
63
|
+
],
|
|
64
|
+
"reject": [
|
|
65
|
+
"skill text as authority",
|
|
66
|
+
"skill-triggered self-arming"
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "codex-app-server-provider",
|
|
71
|
+
"requested_url": "https://github.com/wonderwhy-er/ai-sdk-provider-codex-app-server",
|
|
72
|
+
"corroborating_public_url": "https://github.com/pablof7z/ai-sdk-provider-codex-app-server",
|
|
73
|
+
"license": "MIT on corroborating implementation",
|
|
74
|
+
"use": "agent-backend-contract-reference",
|
|
75
|
+
"adopt": [
|
|
76
|
+
"persistent JSON-RPC process",
|
|
77
|
+
"persistent/stateless thread modes",
|
|
78
|
+
"mid-execution message injection",
|
|
79
|
+
"interrupt",
|
|
80
|
+
"server-initiated request handling",
|
|
81
|
+
"model discovery"
|
|
82
|
+
],
|
|
83
|
+
"reject": [
|
|
84
|
+
"auto-approval as authority",
|
|
85
|
+
"danger-full-access default",
|
|
86
|
+
"provider-owned permission semantics overriding DEADBYTE authority"
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
"adversarial_acceptance": [
|
|
91
|
+
"rotated credentials persist atomically before old credentials become unusable",
|
|
92
|
+
"registered is not reachable: online requires verified transport readiness and request acknowledgement",
|
|
93
|
+
"remote requests are idempotently identified and cannot disappear silently without a terminal transport result",
|
|
94
|
+
"shared state files commit by atomic rename and readers never accept truncated JSON",
|
|
95
|
+
"persistent jobs declare ownership and survive only under an explicit external supervisor contract",
|
|
96
|
+
"skills cannot widen or arm authority and every loaded byte is hash-bound",
|
|
97
|
+
"agent backend threads survive controller recreation through durable thread identity without granting new authority"
|
|
98
|
+
]
|
|
99
|
+
}
|
package/R44-PARENT.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "deadbyte.r44-parent.v1",
|
|
3
|
+
"parent_release_id": "v0.14.1-0a5a833892593283",
|
|
4
|
+
"parent_version": "0.14.1",
|
|
5
|
+
"parent_manifest_sha256": "0a5a8338925932830986421dda60ec5643f62f600404de4992fda2a5e79d09a9",
|
|
6
|
+
"parent_manifest_file_count": 1834,
|
|
7
|
+
"parent_release_root": "C:\\Users\\DEADBYTE\\.deadbyte-mcp\\releases\\v0.14.1-0a5a833892593283",
|
|
8
|
+
"parent_generation_manifest_sha256": "fcfcb5a47d55039b7bb5d42faa0739b57b13d8a420d4418ae09d96d2862967cb",
|
|
9
|
+
"parent_generation_file_count": 7,
|
|
10
|
+
"parent_generation_root": "C:\\Users\\DEADBYTE\\.deadbyte-mcp\\generations\\v0.14.1-0a5a833892593283-ga2198d593efd75bd",
|
|
11
|
+
"parent_launcher_sha256": "e054796810c3d7be99ff3036e7427c5b75cfd823ea82808edcd28e928252e37e",
|
|
12
|
+
"parent_final_closure_path": "C:\\Users\\DEADBYTE\\.deadbyte-mcp\\evidence\\release\\r43-final-0a5a833892593283.json",
|
|
13
|
+
"parent_final_closure_file_sha256": "f24100212b55d2016ea9c4ff47df5f026c8edc0b9b8643933ed8bf26fde3803f",
|
|
14
|
+
"parent_final_closure_sha256": "2f29e94dd726638c23b2e520a608dcf2a6919e43348855be3940599d557f920b",
|
|
15
|
+
"parent_final_closure_signer_key_id": "c0727a7911e29a0f1edd3cd910e47f89f43edb484743988c89cd82bfd5e37936",
|
|
16
|
+
"parent_proof": "immutable-slot+generation+signed-final-closure",
|
|
17
|
+
"development_root": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-r42-agentic-dev"
|
|
18
|
+
}
|
package/README.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
DEADBYTE MCP V0.
|
|
1
|
+
DEADBYTE MCP V0.15.0 / R44 REMOTE AGENT + SKILL BASELINE
|
|
2
2
|
=========================
|
|
3
3
|
|
|
4
4
|
AUTHENTICATED MACHINE TRUTH + DURABLE AGENT + CODING + AUTONOMOUS PRODUCTION ENGINE
|
|
@@ -7,7 +7,7 @@ NPX PRIMARY OPERATOR UX
|
|
|
7
7
|
------------------------
|
|
8
8
|
Use the npm CLI entry point instead of the legacy CMD convenience wrapper:
|
|
9
9
|
|
|
10
|
-
npx -y deadbyte-mcp@0.
|
|
10
|
+
npx -y deadbyte-mcp@0.15.0 mcp
|
|
11
11
|
npx deadbyte-mcp@latest remote
|
|
12
12
|
npx deadbyte-mcp@latest remote status
|
|
13
13
|
npx deadbyte-mcp@latest remote restart
|
|
@@ -399,3 +399,8 @@ hosted convenience on one side; self-owned release/evidence authority on the oth
|
|
|
399
399
|
NO RAW SHELL COMMAND STRING. NO CALLER-SELECTED EXECUTABLE. CODING AND AUTONOMOUS
|
|
400
400
|
EXECUTION REQUIRE EXPLICIT LOCAL STANDING GRANTS. REPORTS ARE CLAIMS; VERIFIED
|
|
401
401
|
OBSERVATIONS AND SIGNED EVIDENCE ARE AUTHORITY.
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
R44 REMOTE AGENT / SKILL / DURABLE JOB
|
|
405
|
+
---------------------------------------
|
|
406
|
+
R44 keeps the R43 authority model and adds one read-only public skill_catalog, bringing the compact/full surfaces to exact 43/81. Skills are Ed25519/content-addressed and cannot arm authority. The optional codex_app_server planner is executable-hash pinned, uses approvalPolicy=never and read-only sandbox defaults, persists thread identity, and fails closed on interrupted requests. Remote devices require Ed25519 identity, epoch, verified reachability, local capability authorization, durable request IDs and terminal acknowledgement. Persistent jobs require the external supervisor and exact process identity.
|
package/controller/README.TXT
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
DEADBYTE MCP V0.
|
|
1
|
+
DEADBYTE MCP V0.15.0 / R44 CONTROLLER
|
|
2
2
|
====================================
|
|
3
3
|
|
|
4
4
|
ENTRY POINT
|
|
@@ -11,8 +11,8 @@ Bare `remote` is a foreground device session. It starts the verified runtime, ar
|
|
|
11
11
|
coding, and autonomous authority, verifies those three planes are ARMED, and requires Desktop and Host
|
|
12
12
|
to stay DISARMED. R40 Desktop observation/UIA grounding remains available read-only; GUI mutation needs
|
|
13
13
|
the separate explicit Desktop standing grant and Autonomous authority cannot substitute for it.
|
|
14
|
-
The production Bridge uses the compact capability profile (exact
|
|
15
|
-
stdio MCP keeps the exact full
|
|
14
|
+
The production Bridge uses the compact capability profile (exact 43 tools / 6 gateways) while local
|
|
15
|
+
stdio MCP keeps the exact full 81-tool profile. The compact console shows request-before-result
|
|
16
16
|
Live Activity without raw SHA text, request IDs, payload JSON, or duplicate Bridge stdout by
|
|
17
17
|
default; use `remote --verbose` for the detailed audit/runtime stream. Ctrl+C/SIGTERM or foreground
|
|
18
18
|
input closure revokes Desktop/process/coding/autonomous authority, applies fail-safe Host disarm, and parks
|
|
@@ -101,8 +101,7 @@ policy digests and profile hashes to the explicit mutable development root; the
|
|
|
101
101
|
autonomoustest run the R37 compact public capability-closure MRTR production gate
|
|
102
102
|
|
|
103
103
|
disarmcoding also revokes autonomous authority. No MCP tool creates or widens either
|
|
104
|
-
grant.
|
|
105
|
-
client_sampling uses the connected MCP client's model with durable resume state.
|
|
104
|
+
grant. Provider-backed planners (openai_compatible, openai_responses, or hash-pinned codex_app_server) use the background supervisor; client_sampling uses the connected MCP client's model with durable resume state.
|
|
106
105
|
|
|
107
106
|
R27 IMMUTABLE SLOT UPDATE
|
|
108
107
|
-------------------------
|
|
@@ -1336,7 +1336,7 @@ while ($true) {
|
|
|
1336
1336
|
Clear-Host
|
|
1337
1337
|
$cfg = Get-Config
|
|
1338
1338
|
Assert-ControllerRootBound $cfg
|
|
1339
|
-
Write-Host 'DEADBYTE MCP ON-DEMAND CONTROLLER V0.
|
|
1339
|
+
Write-Host 'DEADBYTE MCP ON-DEMAND CONTROLLER V0.15.0 / R44'
|
|
1340
1340
|
Write-Host '======================================'
|
|
1341
1341
|
Show-State $cfg | Out-Null
|
|
1342
1342
|
Write-Host ''
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# DEADBYTE MCP V0.
|
|
1
|
+
# DEADBYTE MCP V0.15.0 / R44 ARCHITECTURE
|
|
2
2
|
|
|
3
3
|
```mermaid
|
|
4
4
|
flowchart TD
|
|
@@ -180,3 +180,10 @@ The controller defaults `MachineRuntimeEnabled` on, forwards it only to the Brid
|
|
|
180
180
|
non-mutating `machinetest` public HTTPS gate. That gate cross-checks status/list, derives machine_id
|
|
181
181
|
from public SPKI, issues a random nonce, and verifies the Ed25519 signature without target-local key
|
|
182
182
|
access. See `V085-R29-MACHINE-IDENTITY.md`.
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
## R44 remote-agent and skill boundary
|
|
186
|
+
|
|
187
|
+
R44 adds one read-only public `skill_catalog`, making the current full/compact catalogs exactly 81/43 while sealed R43 remains 80/42. Skill manifests are Ed25519-authenticated, content-addressed closed-world resource sets; skill content is never authority.
|
|
188
|
+
|
|
189
|
+
The Agent Backend commits pending requests before send and classifies unresolved restart work as interrupted. The Codex app-server adapter binds current thread/turn identities, defaults approvals to never and sandbox to read-only, and persists logical thread identity. Remote Device routing requires Ed25519 SPKI + epoch, verified reachability, local capability authorization, stable request identity and terminal state. Only the external Durable Job supervisor may own persistent jobs; reattachment requires exact handle, PID, creation identity and profile.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# DEADBYTE MCP R44 Architecture
|
|
2
|
+
|
|
3
|
+
R44 / V0.15.0 is the remote-agent-and-skill successor to sealed R43 `v0.14.1-0a5a833892593283`. R43 is immutable parent authority.
|
|
4
|
+
|
|
5
|
+
## Decision
|
|
6
|
+
|
|
7
|
+
R44 keeps DEADBYTE authority, evidence, release slots, typed tools, hash preconditions, signed journals, rollback and all-disarmed closure as the foundation. External projects are donors and failure corpora, never authority.
|
|
8
|
+
|
|
9
|
+
## New planes
|
|
10
|
+
|
|
11
|
+
### Skill Plane
|
|
12
|
+
|
|
13
|
+
Metadata-first progressive disclosure. A catalog entry exposes only name, version, description, capability requirements and authority declarations. Loading a skill verifies a content-addressed manifest, every declared resource hash, provenance, and Ed25519 attestation before returning instructions. Skill text cannot arm or renew Process, Coding, Autonomous, Desktop or Host.
|
|
14
|
+
|
|
15
|
+
### Agent Backend Plane
|
|
16
|
+
|
|
17
|
+
A persistent JSON-RPC process contract for Codex app-server style providers. Session identity is durable and explicit. Threads support resume, bounded injection and interrupt. Server-initiated approval requests are translated into DEADBYTE policy/consent checks; provider auto-approval never widens authority.
|
|
18
|
+
|
|
19
|
+
### Remote Device Plane
|
|
20
|
+
|
|
21
|
+
Device identity is a public-key identity plus epoch, not a display name. Pairing and AI-client authorization are separate. OAuth2/PKCE and device authorization may establish authentication, but a remote call is executable only when the local device reports a verified ready transport and the requested DEADBYTE capability is locally authorized. Delivery uses stable request IDs and terminal acknowledgement states.
|
|
22
|
+
|
|
23
|
+
### Durable Job Supervisor
|
|
24
|
+
|
|
25
|
+
Every job declares one lifetime: controller-owned, session-owned, or persistent. Persistent means an out-of-process supervisor owns execution, durable status/log identity exists, and restart recovery proves the same job identity. A timeout is never silently rebranded as persistence.
|
|
26
|
+
|
|
27
|
+
## R44 hard rules
|
|
28
|
+
|
|
29
|
+
- R43 release slot and final evidence are read-only.
|
|
30
|
+
- No external donor may add raw shell/PID/stdin/environment authority to the public surface.
|
|
31
|
+
- No skill, remote relay, provider, model, or client can arm a DEADBYTE authority plane.
|
|
32
|
+
- Shared JSON state is atomic temp+fsync+rename; corrupted/truncated state fails closed.
|
|
33
|
+
- Online/reachable are distinct states; only reachable may accept routed work.
|
|
34
|
+
- Remote calls have stable IDs, replay classification, acknowledgement and terminal result/error.
|
|
35
|
+
- Credential rotation is persisted atomically before the superseded credential is discarded.
|
|
36
|
+
- All new public tools have strict input and output schemas.
|
|
37
|
+
- R44 Final requires exact R43 parent proof, full regression, restart/recovery adversarial tests, remote/skill/backend gates, reversible activation, exact R43 rollback, same-slot R44 restore, and signed all-disarmed closure.
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deadbyte-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
|
-
"description": "Authenticated MCP agentic runtime with
|
|
6
|
+
"description": "Authenticated MCP agentic runtime with signed skills, persistent model backends, identity-bound remote devices, durable job supervision, immutable release slots, and separately revocable machine authority.",
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": ">=22"
|
|
9
9
|
},
|
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
"r42:parent:verify": "node scripts/verify-r42-parent.mjs",
|
|
17
17
|
"r42:eval": "node scripts/agent-eval-r42.mjs",
|
|
18
18
|
"self-update:runtime": "node scripts/runtime-self-update.mjs",
|
|
19
|
-
"self-update:deferred": "node scripts/deferred-slot-operation-
|
|
20
|
-
"release:parity": "node scripts/release-parity-
|
|
21
|
-
"release:final:write": "node scripts/final-closure-
|
|
22
|
-
"release:final:verify": "node scripts/final-closure-verify-
|
|
19
|
+
"self-update:deferred": "node scripts/deferred-slot-operation-r44.mjs",
|
|
20
|
+
"release:parity": "node scripts/release-parity-r44.mjs",
|
|
21
|
+
"release:final:write": "node scripts/final-closure-r44.mjs",
|
|
22
|
+
"release:final:verify": "node scripts/final-closure-verify-r44.mjs",
|
|
23
23
|
"proof": "node src/proof-cli.mjs workspaces/demo input.txt",
|
|
24
24
|
"verify": "node src/verifier-cli.mjs workspaces/demo evidence/latest.json",
|
|
25
25
|
"trust:init": "node src/trust-init.mjs",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"contained:run": "node src/contained-cli.mjs workspaces/demo input.txt",
|
|
43
43
|
"contained:smoke": "node src/contained-smoke.mjs",
|
|
44
44
|
"mcp:contained:smoke": "node src/mcp-contained-smoke-client.mjs",
|
|
45
|
-
"gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-
|
|
45
|
+
"gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r44.ps1",
|
|
46
46
|
"authority:smoke": "node src/authority-smoke.mjs",
|
|
47
47
|
"mcp:remote:smoke": "node src/remote-mcp-smoke-client.mjs",
|
|
48
48
|
"mcp:host:smoke": "node src/mcp-host-smoke-client.mjs",
|
|
@@ -53,7 +53,12 @@
|
|
|
53
53
|
"audit:verify": "node src/deadbyte-cli.mjs audit verify",
|
|
54
54
|
"audit:status": "node src/deadbyte-cli.mjs audit status",
|
|
55
55
|
"desktop:build": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/build-desktop-r40.ps1",
|
|
56
|
-
"desktop:policy:refresh": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/init-desktop-policy-r40.ps1"
|
|
56
|
+
"desktop:policy:refresh": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/init-desktop-policy-r40.ps1",
|
|
57
|
+
"r43:parent:verify": "node scripts/verify-r43-parent.mjs",
|
|
58
|
+
"r43:full:test": "node scripts/full-regression-r43.mjs",
|
|
59
|
+
"r44:parent:verify": "node scripts/verify-r44-parent.mjs",
|
|
60
|
+
"r44:full:test": "node scripts/full-regression-r44.mjs",
|
|
61
|
+
"finalize:r44": "node scripts/finalize-r44.mjs"
|
|
57
62
|
},
|
|
58
63
|
"bundleDependencies": [
|
|
59
64
|
"@modelcontextprotocol/server",
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { createHash, createPublicKey, randomBytes } from 'node:crypto';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { mkdir, readFile, realpath, writeFile } from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { parseActivePointer } from '../src/release-slot.mjs';
|
|
8
|
+
import { loadPowerShellDataFile, runSlotUpdateCli, verifySlotUpdateEnvelope } from '../src/runtime-update.mjs';
|
|
9
|
+
|
|
10
|
+
const HEX64=/^[0-9a-f]{64}$/;
|
|
11
|
+
const RECEIPT_ID=/^r27-[A-Za-z0-9-]+$/;
|
|
12
|
+
const here=path.dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const packageRoot=path.resolve(here,'..');
|
|
14
|
+
const stateRoot=path.resolve(process.env.DEADBYTE_STATE_ROOT||path.join(os.homedir(),'.deadbyte-mcp'));
|
|
15
|
+
const evidenceRoot=path.join(stateRoot,'evidence','deferred-slot-operations');
|
|
16
|
+
const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
17
|
+
const atomicJson=async(file,value)=>{
|
|
18
|
+
await mkdir(path.dirname(file),{recursive:true});
|
|
19
|
+
const temp=`${file}.${process.pid}.${randomBytes(4).toString('hex')}.tmp`;
|
|
20
|
+
await writeFile(temp,`${JSON.stringify(value,null,2)}\n`,{flag:'wx'});
|
|
21
|
+
await import('node:fs/promises').then(fs=>fs.rename(temp,file));
|
|
22
|
+
};
|
|
23
|
+
function activationArgs(manifestSha){
|
|
24
|
+
if(!HEX64.test(manifestSha??'')) throw new Error('activate requires one lowercase manifest SHA-256');
|
|
25
|
+
return ['--stage',packageRoot,'--development-root',packageRoot,'--expected-version','0.14.1',
|
|
26
|
+
'--expected-manifest',manifestSha,'--process-policy',path.join(packageRoot,'controller','deadbyte-process-policy.json'),
|
|
27
|
+
'--process-policy-sha256',null,'--desktop-policy',path.join(packageRoot,'controller','deadbyte-desktop-policy.json'),
|
|
28
|
+
'--desktop-policy-sha256',null,'--semantic-lsp-config',path.join(packageRoot,'controller','deadbyte-semantic-lsp-config.json'),
|
|
29
|
+
'--semantic-lsp-config-sha256',null,'--enable-machine-fs','--enable-observation','--enable-desktop','--enable-autonomous-supervisor'];
|
|
30
|
+
}
|
|
31
|
+
async function bridgeBootstrapArgs(explicitBridgeRoot=null,explicitBridgeSha256=null){
|
|
32
|
+
const hasRoot=typeof explicitBridgeRoot==='string'&&explicitBridgeRoot.length>0;
|
|
33
|
+
const hasSha=typeof explicitBridgeSha256==='string'&&explicitBridgeSha256.length>0;
|
|
34
|
+
if(hasRoot!==hasSha) throw new Error('bridge override requires exact root + SHA pair');
|
|
35
|
+
let bridgeRootRaw,expectedSha256=null;
|
|
36
|
+
if(hasRoot){
|
|
37
|
+
if(!path.isAbsolute(explicitBridgeRoot)||!HEX64.test(explicitBridgeSha256)) throw new Error('bridge override requires exact root + SHA pair');
|
|
38
|
+
bridgeRootRaw=explicitBridgeRoot;expectedSha256=explicitBridgeSha256;
|
|
39
|
+
}else{
|
|
40
|
+
const pointer=parseActivePointer(await readFile(path.join(stateRoot,'active-release.json'),'utf8'));
|
|
41
|
+
const config=await loadPowerShellDataFile(pointer.config_path);
|
|
42
|
+
bridgeRootRaw=config?.Bridge?.WorkingDirectory;
|
|
43
|
+
if(typeof bridgeRootRaw!=='string'||!path.isAbsolute(bridgeRootRaw)) throw new Error('active controller Bridge.WorkingDirectory must be absolute');
|
|
44
|
+
}
|
|
45
|
+
const bridgeRoot=await realpath(path.resolve(bridgeRootRaw));
|
|
46
|
+
const packageFile=path.join(bridgeRoot,'package.json');
|
|
47
|
+
const bridgeScript=path.join(bridgeRoot,'src','bridge.mjs');
|
|
48
|
+
const pkg=JSON.parse(await readFile(packageFile,'utf8'));
|
|
49
|
+
if(pkg?.name!=='deadbyte-chatgpt-bridge') throw new Error('active Bridge package identity mismatch');
|
|
50
|
+
const scriptSha256=sha256(await readFile(bridgeScript));
|
|
51
|
+
if(expectedSha256&&scriptSha256!==expectedSha256) throw new Error('bridge override SHA-256 mismatch');
|
|
52
|
+
return ['--bridge-root',bridgeRoot,'--bridge-script-sha256',scriptSha256];
|
|
53
|
+
}
|
|
54
|
+
async function rollbackArgs(receiptPath){
|
|
55
|
+
const resolved=await realpath(path.resolve(receiptPath));
|
|
56
|
+
const allowed=path.join(stateRoot,'evidence','updates')+path.sep;
|
|
57
|
+
if(!resolved.startsWith(allowed)||path.basename(resolved).toLowerCase()!=='receipt.json'||!RECEIPT_ID.test(path.basename(path.dirname(resolved)))) {
|
|
58
|
+
throw new Error('rollback receipt must be one signed activation receipt under the update evidence store');
|
|
59
|
+
}
|
|
60
|
+
const envelope=JSON.parse(await readFile(resolved,'utf8'));
|
|
61
|
+
const publicKey=createPublicKey(await readFile(path.join(stateRoot,'trust','ed25519-public.pem')));
|
|
62
|
+
if(!verifySlotUpdateEnvelope(envelope,publicKey)||envelope.body?.rollback_performed!==false) throw new Error('rollback activation receipt verification failed');
|
|
63
|
+
const pointer=parseActivePointer(await readFile(path.join(stateRoot,'active-release.json'),'utf8'));
|
|
64
|
+
if(pointer.release_id!==envelope.body?.active_pointer?.release_id||pointer.generation_root!==envelope.body?.active_pointer?.generation_root) {
|
|
65
|
+
throw new Error('rollback receipt does not identify the active release generation');
|
|
66
|
+
}
|
|
67
|
+
return ['--rollback-receipt',resolved];
|
|
68
|
+
}
|
|
69
|
+
async function normalizedArgs(mode,value,{explicitBridgeRoot=null,explicitBridgeSha256=null}={}){
|
|
70
|
+
if(mode==='activate'){
|
|
71
|
+
const args=activationArgs(value);
|
|
72
|
+
args[args.indexOf('--process-policy-sha256')+1]=sha256(await readFile(path.join(packageRoot,'controller','deadbyte-process-policy.json')));
|
|
73
|
+
args[args.indexOf('--desktop-policy-sha256')+1]=sha256(await readFile(path.join(packageRoot,'controller','deadbyte-desktop-policy.json')));
|
|
74
|
+
args[args.indexOf('--semantic-lsp-config-sha256')+1]=sha256(await readFile(path.join(packageRoot,'controller','deadbyte-semantic-lsp-config.json')));
|
|
75
|
+
args.push(...await bridgeBootstrapArgs(explicitBridgeRoot,explicitBridgeSha256));
|
|
76
|
+
return args;
|
|
77
|
+
}
|
|
78
|
+
if(mode==='rollback'){
|
|
79
|
+
if(explicitBridgeRoot||explicitBridgeSha256) throw new Error('rollback does not accept bridge override');
|
|
80
|
+
return rollbackArgs(value);
|
|
81
|
+
}
|
|
82
|
+
throw new Error("operation must be exactly 'activate' or 'rollback'");
|
|
83
|
+
}
|
|
84
|
+
const rawArgs=process.argv.slice(2);
|
|
85
|
+
const mode=rawArgs[0],value=rawArgs[1];
|
|
86
|
+
if(!value||!['activate','rollback'].includes(mode)) throw new Error('usage: deferred-slot-operation-r43.mjs <activate manifest_sha256|rollback activation_receipt> [--bridge-root ABS --bridge-script-sha256 HEX64]');
|
|
87
|
+
let cursor=2,explicitBridgeRoot=null,explicitBridgeSha256=null;
|
|
88
|
+
if(rawArgs[cursor]==='--bridge-root'){
|
|
89
|
+
explicitBridgeRoot=rawArgs[cursor+1]??null;
|
|
90
|
+
if(rawArgs[cursor+2]!=='--bridge-script-sha256') throw new Error('bridge override requires exact root + SHA pair');
|
|
91
|
+
explicitBridgeSha256=rawArgs[cursor+3]??null;cursor+=4;
|
|
92
|
+
}
|
|
93
|
+
let workerFlag=null,operationIdArg=null;
|
|
94
|
+
if(rawArgs[cursor]==='--worker'){workerFlag='--worker';operationIdArg=rawArgs[cursor+1]??null;cursor+=2;}
|
|
95
|
+
if(cursor!==rawArgs.length) throw new Error('deferred slot operation arguments invalid');
|
|
96
|
+
if((explicitBridgeRoot===null)!==(explicitBridgeSha256===null)) throw new Error('bridge override requires exact root + SHA pair');
|
|
97
|
+
if(mode==='rollback'&&(explicitBridgeRoot||explicitBridgeSha256)) throw new Error('rollback does not accept bridge override');
|
|
98
|
+
if(workerFlag==='--worker'){
|
|
99
|
+
if(!/^[0-9a-f]{32}$/.test(operationIdArg??'')) throw new Error('deferred worker operation id invalid');
|
|
100
|
+
const statePath=path.join(evidenceRoot,`${operationIdArg}.json`);
|
|
101
|
+
await new Promise(resolve=>setTimeout(resolve,4000));
|
|
102
|
+
await atomicJson(statePath,{schema:'deadbyte.deferred-slot-operation.v1',operation_id:operationIdArg,mode,state:'running',started_at_utc:new Date().toISOString(),bridge_root:explicitBridgeRoot,bridge_script_sha256:explicitBridgeSha256});
|
|
103
|
+
try{
|
|
104
|
+
const args=await normalizedArgs(mode,value,{explicitBridgeRoot,explicitBridgeSha256});
|
|
105
|
+
const result=await runSlotUpdateCli(args,{stateRoot});
|
|
106
|
+
await atomicJson(statePath,{schema:'deadbyte.deferred-slot-operation.v1',operation_id:operationIdArg,mode,state:'completed',
|
|
107
|
+
completed_at_utc:new Date().toISOString(),receipt_path:result.receipt_path,receipt_sha256:result.receipt_sha256,
|
|
108
|
+
active_release:result.pointer.release_id,generation_root:result.pointer.generation_root,bridge_root:explicitBridgeRoot,bridge_script_sha256:explicitBridgeSha256});
|
|
109
|
+
}catch(error){
|
|
110
|
+
await atomicJson(statePath,{schema:'deadbyte.deferred-slot-operation.v1',operation_id:operationIdArg,mode,state:'failed',
|
|
111
|
+
completed_at_utc:new Date().toISOString(),error:String(error?.message??error),bridge_root:explicitBridgeRoot,bridge_script_sha256:explicitBridgeSha256});
|
|
112
|
+
process.exitCode=1;
|
|
113
|
+
}
|
|
114
|
+
}else{
|
|
115
|
+
const operationId=randomBytes(16).toString('hex');
|
|
116
|
+
const statePath=path.join(evidenceRoot,`${operationId}.json`);
|
|
117
|
+
await atomicJson(statePath,{schema:'deadbyte.deferred-slot-operation.v1',operation_id:operationId,mode,state:'scheduled',scheduled_at_utc:new Date().toISOString(),bridge_root:explicitBridgeRoot,bridge_script_sha256:explicitBridgeSha256});
|
|
118
|
+
const workerArgs=[fileURLToPath(import.meta.url),mode,value];
|
|
119
|
+
if(explicitBridgeRoot) workerArgs.push('--bridge-root',explicitBridgeRoot,'--bridge-script-sha256',explicitBridgeSha256);
|
|
120
|
+
workerArgs.push('--worker',operationId);
|
|
121
|
+
const child=spawn(process.execPath,workerArgs,{
|
|
122
|
+
cwd:packageRoot,detached:true,stdio:'ignore',windowsHide:true,env:{...process.env,DEADBYTE_STATE_ROOT:stateRoot}
|
|
123
|
+
});
|
|
124
|
+
child.unref();
|
|
125
|
+
console.log(JSON.stringify({status:'scheduled',operation_id:operationId,mode,state_path:statePath,execution_provider:'deadbyte_mcp',rdc_operation_count:0,bridge_root:explicitBridgeRoot,bridge_script_sha256:explicitBridgeSha256}));
|
|
126
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { createHash, createPublicKey, randomBytes } from 'node:crypto';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import { mkdir, readFile, realpath, writeFile } from 'node:fs/promises';
|
|
4
|
+
import os from 'node:os';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
import { parseActivePointer } from '../src/release-slot.mjs';
|
|
8
|
+
import { loadPowerShellDataFile, runSlotUpdateCli, verifySlotUpdateEnvelope } from '../src/runtime-update.mjs';
|
|
9
|
+
|
|
10
|
+
const HEX64=/^[0-9a-f]{64}$/;
|
|
11
|
+
const RECEIPT_ID=/^r27-[A-Za-z0-9-]+$/;
|
|
12
|
+
const here=path.dirname(fileURLToPath(import.meta.url));
|
|
13
|
+
const packageRoot=path.resolve(here,'..');
|
|
14
|
+
const stateRoot=path.resolve(process.env.DEADBYTE_STATE_ROOT||path.join(os.homedir(),'.deadbyte-mcp'));
|
|
15
|
+
const evidenceRoot=path.join(stateRoot,'evidence','deferred-slot-operations');
|
|
16
|
+
const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
17
|
+
const atomicJson=async(file,value)=>{
|
|
18
|
+
await mkdir(path.dirname(file),{recursive:true});
|
|
19
|
+
const temp=`${file}.${process.pid}.${randomBytes(4).toString('hex')}.tmp`;
|
|
20
|
+
await writeFile(temp,`${JSON.stringify(value,null,2)}\n`,{flag:'wx'});
|
|
21
|
+
await import('node:fs/promises').then(fs=>fs.rename(temp,file));
|
|
22
|
+
};
|
|
23
|
+
function activationArgs(manifestSha){
|
|
24
|
+
if(!HEX64.test(manifestSha??'')) throw new Error('activate requires one lowercase manifest SHA-256');
|
|
25
|
+
return ['--stage',packageRoot,'--development-root',packageRoot,'--expected-version','0.15.0',
|
|
26
|
+
'--expected-manifest',manifestSha,'--process-policy',path.join(packageRoot,'controller','deadbyte-process-policy.json'),
|
|
27
|
+
'--process-policy-sha256',null,'--desktop-policy',path.join(packageRoot,'controller','deadbyte-desktop-policy.json'),
|
|
28
|
+
'--desktop-policy-sha256',null,'--semantic-lsp-config',path.join(packageRoot,'controller','deadbyte-semantic-lsp-config.json'),
|
|
29
|
+
'--semantic-lsp-config-sha256',null,'--enable-machine-fs','--enable-observation','--enable-desktop','--enable-autonomous-supervisor'];
|
|
30
|
+
}
|
|
31
|
+
async function bridgeBootstrapArgs(explicitBridgeRoot=null,explicitBridgeSha256=null){
|
|
32
|
+
const hasRoot=typeof explicitBridgeRoot==='string'&&explicitBridgeRoot.length>0;
|
|
33
|
+
const hasSha=typeof explicitBridgeSha256==='string'&&explicitBridgeSha256.length>0;
|
|
34
|
+
if(hasRoot!==hasSha) throw new Error('bridge override requires exact root + SHA pair');
|
|
35
|
+
let bridgeRootRaw,expectedSha256=null;
|
|
36
|
+
if(hasRoot){
|
|
37
|
+
if(!path.isAbsolute(explicitBridgeRoot)||!HEX64.test(explicitBridgeSha256)) throw new Error('bridge override requires exact root + SHA pair');
|
|
38
|
+
bridgeRootRaw=explicitBridgeRoot;expectedSha256=explicitBridgeSha256;
|
|
39
|
+
}else{
|
|
40
|
+
const pointer=parseActivePointer(await readFile(path.join(stateRoot,'active-release.json'),'utf8'));
|
|
41
|
+
const config=await loadPowerShellDataFile(pointer.config_path);
|
|
42
|
+
bridgeRootRaw=config?.Bridge?.WorkingDirectory;
|
|
43
|
+
if(typeof bridgeRootRaw!=='string'||!path.isAbsolute(bridgeRootRaw)) throw new Error('active controller Bridge.WorkingDirectory must be absolute');
|
|
44
|
+
}
|
|
45
|
+
const bridgeRoot=await realpath(path.resolve(bridgeRootRaw));
|
|
46
|
+
const packageFile=path.join(bridgeRoot,'package.json');
|
|
47
|
+
const bridgeScript=path.join(bridgeRoot,'src','bridge.mjs');
|
|
48
|
+
const pkg=JSON.parse(await readFile(packageFile,'utf8'));
|
|
49
|
+
if(pkg?.name!=='deadbyte-chatgpt-bridge') throw new Error('active Bridge package identity mismatch');
|
|
50
|
+
const scriptSha256=sha256(await readFile(bridgeScript));
|
|
51
|
+
if(expectedSha256&&scriptSha256!==expectedSha256) throw new Error('bridge override SHA-256 mismatch');
|
|
52
|
+
return ['--bridge-root',bridgeRoot,'--bridge-script-sha256',scriptSha256];
|
|
53
|
+
}
|
|
54
|
+
async function rollbackArgs(receiptPath){
|
|
55
|
+
const resolved=await realpath(path.resolve(receiptPath));
|
|
56
|
+
const allowed=path.join(stateRoot,'evidence','updates')+path.sep;
|
|
57
|
+
if(!resolved.startsWith(allowed)||path.basename(resolved).toLowerCase()!=='receipt.json'||!RECEIPT_ID.test(path.basename(path.dirname(resolved)))) {
|
|
58
|
+
throw new Error('rollback receipt must be one signed activation receipt under the update evidence store');
|
|
59
|
+
}
|
|
60
|
+
const envelope=JSON.parse(await readFile(resolved,'utf8'));
|
|
61
|
+
const publicKey=createPublicKey(await readFile(path.join(stateRoot,'trust','ed25519-public.pem')));
|
|
62
|
+
if(!verifySlotUpdateEnvelope(envelope,publicKey)||envelope.body?.rollback_performed!==false) throw new Error('rollback activation receipt verification failed');
|
|
63
|
+
const pointer=parseActivePointer(await readFile(path.join(stateRoot,'active-release.json'),'utf8'));
|
|
64
|
+
if(pointer.release_id!==envelope.body?.active_pointer?.release_id||pointer.generation_root!==envelope.body?.active_pointer?.generation_root) {
|
|
65
|
+
throw new Error('rollback receipt does not identify the active release generation');
|
|
66
|
+
}
|
|
67
|
+
return ['--rollback-receipt',resolved];
|
|
68
|
+
}
|
|
69
|
+
async function normalizedArgs(mode,value,{explicitBridgeRoot=null,explicitBridgeSha256=null}={}){
|
|
70
|
+
if(mode==='activate'){
|
|
71
|
+
const args=activationArgs(value);
|
|
72
|
+
args[args.indexOf('--process-policy-sha256')+1]=sha256(await readFile(path.join(packageRoot,'controller','deadbyte-process-policy.json')));
|
|
73
|
+
args[args.indexOf('--desktop-policy-sha256')+1]=sha256(await readFile(path.join(packageRoot,'controller','deadbyte-desktop-policy.json')));
|
|
74
|
+
args[args.indexOf('--semantic-lsp-config-sha256')+1]=sha256(await readFile(path.join(packageRoot,'controller','deadbyte-semantic-lsp-config.json')));
|
|
75
|
+
args.push(...await bridgeBootstrapArgs(explicitBridgeRoot,explicitBridgeSha256));
|
|
76
|
+
return args;
|
|
77
|
+
}
|
|
78
|
+
if(mode==='rollback'){
|
|
79
|
+
if(explicitBridgeRoot||explicitBridgeSha256) throw new Error('rollback does not accept bridge override');
|
|
80
|
+
return rollbackArgs(value);
|
|
81
|
+
}
|
|
82
|
+
throw new Error("operation must be exactly 'activate' or 'rollback'");
|
|
83
|
+
}
|
|
84
|
+
const rawArgs=process.argv.slice(2);
|
|
85
|
+
const mode=rawArgs[0],value=rawArgs[1];
|
|
86
|
+
if(!value||!['activate','rollback'].includes(mode)) throw new Error('usage: deferred-slot-operation-r44.mjs <activate manifest_sha256|rollback activation_receipt> [--bridge-root ABS --bridge-script-sha256 HEX64]');
|
|
87
|
+
let cursor=2,explicitBridgeRoot=null,explicitBridgeSha256=null;
|
|
88
|
+
if(rawArgs[cursor]==='--bridge-root'){
|
|
89
|
+
explicitBridgeRoot=rawArgs[cursor+1]??null;
|
|
90
|
+
if(rawArgs[cursor+2]!=='--bridge-script-sha256') throw new Error('bridge override requires exact root + SHA pair');
|
|
91
|
+
explicitBridgeSha256=rawArgs[cursor+3]??null;cursor+=4;
|
|
92
|
+
}
|
|
93
|
+
let workerFlag=null,operationIdArg=null;
|
|
94
|
+
if(rawArgs[cursor]==='--worker'){workerFlag='--worker';operationIdArg=rawArgs[cursor+1]??null;cursor+=2;}
|
|
95
|
+
if(cursor!==rawArgs.length) throw new Error('deferred slot operation arguments invalid');
|
|
96
|
+
if((explicitBridgeRoot===null)!==(explicitBridgeSha256===null)) throw new Error('bridge override requires exact root + SHA pair');
|
|
97
|
+
if(mode==='rollback'&&(explicitBridgeRoot||explicitBridgeSha256)) throw new Error('rollback does not accept bridge override');
|
|
98
|
+
if(workerFlag==='--worker'){
|
|
99
|
+
if(!/^[0-9a-f]{32}$/.test(operationIdArg??'')) throw new Error('deferred worker operation id invalid');
|
|
100
|
+
const statePath=path.join(evidenceRoot,`${operationIdArg}.json`);
|
|
101
|
+
await new Promise(resolve=>setTimeout(resolve,4000));
|
|
102
|
+
await atomicJson(statePath,{schema:'deadbyte.deferred-slot-operation.v1',operation_id:operationIdArg,mode,state:'running',started_at_utc:new Date().toISOString(),bridge_root:explicitBridgeRoot,bridge_script_sha256:explicitBridgeSha256});
|
|
103
|
+
try{
|
|
104
|
+
const args=await normalizedArgs(mode,value,{explicitBridgeRoot,explicitBridgeSha256});
|
|
105
|
+
const result=await runSlotUpdateCli(args,{stateRoot});
|
|
106
|
+
await atomicJson(statePath,{schema:'deadbyte.deferred-slot-operation.v1',operation_id:operationIdArg,mode,state:'completed',
|
|
107
|
+
completed_at_utc:new Date().toISOString(),receipt_path:result.receipt_path,receipt_sha256:result.receipt_sha256,
|
|
108
|
+
active_release:result.pointer.release_id,generation_root:result.pointer.generation_root,bridge_root:explicitBridgeRoot,bridge_script_sha256:explicitBridgeSha256});
|
|
109
|
+
}catch(error){
|
|
110
|
+
await atomicJson(statePath,{schema:'deadbyte.deferred-slot-operation.v1',operation_id:operationIdArg,mode,state:'failed',
|
|
111
|
+
completed_at_utc:new Date().toISOString(),error:String(error?.message??error),bridge_root:explicitBridgeRoot,bridge_script_sha256:explicitBridgeSha256});
|
|
112
|
+
process.exitCode=1;
|
|
113
|
+
}
|
|
114
|
+
}else{
|
|
115
|
+
const operationId=randomBytes(16).toString('hex');
|
|
116
|
+
const statePath=path.join(evidenceRoot,`${operationId}.json`);
|
|
117
|
+
await atomicJson(statePath,{schema:'deadbyte.deferred-slot-operation.v1',operation_id:operationId,mode,state:'scheduled',scheduled_at_utc:new Date().toISOString(),bridge_root:explicitBridgeRoot,bridge_script_sha256:explicitBridgeSha256});
|
|
118
|
+
const workerArgs=[fileURLToPath(import.meta.url),mode,value];
|
|
119
|
+
if(explicitBridgeRoot) workerArgs.push('--bridge-root',explicitBridgeRoot,'--bridge-script-sha256',explicitBridgeSha256);
|
|
120
|
+
workerArgs.push('--worker',operationId);
|
|
121
|
+
const child=spawn(process.execPath,workerArgs,{
|
|
122
|
+
cwd:packageRoot,detached:true,stdio:'ignore',windowsHide:true,env:{...process.env,DEADBYTE_STATE_ROOT:stateRoot}
|
|
123
|
+
});
|
|
124
|
+
child.unref();
|
|
125
|
+
console.log(JSON.stringify({status:'scheduled',operation_id:operationId,mode,state_path:statePath,execution_provider:'deadbyte_mcp',rdc_operation_count:0,bridge_root:explicitBridgeRoot,bridge_script_sha256:explicitBridgeSha256}));
|
|
126
|
+
}
|