deadbyte-mcp 0.11.3 → 0.13.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.
Files changed (127) hide show
  1. package/MANIFEST.SHA256 +126 -54
  2. package/R41-PARENT.json +15 -0
  3. package/README.txt +5 -4
  4. package/acceptance/r40/desktop-live-drift.mjs +106 -0
  5. package/acceptance/r40/desktop-live-ground.mjs +110 -0
  6. package/acceptance/r40/desktop-live-input.mjs +128 -0
  7. package/acceptance/r40/desktop-live-observe.mjs +100 -0
  8. package/acceptance/r40/desktop-live-uia.mjs +121 -0
  9. package/bin/appcontainer-stage.obj +0 -0
  10. package/bin/bootstrap-advapi32.obj +0 -0
  11. package/bin/bootstrap-exitcode.obj +0 -0
  12. package/bin/bootstrap-kernel32.obj +0 -0
  13. package/bin/child-control-probe.obj +0 -0
  14. package/bin/child-control-stage.obj +0 -0
  15. package/bin/contained-reverse-worker.obj +0 -0
  16. package/bin/contained-transform-worker.obj +0 -0
  17. package/bin/containment-probe.obj +0 -0
  18. package/bin/deadbyte-contain.obj +0 -0
  19. package/bin/deadbyte-desktop-input-r40.exe +0 -0
  20. package/bin/deadbyte-desktop-input-r40.obj +0 -0
  21. package/bin/deadbyte-desktop-observer-r40.exe +0 -0
  22. package/bin/deadbyte-desktop-observer-r40.obj +0 -0
  23. package/bin/deadbyte-desktop-uia-r40.exe +0 -0
  24. package/bin/deadbyte-desktop-uia-r40.obj +0 -0
  25. package/bin/deadbyte-exec.obj +0 -0
  26. package/bin/deadbyte-process-host.obj +0 -0
  27. package/bin/deadbyte-tunnel-host.obj +0 -0
  28. package/controller/README.TXT +7 -5
  29. package/controller/deadbyte-controller.config.psd1.example +3 -0
  30. package/controller/deadbyte-controller.ps1 +149 -4
  31. package/controller/deadbyte-desktop-policy.json +41 -0
  32. package/controller/deadbyte-process-policy.json +4 -4
  33. package/docs/ARCHITECTURE.md +6 -1
  34. package/docs/superpowers/specs/2026-09-19-r40-desktop-computer-use-design.md +214 -0
  35. package/docs/superpowers/specs/2026-09-20-r41-deterministic-memory-design.md +132 -0
  36. package/native/deadbyte-desktop-input.cpp +455 -0
  37. package/native/deadbyte-desktop-observer.cpp +253 -0
  38. package/native/deadbyte-desktop-uia.cpp +307 -0
  39. package/package.json +12 -8
  40. package/proof/CONTAINMENT-BUILD.txt +6 -6
  41. package/scripts/build-containment.ps1 +24 -14
  42. package/scripts/build-desktop-r40.ps1 +112 -0
  43. package/scripts/deferred-slot-operation-r40.mjs +126 -0
  44. package/scripts/deferred-slot-operation-r41.mjs +127 -0
  45. package/scripts/final-closure-r40.mjs +114 -0
  46. package/scripts/final-closure-r41.mjs +116 -0
  47. package/scripts/final-closure-verify-r40.mjs +212 -0
  48. package/scripts/final-closure-verify-r41.mjs +215 -0
  49. package/scripts/gate-windows-r40.ps1 +43 -0
  50. package/scripts/gate-windows-r41.ps1 +48 -0
  51. package/scripts/init-desktop-policy-r40.ps1 +85 -0
  52. package/scripts/r40-compact-ledger-probe.mjs +4 -0
  53. package/scripts/release-parity-r40.mjs +212 -0
  54. package/scripts/release-parity-r41.mjs +221 -0
  55. package/scripts/release-parity-tests-r40.ps1 +9 -0
  56. package/scripts/release-parity-tests-r41.ps1 +9 -0
  57. package/scripts/verify-memory-r41.mjs +88 -0
  58. package/scripts/verify-r41-parent.mjs +61 -0
  59. package/scripts/windows-gate-evidence-r40.mjs +52 -0
  60. package/scripts/windows-gate-evidence-r41.mjs +53 -0
  61. package/src/autonomous-context-engine.mjs +3 -1
  62. package/src/autonomous-planner-contracts.mjs +19 -1
  63. package/src/autonomous-planner.mjs +24 -0
  64. package/src/autonomous-runtime.mjs +164 -25
  65. package/src/capability-ledger.mjs +6 -1
  66. package/src/compact-gateway-mcp-tools.mjs +14 -2
  67. package/src/deadbyte-cli.mjs +72 -44
  68. package/src/desktop-contract.mjs +263 -0
  69. package/src/desktop-input-r40.mjs +148 -0
  70. package/src/desktop-mcp-tools-r40.mjs +126 -0
  71. package/src/desktop-memory-r40.mjs +272 -0
  72. package/src/desktop-observer-r40.mjs +231 -0
  73. package/src/desktop-policy-r40.mjs +110 -0
  74. package/src/desktop-runtime-r40.mjs +318 -0
  75. package/src/desktop-uia-r40.mjs +123 -0
  76. package/src/mcp-server.mjs +87 -19
  77. package/src/memory-r41.mjs +692 -0
  78. package/src/r40-compact-disarmed-probe.mjs +71 -0
  79. package/src/r40-full-surface-probe.mjs +34 -0
  80. package/src/release-generation.mjs +38 -5
  81. package/src/remote-console.mjs +41 -0
  82. package/src/remote-live-log.mjs +208 -45
  83. package/src/remote-mcp-desktop-r40-smoke-client.mjs +70 -0
  84. package/src/remote-mcp-r40-parity-client.mjs +200 -0
  85. package/src/remote-mcp-smoke-client.mjs +20 -6
  86. package/src/remote-result-journal.mjs +10 -2
  87. package/src/runtime-update.mjs +55 -17
  88. package/src/tool-audit.mjs +29 -2
  89. package/src/version.mjs +1 -1
  90. package/test/autonomous-capability-r36.test.mjs +43 -1
  91. package/test/autonomous-desktop-r40.test.mjs +188 -0
  92. package/test/capability-ledger-r36.test.mjs +1 -0
  93. package/test/cli-entrypoint.test.mjs +1 -1
  94. package/test/compact-catalog-r36.test.mjs +2 -2
  95. package/test/compact-gateway-r36.test.mjs +56 -4
  96. package/test/compact-max-catalog-r40.test.mjs +95 -0
  97. package/test/controller-desktop-r40.test.mjs +86 -0
  98. package/test/core.test.mjs +1 -1
  99. package/test/desktop-adversarial-r40.test.mjs +62 -0
  100. package/test/desktop-contract-r40.test.mjs +200 -0
  101. package/test/desktop-input-r40.test.mjs +63 -0
  102. package/test/desktop-mcp-tools-r40.test.mjs +61 -0
  103. package/test/desktop-memory-r40.test.mjs +141 -0
  104. package/test/desktop-observer-r40.test.mjs +119 -0
  105. package/test/desktop-policy-r40.test.mjs +111 -0
  106. package/test/desktop-runtime-r40.test.mjs +278 -0
  107. package/test/desktop-uia-r40.test.mjs +42 -0
  108. package/test/full-max-catalog-r40.test.mjs +91 -0
  109. package/test/helpers/autonomous-r34-fixture.mjs +3 -3
  110. package/test/memory-autonomous-integration-r41.test.mjs +31 -0
  111. package/test/memory-history-r41.test.mjs +126 -0
  112. package/test/memory-projections-r41.test.mjs +92 -0
  113. package/test/memory-retrieval-r41.test.mjs +124 -0
  114. package/test/memory-snapshot-r41.test.mjs +106 -0
  115. package/test/r33-closeout-regression.test.mjs +7 -7
  116. package/test/r33-finalization.test.mjs +15 -15
  117. package/test/r37-remote-tool-call-timeline.test.mjs +6 -5
  118. package/test/r40-finalization.test.mjs +118 -0
  119. package/test/r41-finalization.test.mjs +38 -0
  120. package/test/release-generation.test.mjs +41 -9
  121. package/test/release-version.test.mjs +20 -61
  122. package/test/remote-console-r40.test.mjs +38 -0
  123. package/test/remote-live-log-r37.test.mjs +89 -32
  124. package/test/remote-r24-catalog.test.mjs +12 -3
  125. package/test/remote-result-journal.test.mjs +15 -0
  126. package/test/remote-session-cli.test.mjs +69 -46
  127. package/test/runtime-self-update.test.mjs +44 -0
@@ -0,0 +1,123 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { spawn } from 'node:child_process';
3
+ import { readFile } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+
6
+ export const DESKTOP_UIA_GROUND_SCHEMA='deadbyte.desktop-uia-ground.v1';
7
+ const HEX64=/^[0-9a-f]{64}$/;
8
+ const HWND=/^0x[0-9a-f]{1,16}$/;
9
+ const QUERY_KINDS=new Set(['root','name_exact','name_contains','automation_id_exact','control_type']);
10
+ const sha256Bytes=value=>createHash('sha256').update(value).digest('hex');
11
+
12
+ function insist(c,m){if(!c)throw new Error(m);}
13
+ function integer(v,label,{min=Number.MIN_SAFE_INTEGER,max=Number.MAX_SAFE_INTEGER}={}){
14
+ insist(Number.isSafeInteger(v)&&v>=min&&v<=max,label+' invalid');return v;
15
+ }
16
+ function hwnd(v){const s=String(v??'').toLowerCase();insist(HWND.test(s),'desktop UIA hwnd invalid');return s;}
17
+ function queryInput(query){
18
+ insist(query&&typeof query==='object'&&!Array.isArray(query),'desktop UIA query invalid');
19
+ const kind=String(query.kind??'');
20
+ insist(QUERY_KINDS.has(kind),'desktop UIA query kind invalid');
21
+ const value=query.value??'';
22
+ insist(typeof value==='string'&&!value.includes('\0'),'desktop UIA query value invalid');
23
+ const bytes=Buffer.from(value,'utf8');
24
+ if(kind==='root') insist(bytes.length===0,'desktop UIA root query cannot carry value');
25
+ else insist(bytes.length>=1&&bytes.length<=512,'desktop UIA query value bytes invalid');
26
+ const maxResults=integer(query.max_results??8,'desktop UIA max_results',{min:1,max:16});
27
+ const ordinal=integer(query.ordinal??0,'desktop UIA ordinal',{min:0,max:maxResults-1});
28
+ const querySha256=sha256Bytes(Buffer.from(JSON.stringify({kind,value,max_results:maxResults,ordinal}),'utf8'));
29
+ return {kind,value,bytes,maxResults,ordinal,querySha256};
30
+ }
31
+
32
+ export function serializeDesktopUiaRequest({expectedWindow,query}={}){
33
+ insist(expectedWindow&&typeof expectedWindow==='object','desktop UIA expected window missing');
34
+ const expectedHwnd=hwnd(expectedWindow.hwnd);
35
+ const expectedPid=integer(expectedWindow.pid,'desktop UIA expected pid',{min:1,max:0x7fffffff});
36
+ const q=queryInput(query);
37
+ const header=Buffer.from([
38
+ 'DEADBYTE_DESKTOP_UIA_V1',
39
+ 'expected_hwnd='+expectedHwnd,
40
+ 'expected_pid='+expectedPid,
41
+ 'query_kind='+q.kind,
42
+ 'max_results='+q.maxResults,
43
+ 'query_bytes='+q.bytes.length,
44
+ ''
45
+ ].join('\n'),'utf8');
46
+ const request=Buffer.concat([header,q.bytes]);
47
+ insist(request.length<=8192,'desktop UIA request exceeds bound');
48
+ return {request,query:q};
49
+ }
50
+
51
+ export function parseDesktopUiaResponse(bytes,{expectedWindow,query,expectedBounds}={}){
52
+ insist(Buffer.isBuffer(bytes)&&bytes.length>=2&&bytes.length<=256*1024,'desktop UIA response invalid');
53
+ let raw;try{raw=JSON.parse(bytes.toString('utf8').trim());}catch{throw new Error('desktop UIA response JSON invalid');}
54
+ insist(raw?.schema===DESKTOP_UIA_GROUND_SCHEMA,'desktop UIA response schema mismatch');
55
+ const q=queryInput(query);
56
+ insist(String(raw.query_kind)===q.kind,'desktop UIA response query mismatch');
57
+ insist(hwnd(raw.foreground_hwnd)===hwnd(expectedWindow.hwnd),'desktop UIA response hwnd mismatch');
58
+ insist(integer(raw.foreground_pid,'desktop UIA response pid',{min:1,max:0x7fffffff})===expectedWindow.pid,'desktop UIA response pid mismatch');
59
+ integer(raw.visited,'desktop UIA visited',{min:0,max:2048});
60
+ insist(typeof raw.truncated==='boolean','desktop UIA truncated invalid');
61
+ insist(Array.isArray(raw.matches)&&raw.matches.length<=q.maxResults,'desktop UIA matches invalid');
62
+ const left=integer(expectedBounds.left,'desktop UIA bounds left',{min:-131072,max:131072});
63
+ const top=integer(expectedBounds.top,'desktop UIA bounds top',{min:-131072,max:131072});
64
+ const width=integer(expectedBounds.width,'desktop UIA bounds width',{min:1,max:131072});
65
+ const height=integer(expectedBounds.height,'desktop UIA bounds height',{min:1,max:131072});
66
+ const matches=[];
67
+ for(const item of raw.matches){
68
+ const rect={
69
+ left:integer(item.left,'desktop UIA rect left',{min:-131072,max:131072}),
70
+ top:integer(item.top,'desktop UIA rect top',{min:-131072,max:131072}),
71
+ width:integer(item.width,'desktop UIA rect width',{min:1,max:131072}),
72
+ height:integer(item.height,'desktop UIA rect height',{min:1,max:131072})
73
+ };
74
+ const inside=rect.left>=left&&rect.top>=top&&rect.left+rect.width<=left+width&&rect.top+rect.height<=top+height;
75
+ if(!inside) continue;
76
+ matches.push(Object.freeze({
77
+ rect:Object.freeze(rect),
78
+ control_type:integer(item.control_type,'desktop UIA control_type',{min:0,max:100000}),
79
+ enabled:item.enabled===true,offscreen:item.offscreen===true
80
+ }));
81
+ }
82
+ return Object.freeze({
83
+ status:'ok',query_sha256:q.querySha256,query_kind:q.kind,ordinal:q.ordinal,
84
+ visited:raw.visited,truncated:raw.truncated,matches:Object.freeze(matches),
85
+ provider_receipt_sha256:sha256Bytes(bytes)
86
+ });
87
+ }
88
+
89
+ export async function invokeNativeDesktopGrounder({grounderPath,expectedGrounderSha256,timeoutMs=5000,expectedWindow,expectedBounds,query}={}){
90
+ insist(typeof grounderPath==='string'&&path.isAbsolute(grounderPath),'desktop grounderPath must be absolute');
91
+ insist(HEX64.test(expectedGrounderSha256??''),'desktop expectedGrounderSha256 invalid');
92
+ integer(timeoutMs,'desktop UIA timeoutMs',{min:100,max:30000});
93
+ const exe=await readFile(grounderPath);
94
+ insist(exe.length>0&&exe.length<=4*1024*1024,'desktop UIA binary size invalid');
95
+ insist(sha256Bytes(exe)===expectedGrounderSha256,'desktop UIA executable hash mismatch');
96
+ const packed=serializeDesktopUiaRequest({expectedWindow,query});
97
+ return await new Promise((resolve,reject)=>{
98
+ const child=spawn(grounderPath,[],{shell:false,windowsHide:true,stdio:['pipe','pipe','pipe']});
99
+ const stdout=[];let bytes=0,stderr='',done=false,timer=null;
100
+ const finish=(error,value)=>{if(done)return;done=true;if(timer!==null)clearTimeout(timer);error?reject(error):resolve(value);};
101
+ child.stdout.on('data',chunk=>{bytes+=chunk.length;if(bytes>256*1024){try{child.kill('SIGKILL');}catch{};return finish(new Error('desktop UIA stdout exceeds bound'));}stdout.push(Buffer.from(chunk));});
102
+ child.stderr.on('data',chunk=>{stderr+=chunk.toString('utf8');if(Buffer.byteLength(stderr,'utf8')>64*1024){try{child.kill('SIGKILL');}catch{};finish(new Error('desktop UIA stderr exceeds bound'));}});
103
+ child.once('error',error=>finish(error));
104
+ child.once('exit',(code,signal)=>{
105
+ if(code!==0)return finish(new Error('desktop UIA exit='+code+' signal='+(signal??'none')+' stderr='+stderr.slice(-8192)));
106
+ try{finish(null,parseDesktopUiaResponse(Buffer.concat(stdout),{expectedWindow,query,expectedBounds}));}
107
+ catch(error){finish(error);}
108
+ });
109
+ child.stdin.on('error',error=>finish(error));
110
+ child.stdin.end(packed.request);
111
+ timer=setTimeout(()=>{try{child.kill('SIGKILL');}catch{};finish(new Error('desktop UIA timed out after '+timeoutMs+'ms'));},timeoutMs);
112
+ });
113
+ }
114
+
115
+ export function createNativeDesktopGrounder({grounderPath,expectedGrounderSha256,timeoutMs=5000}={}){
116
+ return async({frame,query}={})=>{
117
+ insist(frame?.active_window,'desktop UIA grounding requires foreground window');
118
+ return invokeNativeDesktopGrounder({
119
+ grounderPath,expectedGrounderSha256,timeoutMs,
120
+ expectedWindow:frame.active_window,expectedBounds:frame.bounds,query
121
+ });
122
+ };
123
+ }
@@ -1,3 +1,4 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import { access, readFile } from 'node:fs/promises';
2
3
  import path from 'node:path';
3
4
  import os from 'node:os';
@@ -9,7 +10,7 @@ import { executeProof } from './executor.mjs';
9
10
  import { CONTAINED_TRANSFORM_OPERATIONS, executeContainedTransform } from './contained-executor.mjs';
10
11
  import { resolveExistingInside, resolveWorkspace } from './path-policy.mjs';
11
12
  import { verifyReceipt } from './verifier.mjs';
12
- import { defaultPrivateKeyPath, defaultPublicKeyPath } from './trust.mjs';
13
+ import { defaultPrivateKeyPath, defaultPublicKeyPath, loadPrivateSigningKey, loadPublicVerifyKey } from './trust.mjs';
13
14
  import { DEADBYTE_VERSION } from './version.mjs';
14
15
  import { currentIngressAdapterMode, TUNNEL_STDIO_PROBE_COMPAT_MODE } from './ingress-mode.mjs';
15
16
  import { installTunnelStdioProbeCompat } from './tunnel-stdio-compat.mjs';
@@ -31,6 +32,14 @@ import { createMachineFsRuntime } from './machine-fs.mjs';
31
32
  import { registerMachineFsTools } from './machine-fs-mcp-tools.mjs';
32
33
  import { createObservationRuntime } from './observation-runtime.mjs';
33
34
  import { registerObservationTools } from './observation-mcp-tools.mjs';
35
+ import { loadDesktopPolicy } from './desktop-policy-r40.mjs';
36
+ import { createDesktopObserverRuntime } from './desktop-observer-r40.mjs';
37
+ import { createNativeDesktopInputProvider } from './desktop-input-r40.mjs';
38
+ import { createNativeDesktopGrounder } from './desktop-uia-r40.mjs';
39
+ import { createDesktopRuntime } from './desktop-runtime-r40.mjs';
40
+ import { createDesktopMemoryProvider } from './desktop-memory-r40.mjs';
41
+ import { createR41MemoryProvider } from './memory-r41.mjs';
42
+ import { registerDesktopTools } from './desktop-mcp-tools-r40.mjs';
34
43
  import { loadAutonomousPolicy } from './autonomous-policy.mjs';
35
44
  import { createNativeDiffRuntime } from './native-diff.mjs';
36
45
  import { createAutonomousRuntime } from './autonomous-runtime.mjs';
@@ -54,6 +63,7 @@ import {
54
63
  } from './output-contracts.mjs';
55
64
 
56
65
  const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
66
+ const packageManifestSha256=createHash('sha256').update(await readFile(path.join(packageRoot,'MANIFEST.SHA256'))).digest('hex');
57
67
  const workspaceRoot = path.resolve(process.env.DEADBYTE_WORKSPACE_ROOT ?? path.join(packageRoot, 'workspaces'));
58
68
  const signingKeyPath = process.env.DEADBYTE_SIGNING_KEY ?? defaultPrivateKeyPath();
59
69
  const verifyKeyPath = process.env.DEADBYTE_VERIFY_KEY ?? defaultPublicKeyPath();
@@ -125,6 +135,44 @@ const observationRuntime = observationRuntimeMode === '1'
125
135
  stateRoot: runtimeStateRoot })
126
136
  : null;
127
137
 
138
+ const desktopRuntimeMode=process.env.DEADBYTE_DESKTOP_RUNTIME??'0';
139
+ if(!['0','1'].includes(desktopRuntimeMode)) throw new Error('DEADBYTE_DESKTOP_RUNTIME must be 0 or 1');
140
+ const localDesktopPolicyPath=path.join(packageRoot,'controller','deadbyte-desktop-policy.json');
141
+ let desktopPolicyPath=process.env.DEADBYTE_DESKTOP_POLICY??'';
142
+ if(desktopRuntimeMode==='1'&&!desktopPolicyPath){
143
+ try{await access(localDesktopPolicyPath);desktopPolicyPath=localDesktopPolicyPath;}
144
+ catch(error){if(error?.code!=='ENOENT')throw error;}
145
+ }
146
+ if(desktopRuntimeMode==='1'&&!desktopPolicyPath) throw new Error('DEADBYTE_DESKTOP_RUNTIME=1 requires a desktop policy');
147
+ const desktopPolicy=desktopRuntimeMode==='1'?await loadDesktopPolicy(desktopPolicyPath):null;
148
+ const desktopObserverRuntime=desktopPolicy?createDesktopObserverRuntime({
149
+ observerPath:desktopPolicy.observer.executable,expectedObserverSha256:desktopPolicy.observer.sha256,
150
+ maxFrameBytes:desktopPolicy.limits.max_frame_bytes,timeoutMs:desktopPolicy.limits.capture_timeout_ms,
151
+ allowInputDesktops:desktopPolicy.allowed_input_desktops
152
+ }):null;
153
+ const desktopInputProvider=desktopPolicy?createNativeDesktopInputProvider({
154
+ inputPath:desktopPolicy.input.executable,expectedInputSha256:desktopPolicy.input.sha256,
155
+ timeoutMs:desktopPolicy.limits.input_timeout_ms
156
+ }):null;
157
+ const desktopGrounderProvider=desktopPolicy?createNativeDesktopGrounder({
158
+ grounderPath:desktopPolicy.grounder.executable,expectedGrounderSha256:desktopPolicy.grounder.sha256,
159
+ timeoutMs:desktopPolicy.limits.ground_timeout_ms
160
+ }):null;
161
+ const desktopSigningKey=desktopPolicy?await loadPrivateSigningKey(signingKeyPath):null;
162
+ const desktopVerifyKey=desktopPolicy?await loadPublicVerifyKey(verifyKeyPath):null;
163
+ if(desktopPolicy&&desktopSigningKey.keyId!==desktopVerifyKey.keyId) throw new Error('Desktop signing/verify key mismatch');
164
+ const desktopRuntime=desktopPolicy?createDesktopRuntime({
165
+ policy:desktopPolicy,observerRuntime:desktopObserverRuntime,inputProvider:desktopInputProvider,
166
+ grounderProvider:desktopGrounderProvider,
167
+ privateKey:desktopSigningKey.privateKey,publicKey:desktopVerifyKey.publicKey,keyId:desktopSigningKey.keyId
168
+ }):null;
169
+ const desktopMemoryProvider=desktopPolicy?createDesktopMemoryProvider({
170
+ evidenceDir:desktopPolicy.evidence_dir,
171
+ snapshotPath:path.join(desktopPolicy.evidence_dir,'desktop-memory.json'),
172
+ policySha256:desktopPolicy.policy_sha256,
173
+ privateKey:desktopSigningKey.privateKey,publicKey:desktopVerifyKey.publicKey,keyId:desktopSigningKey.keyId
174
+ }):null;
175
+
128
176
  const autonomousRuntimeMode = process.env.DEADBYTE_AUTONOMOUS_RUNTIME ?? '0';
129
177
  if (!['0','1'].includes(autonomousRuntimeMode)) throw new Error('DEADBYTE_AUTONOMOUS_RUNTIME must be 0 or 1');
130
178
  const autonomousSupervisorMode = process.env.DEADBYTE_AUTONOMOUS_SUPERVISOR_MODE ?? 'in_process';
@@ -142,8 +190,18 @@ if (autonomousRuntimeMode === '1' && !autonomousPolicyPath) throw new Error('DEA
142
190
  const autonomousPolicy = autonomousRuntimeMode === '1' ? await loadAutonomousPolicy(autonomousPolicyPath,codingPolicy) : null;
143
191
  const nativeDiffRuntime = autonomousPolicy ? createNativeDiffRuntime({ policy:autonomousPolicy,codingRuntime,machineFsRuntime,signingKeyPath,verifyKeyPath }) : null;
144
192
  semanticRuntime = codingRuntime ? createSemanticCodeRuntime({ codingRuntime, backends: semanticLsp.backends, nativeDiffRuntime }) : null;
193
+ const autonomousMemorySigningKey=autonomousPolicy?await loadPrivateSigningKey(signingKeyPath):null;
194
+ const autonomousMemoryVerifyKey=autonomousPolicy?await loadPublicVerifyKey(verifyKeyPath):null;
195
+ if(autonomousPolicy&&autonomousMemorySigningKey.keyId!==autonomousMemoryVerifyKey.keyId) throw new Error('R41 memory signing/verify key mismatch');
196
+ const memoryProvider=autonomousPolicy?createR41MemoryProvider({
197
+ memoryRoot:path.join(autonomousPolicy.evidence_dir,'memory-r41',packageManifestSha256),sourceReleaseManifest:packageManifestSha256,
198
+ journalRoot:path.join(autonomousPolicy.evidence_dir,'goals'),
199
+ writerVersion:DEADBYTE_VERSION,privateKey:autonomousMemorySigningKey.privateKey,
200
+ publicKey:autonomousMemoryVerifyKey.publicKey,keyId:autonomousMemorySigningKey.keyId,
201
+ byteBudget:Math.min(262144,Math.max(65536,Math.floor(autonomousPolicy.limits.max_context_bytes/2))),semantic:{enabled:false}
202
+ }):null;
145
203
  const autonomousRuntime = autonomousPolicy ? createAutonomousRuntime({ policy:autonomousPolicy,codingRuntime,nativeDiffRuntime,
146
- machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,signingKeyPath,verifyKeyPath }) : null;
204
+ machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,desktopRuntime,desktopMemoryProvider,memoryProvider,signingKeyPath,verifyKeyPath }) : null;
147
205
  const autonomousSupervisor = autonomousRuntime && autonomousPolicy.planner.backend === 'openai_compatible' &&
148
206
  autonomousSupervisorMode === 'in_process'
149
207
  ? startAutonomousSupervisor({ runtime: autonomousRuntime, policy: autonomousPolicy })
@@ -185,11 +243,17 @@ function filteredToolServer(server,allowed){
185
243
 
186
244
  serveStdio(() => {
187
245
  const server = new McpServer({ name: 'deadbyte-mcp', version: DEADBYTE_VERSION });
246
+ const registeredToolNames=new Set();
247
+ const toolServer={registerTool(name,...args){
248
+ if(registeredToolNames.has(name)) throw new Error(`duplicate tool registration: ${name}`);
249
+ registeredToolNames.add(name);
250
+ return server.registerTool(name,...args);
251
+ }};
188
252
  registerOperatorSurface(server,{packageRoot,surfaceProfile,compactToolLimit:COMPACT_SURFACE_TOOL_LIMIT});
189
253
  if (toolAudit) installToolAudit(server,toolAudit);
190
254
 
191
255
  if (surfaceProfile === 'full') {
192
- server.registerTool(
256
+ toolServer.registerTool(
193
257
  'workspace_open',
194
258
  {
195
259
  description: 'Open a named workspace below the configured DEADBYTE workspace root.',
@@ -206,7 +270,7 @@ serveStdio(() => {
206
270
  }
207
271
  );
208
272
 
209
- server.registerTool(
273
+ toolServer.registerTool(
210
274
  'file_read',
211
275
  {
212
276
  description: 'Read one UTF-8 file inside a named workspace. Path traversal and symlink escape are denied.',
@@ -229,7 +293,7 @@ serveStdio(() => {
229
293
  }
230
294
  );
231
295
 
232
- server.registerTool(
296
+ toolServer.registerTool(
233
297
  'proof_execute',
234
298
  {
235
299
  description: 'Run the fixed DEADBYTE V0 proof worker inside one workspace and produce an Ed25519-signed hashed receipt. This is not a general shell.',
@@ -263,7 +327,7 @@ serveStdio(() => {
263
327
  }
264
328
  );
265
329
 
266
- server.registerTool(
330
+ toolServer.registerTool(
267
331
  'contained_transform',
268
332
  {
269
333
  description: 'Run one compile-time allowlisted ASCII transform inside the proven Windows AppContainer + atomic Job boundary. Input is copied into a private sandbox profile; the host workspace is never mounted. This is not a shell and does not accept an executable path.',
@@ -306,7 +370,7 @@ serveStdio(() => {
306
370
 
307
371
  }
308
372
 
309
- server.registerTool(
373
+ toolServer.registerTool(
310
374
  'evidence_verify',
311
375
  {
312
376
  description: 'Independently verify Ed25519 receipt authenticity and recompute file, stream, and worker hashes.',
@@ -327,7 +391,7 @@ serveStdio(() => {
327
391
  );
328
392
 
329
393
  if (machineRuntime) {
330
- registerMachineTools(server, {
394
+ registerMachineTools(toolServer, {
331
395
  runtime: machineRuntime,
332
396
  assertRevokeAuthority: async () => {
333
397
  if (!hostPolicy) throw new Error('privileged host plane is not configured');
@@ -337,37 +401,41 @@ serveStdio(() => {
337
401
  }
338
402
 
339
403
  if (agentRuntime && surfaceProfile === 'full') {
340
- registerAgentTools(server, { runtime: agentRuntime, workspacePathFromId });
404
+ registerAgentTools(toolServer, { runtime: agentRuntime, workspacePathFromId });
341
405
  }
342
406
 
343
407
  if (processRuntime && surfaceProfile === 'full') {
344
- registerProcessTools(server, { runtime: processRuntime });
408
+ registerProcessTools(toolServer, { runtime: processRuntime });
345
409
  }
346
410
 
347
411
  if (codingRuntime && codingTaskRuntime && semanticRuntime) {
348
- const codingServer=surfaceProfile==='full'?server:filteredToolServer(server,COMPACT_CODING_DIRECT_TOOLS);
412
+ const codingServer=surfaceProfile==='full'?toolServer:filteredToolServer(toolServer,COMPACT_CODING_DIRECT_TOOLS);
349
413
  registerCodingTools(codingServer, { codingRuntime, taskRuntime: codingTaskRuntime, semanticRuntime });
350
414
  }
351
415
 
352
416
  if (machineFsRuntime && surfaceProfile === 'full') {
353
- registerMachineFsTools(server, { runtime: machineFsRuntime });
417
+ registerMachineFsTools(toolServer, { runtime: machineFsRuntime });
354
418
  }
355
419
 
356
420
  if (observationRuntime && surfaceProfile === 'full') {
357
- registerObservationTools(server, { runtime: observationRuntime });
421
+ registerObservationTools(toolServer, { runtime: observationRuntime });
422
+ }
423
+
424
+ if (desktopRuntime && surfaceProfile === 'full') {
425
+ registerDesktopTools(toolServer,{runtime:desktopRuntime});
358
426
  }
359
427
 
360
428
  if (autonomousRuntime && nativeDiffRuntime) {
361
- registerAutonomousTools(server, { autonomousRuntime, nativeDiffRuntime });
429
+ registerAutonomousTools(toolServer, { autonomousRuntime, nativeDiffRuntime });
362
430
  }
363
431
 
364
- registerCompactGatewayTools(server,{
432
+ registerCompactGatewayTools(toolServer,{
365
433
  profile:surfaceProfile,ledger:R36_CAPABILITY_LEDGER,codingRuntime,semanticRuntime,machineFsRuntime,
366
- processRuntime,observationRuntime,machineRuntime
434
+ processRuntime,observationRuntime,machineRuntime,desktopRuntime,catalogProvider:()=>[...registeredToolNames]
367
435
  });
368
436
 
369
437
  if (hostPolicy) {
370
- server.registerTool(
438
+ toolServer.registerTool(
371
439
  'host_file_read',
372
440
  {
373
441
  description: 'Privileged host-plane read from a locally allowlisted root. Requires a live local arm lease; path traversal and symlink escape are denied.',
@@ -388,7 +456,7 @@ serveStdio(() => {
388
456
  }
389
457
  );
390
458
 
391
- server.registerTool(
459
+ toolServer.registerTool(
392
460
  'host_file_write',
393
461
  {
394
462
  description: 'Privileged host-plane hash-precondition file write inside a locally allowlisted root. Commit is same-directory atomic rename and post-commit SHA-256 verified. Requires a live local arm lease.',
@@ -417,7 +485,7 @@ serveStdio(() => {
417
485
  }
418
486
  );
419
487
 
420
- server.registerTool(
488
+ toolServer.registerTool(
421
489
  'host_exec',
422
490
  {
423
491
  description: 'Privileged host-plane script execution through a locally allowlisted and SHA-256-pinned executable. No raw shell command string is accepted. Requires a live local arm lease.',