deadbyte-mcp 0.15.35 → 0.15.37

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 (92) hide show
  1. package/MANIFEST.SHA256 +91 -46
  2. package/PROVENANCE.json +76 -30
  3. package/README.txt +62 -8
  4. package/RELEASE.json +78 -23
  5. package/SBOM.cdx.json +10 -25
  6. package/TEST-MATRIX.json +109 -44
  7. package/bridge/package.json +4 -2
  8. package/bridge/src/bridge-health-r59.mjs +53 -0
  9. package/bridge/src/bridge.mjs +158 -26
  10. package/bridge/src/canonical-json-r60.mjs +13 -0
  11. package/bridge/src/r40-governor.mjs +56 -10
  12. package/bridge/src/reconnect-delay-r60.mjs +31 -0
  13. package/bridge/src/remote-call-claims-r60.mjs +157 -0
  14. package/bridge/src/remote-dispatch-r60.mjs +75 -0
  15. package/controller/deadbyte-controller.ps1 +76 -13
  16. package/controller/deadbyte-process-policy.json +4 -4
  17. package/docs/R59-PROVENANCE.json +87 -0
  18. package/docs/R59-RELEASE.json +187 -0
  19. package/docs/R59-SBOM.cdx.json +68 -0
  20. package/docs/R59-TASK-CONTRACT.md +26 -0
  21. package/docs/R59-TEST-MATRIX.json +258 -0
  22. package/docs/R59-bridge-package.json +13 -0
  23. package/docs/R59-package-lock.json +184 -0
  24. package/docs/R59-package.json +106 -0
  25. package/docs/R59-version.mjs +6 -0
  26. package/docs/R60-TASK-CONTRACT.md +22 -0
  27. package/package.json +7 -3
  28. package/proof/r59-full-regression-current.json +13 -0
  29. package/proof/r59-full-regression-current.stderr.log +0 -0
  30. package/proof/r59-full-regression-current.stdout.log +1268 -0
  31. package/scripts/full-regression-r60.mjs +32 -0
  32. package/scripts/gate-windows-r59-prepublish.ps1 +41 -0
  33. package/scripts/gate-windows-r60-prepublish.ps1 +74 -0
  34. package/scripts/r59-full-regression-capture.mjs +35 -0
  35. package/src/capability-resolver.mjs +25 -7
  36. package/src/capability-snapshot.mjs +56 -0
  37. package/src/compact-gateway-mcp-tools.mjs +10 -11
  38. package/src/deadbyte-cli.mjs +80 -34
  39. package/src/mcp-server.mjs +179 -118
  40. package/src/r40-compact-disarmed-probe.mjs +1 -1
  41. package/src/r44-compact-disarmed-probe.mjs +1 -1
  42. package/src/r45-compact-disarmed-probe.mjs +1 -1
  43. package/src/remote-authority.mjs +56 -0
  44. package/src/remote-enforcement-probe-r60.mjs +17 -0
  45. package/src/remote-live-log.mjs +19 -2
  46. package/src/remote-log-decode-r60.mjs +32 -0
  47. package/src/remote-mcp-machine-smoke-client.mjs +19 -1
  48. package/src/remote-mcp-r40-parity-client.mjs +1 -1
  49. package/src/remote-mcp-r44-parity-client.mjs +1 -1
  50. package/src/remote-mcp-r45-parity-client.mjs +1 -1
  51. package/src/remote-mcp-smoke-client.mjs +1 -1
  52. package/src/remote-session-guardian.mjs +20 -3
  53. package/src/runtime-plane-registry.mjs +74 -0
  54. package/src/tool-audit.mjs +5 -0
  55. package/src/version.mjs +1 -1
  56. package/test/bridge-runtime-r59.test.mjs +60 -0
  57. package/test/capability-resolver.test.mjs +16 -0
  58. package/test/capability-snapshot-r59.test.mjs +39 -0
  59. package/test/compact-gateway-r36.test.mjs +22 -2
  60. package/test/compact-max-catalog-r44.test.mjs +1 -1
  61. package/test/compact-max-catalog-r45.test.mjs +1 -1
  62. package/test/contained.test.mjs +2 -1
  63. package/test/controller-policy-preflight-r59.test.mjs +39 -0
  64. package/test/fixtures/r59-compact-surface-v0.15.35.json +222 -0
  65. package/test/observation-integration.test.mjs +2 -3
  66. package/test/optional-plane-degraded-r59.test.mjs +44 -0
  67. package/test/r48-release-contract.test.mjs +1 -1
  68. package/test/r49-windows-gate.test.mjs +1 -1
  69. package/test/r51-runtime-coherence.test.mjs +2 -2
  70. package/test/r58-bundled-bridge.test.mjs +3 -1
  71. package/test/r58-cleanup-retention.test.mjs +9 -3
  72. package/test/r58-concurrent-recovery.test.mjs +9 -3
  73. package/test/r58-controller-live-local.test.mjs +36 -4
  74. package/test/r58-controller-state-coherence.test.mjs +1 -1
  75. package/test/r58-release-contract.test.mjs +3 -2
  76. package/test/r58-stale-owner.test.mjs +2 -2
  77. package/test/r58-windows-gate.test.mjs +2 -1
  78. package/test/r59-release-contract.test.mjs +61 -0
  79. package/test/r59-tool-surface-compat.test.mjs +90 -0
  80. package/test/r60-authority-coherence.test.mjs +36 -0
  81. package/test/r60-authority-enforcement.test.mjs +28 -0
  82. package/test/r60-bridge-dispatch.test.mjs +119 -0
  83. package/test/r60-clock-discipline.test.mjs +15 -0
  84. package/test/r60-live-timeline.test.mjs +29 -0
  85. package/test/r60-reconnect-errors.test.mjs +21 -0
  86. package/test/r60-reconnect-jitter.test.mjs +18 -0
  87. package/test/r60-release-contract.test.mjs +81 -0
  88. package/test/r60-remote-call-recovery.test.mjs +170 -0
  89. package/test/r60-windows-log-decode.test.mjs +25 -0
  90. package/test/remote-live-log-r37.test.mjs +1 -1
  91. package/test/remote-session-cli.test.mjs +200 -43
  92. package/test/runtime-plane-registry-r59.test.mjs +40 -0
@@ -66,6 +66,7 @@ import { capabilityProfileFromEnv, COMPACT_SURFACE_TOOL_LIMIT, R36_CAPABILITY_LE
66
66
  import { registerCompactGatewayTools } from './compact-gateway-mcp-tools.mjs';
67
67
  import { createSkillPlane } from './skill-plane-r44.mjs';
68
68
  import { registerSkillToolsR44 } from './skill-mcp-tools-r44.mjs';
69
+ import { createRuntimePlaneRegistry, createUnavailableRuntime, RuntimePlaneUnavailableError } from './runtime-plane-registry.mjs';
69
70
  import {
70
71
  containedTransformOutputSchema,
71
72
  evidenceVerifyOutputSchema,
@@ -86,6 +87,7 @@ const verifyKeyPath = process.env.DEADBYTE_VERIFY_KEY ?? defaultPublicKeyPath();
86
87
  const auditRuntimeMode = process.env.DEADBYTE_AUDIT_RUNTIME ?? '0';
87
88
  if (!['0','1'].includes(auditRuntimeMode)) throw new Error('DEADBYTE_AUDIT_RUNTIME must be 0 or 1');
88
89
  const runtimeStateRoot = path.resolve(process.env.DEADBYTE_STATE_ROOT || path.join(os.homedir(),'.deadbyte-mcp'));
90
+ const planeRegistry=createRuntimePlaneRegistry();
89
91
  const interruptedUpdateRecovery = await recoverInterruptedSlotUpdates({ stateRoot: runtimeStateRoot });
90
92
  if (interruptedUpdateRecovery.launched > 0) {
91
93
  console.error(`[runtime-update-recovery] launched ${interruptedUpdateRecovery.launched} detached supervisor(s)`);
@@ -103,15 +105,16 @@ if (!privilegedPolicyExplicit) {
103
105
  if (error?.code !== 'ENOENT') throw error;
104
106
  }
105
107
  }
106
- const hostPolicy = privilegedPolicyPath ? await loadHostPolicy(privilegedPolicyPath) : null;
108
+ planeRegistry.define('host',{configured:Boolean(privilegedPolicyPath),required:false});
109
+ const hostPolicy=await planeRegistry.initialize('host',async()=>loadHostPolicy(privilegedPolicyPath));
107
110
  const machineRuntimeMode = process.env.DEADBYTE_MACHINE_RUNTIME ?? '0';
108
111
  if (!['0', '1'].includes(machineRuntimeMode)) throw new Error('DEADBYTE_MACHINE_RUNTIME must be 0 or 1');
109
- const machineRuntime = machineRuntimeMode === '1'
110
- ? await createMachineRuntime({ stateRoot: runtimeStateRoot })
111
- : null;
112
+ planeRegistry.define('machine',{configured:machineRuntimeMode==='1',required:true});
113
+ const machineRuntime=await planeRegistry.initialize('machine',async()=>createMachineRuntime({stateRoot:runtimeStateRoot}));
112
114
  const agentRuntimeMode = process.env.DEADBYTE_AGENT_RUNTIME ?? '0';
113
115
  if (!['0', '1'].includes(agentRuntimeMode)) throw new Error('DEADBYTE_AGENT_RUNTIME must be 0 or 1');
114
- const agentRuntime = agentRuntimeMode === '1' ? createAgentRuntime({ signingKeyPath, verifyKeyPath }) : null;
116
+ planeRegistry.define('agent',{configured:agentRuntimeMode==='1',required:false});
117
+ const agentRuntime=await planeRegistry.initialize('agent',async()=>createAgentRuntime({signingKeyPath,verifyKeyPath}));
115
118
 
116
119
  const processRuntimeMode = process.env.DEADBYTE_PROCESS_RUNTIME ?? '0';
117
120
  if (!['0', '1'].includes(processRuntimeMode)) throw new Error('DEADBYTE_PROCESS_RUNTIME must be 0 or 1');
@@ -121,9 +124,14 @@ if (processRuntimeMode === '1' && !processPolicyPath) {
121
124
  try { await access(localProcessPolicyPath); processPolicyPath = localProcessPolicyPath; }
122
125
  catch (error) { if (error?.code !== 'ENOENT') throw error; }
123
126
  }
124
- if (processRuntimeMode === '1' && !processPolicyPath) throw new Error('DEADBYTE_PROCESS_RUNTIME=1 requires a process policy');
125
- const processPolicy = processRuntimeMode === '1' ? await loadProcessPolicy(processPolicyPath) : null;
126
- const processRuntime = processPolicy ? createProcessRuntime({ policy: processPolicy, signingKeyPath, verifyKeyPath }) : null;
127
+ planeRegistry.define('process',{configured:processRuntimeMode==='1',required:false});
128
+ let processPolicy=null;
129
+ const processRuntime=await planeRegistry.initialize('process',async()=>{
130
+ if(!processPolicyPath) throw new Error('DEADBYTE_PROCESS_RUNTIME=1 requires a process policy');
131
+ processPolicy=await loadProcessPolicy(processPolicyPath);
132
+ return createProcessRuntime({policy:processPolicy,signingKeyPath,verifyKeyPath});
133
+ });
134
+ if(!processRuntime) processPolicy=null;
127
135
 
128
136
  const codingRuntimeMode = process.env.DEADBYTE_CODING_RUNTIME ?? '0';
129
137
  if (!['0', '1'].includes(codingRuntimeMode)) throw new Error('DEADBYTE_CODING_RUNTIME must be 0 or 1');
@@ -133,29 +141,32 @@ if (codingRuntimeMode === '1' && !codingPolicyPath) {
133
141
  try { await access(localCodingPolicyPath); codingPolicyPath = localCodingPolicyPath; }
134
142
  catch (error) { if (error?.code !== 'ENOENT') throw error; }
135
143
  }
136
- if (codingRuntimeMode === '1' && !codingPolicyPath) throw new Error('DEADBYTE_CODING_RUNTIME=1 requires a coding policy');
137
- const codingPolicy = codingRuntimeMode === '1' ? await loadCodingPolicy(codingPolicyPath) : null;
138
- const codingRuntime = codingPolicy ? createCodingRuntime({ policy: codingPolicy, signingKeyPath, verifyKeyPath }) : null;
139
- const codingTaskRuntime = codingRuntime ? createCodingTaskRuntime({ codingRuntime, signingKeyPath, verifyKeyPath }) : null;
144
+ planeRegistry.define('coding',{configured:codingRuntimeMode==='1',required:false});
145
+ let codingPolicy=null;
146
+ const codingRuntime=await planeRegistry.initialize('coding',async()=>{
147
+ if(!codingPolicyPath) throw new Error('DEADBYTE_CODING_RUNTIME=1 requires a coding policy');
148
+ codingPolicy=await loadCodingPolicy(codingPolicyPath);
149
+ return createCodingRuntime({policy:codingPolicy,signingKeyPath,verifyKeyPath});
150
+ });
151
+ if(!codingRuntime) codingPolicy=null;
152
+ const codingTaskRuntime=codingRuntime?createCodingTaskRuntime({codingRuntime,signingKeyPath,verifyKeyPath}):null;
140
153
  const semanticLspBinding = semanticConfigBindingFromEnv(process.env);
141
- const semanticLsp = codingRuntime && semanticLspBinding
142
- ? await loadSemanticLspBackends({ ...semanticLspBinding, codingRuntime })
143
- : { backends: [], required_ids: [] };
144
- let semanticRuntime = null;
154
+ planeRegistry.define('semantic',{configured:codingRuntimeMode==='1',required:false,dependencies:['coding']});
155
+ let semanticLsp={backends:[],required_ids:[]};
156
+ let semanticRuntime=await planeRegistry.initialize('semantic',async()=>{
157
+ semanticLsp=semanticLspBinding?await loadSemanticLspBackends({...semanticLspBinding,codingRuntime}):semanticLsp;
158
+ return createSemanticCodeRuntime({codingRuntime,backends:semanticLsp.backends,nativeDiffRuntime:null});
159
+ });
145
160
  const machineFsRuntimeMode = process.env.DEADBYTE_MACHINE_FS_RUNTIME ?? '0';
146
161
  if (!['0','1'].includes(machineFsRuntimeMode)) throw new Error('DEADBYTE_MACHINE_FS_RUNTIME must be 0 or 1');
147
- if (machineFsRuntimeMode === '1' && !codingPolicy) throw new Error('DEADBYTE_MACHINE_FS_RUNTIME=1 requires DEADBYTE_CODING_RUNTIME=1');
148
- const machineFsRuntime = machineFsRuntimeMode === '1'
149
- ? createMachineFsRuntime({ policy: codingPolicy, signingKeyPath, verifyKeyPath })
150
- : null;
162
+ planeRegistry.define('machine_fs',{configured:machineFsRuntimeMode==='1',required:false,dependencies:['coding']});
163
+ const machineFsRuntime=await planeRegistry.initialize('machine_fs',async()=>createMachineFsRuntime({policy:codingPolicy,signingKeyPath,verifyKeyPath}));
151
164
  const observationRuntimeMode = process.env.DEADBYTE_OBSERVATION_RUNTIME ?? '0';
152
165
  if (!['0','1'].includes(observationRuntimeMode)) throw new Error('DEADBYTE_OBSERVATION_RUNTIME must be 0 or 1');
153
- if (observationRuntimeMode === '1' && !machineRuntime) throw new Error('DEADBYTE_OBSERVATION_RUNTIME=1 requires DEADBYTE_MACHINE_RUNTIME=1');
154
- if (observationRuntimeMode === '1' && !codingPolicy) throw new Error('DEADBYTE_OBSERVATION_RUNTIME=1 requires DEADBYTE_CODING_RUNTIME=1');
155
- const observationRuntime = observationRuntimeMode === '1'
156
- ? createObservationRuntime({ policy: codingPolicy, processRuntime, signingKeyPath, verifyKeyPath,
157
- stateRoot: runtimeStateRoot })
158
- : null;
166
+ planeRegistry.define('observation',{configured:observationRuntimeMode==='1',required:false,dependencies:['machine','coding']});
167
+ const observationRuntime=await planeRegistry.initialize('observation',async()=>createObservationRuntime({
168
+ policy:codingPolicy,processRuntime,signingKeyPath,verifyKeyPath,stateRoot:runtimeStateRoot
169
+ }));
159
170
 
160
171
  const desktopRuntimeMode=process.env.DEADBYTE_DESKTOP_RUNTIME??'0';
161
172
  if(!['0','1'].includes(desktopRuntimeMode)) throw new Error('DEADBYTE_DESKTOP_RUNTIME must be 0 or 1');
@@ -165,35 +176,37 @@ if(desktopRuntimeMode==='1'&&!desktopPolicyPath){
165
176
  try{await access(localDesktopPolicyPath);desktopPolicyPath=localDesktopPolicyPath;}
166
177
  catch(error){if(error?.code!=='ENOENT')throw error;}
167
178
  }
168
- if(desktopRuntimeMode==='1'&&!desktopPolicyPath) throw new Error('DEADBYTE_DESKTOP_RUNTIME=1 requires a desktop policy');
169
- const desktopPolicy=desktopRuntimeMode==='1'?await loadDesktopPolicy(desktopPolicyPath):null;
170
- const desktopObserverRuntime=desktopPolicy?createDesktopObserverRuntime({
171
- observerPath:desktopPolicy.observer.executable,expectedObserverSha256:desktopPolicy.observer.sha256,
172
- maxFrameBytes:desktopPolicy.limits.max_frame_bytes,timeoutMs:desktopPolicy.limits.capture_timeout_ms,
173
- allowInputDesktops:desktopPolicy.allowed_input_desktops
174
- }):null;
175
- const desktopInputProvider=desktopPolicy?createNativeDesktopInputProvider({
176
- inputPath:desktopPolicy.input.executable,expectedInputSha256:desktopPolicy.input.sha256,
177
- timeoutMs:desktopPolicy.limits.input_timeout_ms
178
- }):null;
179
- const desktopGrounderProvider=desktopPolicy?createNativeDesktopGrounder({
180
- grounderPath:desktopPolicy.grounder.executable,expectedGrounderSha256:desktopPolicy.grounder.sha256,
181
- timeoutMs:desktopPolicy.limits.ground_timeout_ms
182
- }):null;
183
- const desktopSigningKey=desktopPolicy?await loadPrivateSigningKey(signingKeyPath):null;
184
- const desktopVerifyKey=desktopPolicy?await loadPublicVerifyKey(verifyKeyPath):null;
185
- if(desktopPolicy&&desktopSigningKey.keyId!==desktopVerifyKey.keyId) throw new Error('Desktop signing/verify key mismatch');
186
- const desktopRuntime=desktopPolicy?createDesktopRuntime({
187
- policy:desktopPolicy,observerRuntime:desktopObserverRuntime,inputProvider:desktopInputProvider,
188
- grounderProvider:desktopGrounderProvider,
189
- privateKey:desktopSigningKey.privateKey,publicKey:desktopVerifyKey.publicKey,keyId:desktopSigningKey.keyId
190
- }):null;
191
- const desktopMemoryProvider=desktopPolicy?createDesktopMemoryProvider({
192
- evidenceDir:desktopPolicy.evidence_dir,
193
- snapshotPath:path.join(desktopPolicy.evidence_dir,'desktop-memory.json'),
194
- policySha256:desktopPolicy.policy_sha256,
195
- privateKey:desktopSigningKey.privateKey,publicKey:desktopVerifyKey.publicKey,keyId:desktopSigningKey.keyId
196
- }):null;
179
+ planeRegistry.define('desktop',{configured:desktopRuntimeMode==='1',required:false});
180
+ let desktopPolicy=null;
181
+ let desktopMemoryProvider=null;
182
+ const desktopRuntime=await planeRegistry.initialize('desktop',async()=>{
183
+ if(!desktopPolicyPath) throw new Error('DEADBYTE_DESKTOP_RUNTIME=1 requires a desktop policy');
184
+ desktopPolicy=await loadDesktopPolicy(desktopPolicyPath);
185
+ const observerRuntime=createDesktopObserverRuntime({
186
+ observerPath:desktopPolicy.observer.executable,expectedObserverSha256:desktopPolicy.observer.sha256,
187
+ maxFrameBytes:desktopPolicy.limits.max_frame_bytes,timeoutMs:desktopPolicy.limits.capture_timeout_ms,
188
+ allowInputDesktops:desktopPolicy.allowed_input_desktops
189
+ });
190
+ const inputProvider=createNativeDesktopInputProvider({
191
+ inputPath:desktopPolicy.input.executable,expectedInputSha256:desktopPolicy.input.sha256,
192
+ timeoutMs:desktopPolicy.limits.input_timeout_ms
193
+ });
194
+ const grounderProvider=createNativeDesktopGrounder({
195
+ grounderPath:desktopPolicy.grounder.executable,expectedGrounderSha256:desktopPolicy.grounder.sha256,
196
+ timeoutMs:desktopPolicy.limits.ground_timeout_ms
197
+ });
198
+ const signingKey=await loadPrivateSigningKey(signingKeyPath);
199
+ const verifyKey=await loadPublicVerifyKey(verifyKeyPath);
200
+ if(signingKey.keyId!==verifyKey.keyId) throw new Error('Desktop signing/verify key mismatch');
201
+ desktopMemoryProvider=createDesktopMemoryProvider({
202
+ evidenceDir:desktopPolicy.evidence_dir,snapshotPath:path.join(desktopPolicy.evidence_dir,'desktop-memory.json'),
203
+ policySha256:desktopPolicy.policy_sha256,privateKey:signingKey.privateKey,
204
+ publicKey:verifyKey.publicKey,keyId:signingKey.keyId
205
+ });
206
+ return createDesktopRuntime({policy:desktopPolicy,observerRuntime,inputProvider,grounderProvider,
207
+ privateKey:signingKey.privateKey,publicKey:verifyKey.publicKey,keyId:signingKey.keyId});
208
+ });
209
+ if(!desktopRuntime){desktopPolicy=null;desktopMemoryProvider=null;}
197
210
 
198
211
  const autonomousRuntimeMode = process.env.DEADBYTE_AUTONOMOUS_RUNTIME ?? '0';
199
212
  if (!['0','1'].includes(autonomousRuntimeMode)) throw new Error('DEADBYTE_AUTONOMOUS_RUNTIME must be 0 or 1');
@@ -201,53 +214,55 @@ const autonomousSupervisorMode = process.env.DEADBYTE_AUTONOMOUS_SUPERVISOR_MODE
201
214
  if (!['in_process','external'].includes(autonomousSupervisorMode)) {
202
215
  throw new Error('DEADBYTE_AUTONOMOUS_SUPERVISOR_MODE must be in_process or external');
203
216
  }
204
- if (autonomousRuntimeMode === '1' && !codingRuntime) throw new Error('DEADBYTE_AUTONOMOUS_RUNTIME=1 requires DEADBYTE_CODING_RUNTIME=1');
205
217
  const localAutonomousPolicyPath = path.join(packageRoot,'controller','deadbyte-autonomous-policy.json');
206
218
  let autonomousPolicyPath = process.env.DEADBYTE_AUTONOMOUS_POLICY ?? '';
207
219
  if (autonomousRuntimeMode === '1' && !autonomousPolicyPath) {
208
220
  try { await access(localAutonomousPolicyPath); autonomousPolicyPath = localAutonomousPolicyPath; }
209
221
  catch (error) { if (error?.code !== 'ENOENT') throw error; }
210
222
  }
211
- if (autonomousRuntimeMode === '1' && !autonomousPolicyPath) throw new Error('DEADBYTE_AUTONOMOUS_RUNTIME=1 requires an autonomous policy');
212
- const autonomousPolicy = autonomousRuntimeMode === '1' ? await loadAutonomousPolicy(autonomousPolicyPath,codingPolicy) : null;
213
- const nativeDiffRuntime = autonomousPolicy ? createNativeDiffRuntime({ policy:autonomousPolicy,codingRuntime,machineFsRuntime,signingKeyPath,verifyKeyPath }) : null;
214
- semanticRuntime = codingRuntime ? createSemanticCodeRuntime({ codingRuntime, backends: semanticLsp.backends, nativeDiffRuntime }) : null;
215
- const autonomousMemorySigningKey=autonomousPolicy?await loadPrivateSigningKey(signingKeyPath):null;
216
- const autonomousMemoryVerifyKey=autonomousPolicy?await loadPublicVerifyKey(verifyKeyPath):null;
217
- if(autonomousPolicy&&autonomousMemorySigningKey.keyId!==autonomousMemoryVerifyKey.keyId) throw new Error('R41 memory signing/verify key mismatch');
218
- const memoryProvider=autonomousPolicy?createR41MemoryProvider({
219
- memoryRoot:path.join(autonomousPolicy.evidence_dir,'memory-r41',packageManifestSha256),sourceReleaseManifest:packageManifestSha256,
220
- journalRoot:path.join(autonomousPolicy.evidence_dir,'goals'),
221
- writerVersion:DEADBYTE_VERSION,privateKey:autonomousMemorySigningKey.privateKey,
222
- publicKey:autonomousMemoryVerifyKey.publicKey,keyId:autonomousMemorySigningKey.keyId,
223
- byteBudget:Math.min(262144,Math.max(65536,Math.floor(autonomousPolicy.limits.max_context_bytes/2))),semantic:{enabled:false}
224
- }):null;
225
- const plannerProviderRuntime=autonomousPolicy?.planner.backend==='codex_app_server'
226
- ? await createCodexAppServerR44({
227
- stateDir:path.join(autonomousPolicy.evidence_dir,'provider-r44','codex-app-server'),
228
- model:autonomousPolicy.planner.model,cwd:codingPolicy.roots[autonomousPolicy.planner.root_id].real_path,
229
- clientVersion:DEADBYTE_VERSION,executable:autonomousPolicy.planner.executable,
230
- executableSha256:autonomousPolicy.planner.executable_sha256,args:autonomousPolicy.planner.args
231
- })
232
- : null;
233
- const autonomousRuntime = autonomousPolicy ? createAutonomousRuntime({ policy:autonomousPolicy,codingRuntime,nativeDiffRuntime,
234
- machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,desktopRuntime,desktopMemoryProvider,memoryProvider,
235
- plannerProviderRuntime,signingKeyPath,verifyKeyPath }) : null;
223
+ planeRegistry.define('autonomous',{configured:autonomousRuntimeMode==='1',required:false,dependencies:['coding']});
224
+ let autonomousPolicy=null;
225
+ let nativeDiffRuntime=null;
226
+ const autonomousRuntime=await planeRegistry.initialize('autonomous',async()=>{
227
+ if(!autonomousPolicyPath) throw new Error('DEADBYTE_AUTONOMOUS_RUNTIME=1 requires an autonomous policy');
228
+ autonomousPolicy=await loadAutonomousPolicy(autonomousPolicyPath,codingPolicy);
229
+ nativeDiffRuntime=createNativeDiffRuntime({policy:autonomousPolicy,codingRuntime,machineFsRuntime,signingKeyPath,verifyKeyPath});
230
+ semanticRuntime=createSemanticCodeRuntime({codingRuntime,backends:semanticLsp.backends,nativeDiffRuntime});
231
+ const memorySigningKey=await loadPrivateSigningKey(signingKeyPath);
232
+ const memoryVerifyKey=await loadPublicVerifyKey(verifyKeyPath);
233
+ if(memorySigningKey.keyId!==memoryVerifyKey.keyId) throw new Error('R41 memory signing/verify key mismatch');
234
+ const memoryProvider=createR41MemoryProvider({
235
+ memoryRoot:path.join(autonomousPolicy.evidence_dir,'memory-r41',packageManifestSha256),sourceReleaseManifest:packageManifestSha256,
236
+ journalRoot:path.join(autonomousPolicy.evidence_dir,'goals'),writerVersion:DEADBYTE_VERSION,
237
+ privateKey:memorySigningKey.privateKey,publicKey:memoryVerifyKey.publicKey,keyId:memorySigningKey.keyId,
238
+ byteBudget:Math.min(262144,Math.max(65536,Math.floor(autonomousPolicy.limits.max_context_bytes/2))),semantic:{enabled:false}
239
+ });
240
+ const plannerProviderRuntime=autonomousPolicy.planner.backend==='codex_app_server'
241
+ ? await createCodexAppServerR44({stateDir:path.join(autonomousPolicy.evidence_dir,'provider-r44','codex-app-server'),
242
+ model:autonomousPolicy.planner.model,cwd:codingPolicy.roots[autonomousPolicy.planner.root_id].real_path,
243
+ clientVersion:DEADBYTE_VERSION,executable:autonomousPolicy.planner.executable,
244
+ executableSha256:autonomousPolicy.planner.executable_sha256,args:autonomousPolicy.planner.args})
245
+ : null;
246
+ return createAutonomousRuntime({policy:autonomousPolicy,codingRuntime,nativeDiffRuntime,machineFsRuntime,
247
+ observationRuntime,processRuntime,semanticRuntime,desktopRuntime,desktopMemoryProvider,memoryProvider,
248
+ plannerProviderRuntime,signingKeyPath,verifyKeyPath});
249
+ });
250
+ if(!autonomousRuntime){autonomousPolicy=null;nativeDiffRuntime=null;}
236
251
  const autonomousSupervisor = autonomousRuntime && ['openai_compatible','openai_responses','codex_app_server'].includes(autonomousPolicy.planner.backend) &&
237
252
  autonomousSupervisorMode === 'in_process'
238
253
  ? startAutonomousSupervisor({ runtime: autonomousRuntime, policy: autonomousPolicy })
239
254
  : null;
240
255
  void autonomousSupervisor;
241
- if (auditRuntimeMode === '1' && !machineRuntime) throw new Error('DEADBYTE_AUDIT_RUNTIME=1 requires DEADBYTE_MACHINE_RUNTIME=1');
242
- const auditContextProvider = auditRuntimeMode === '1' ? createAuditContextProvider({
243
- stateRoot:runtimeStateRoot,packageRoot,machineRuntime,processPolicy,codingRuntime,autonomousRuntime,hostPolicy
244
- }) : null;
245
- const toolAudit = auditRuntimeMode === '1' ? await createToolAudit({
246
- stateRoot:runtimeStateRoot,signingKeyPath,contextProvider:auditContextProvider
247
- }) : null;
256
+ planeRegistry.define('audit',{configured:auditRuntimeMode==='1',required:false,dependencies:['machine']});
257
+ const toolAudit=await planeRegistry.initialize('audit',async()=>{
258
+ const contextProvider=createAuditContextProvider({stateRoot:runtimeStateRoot,packageRoot,machineRuntime,
259
+ processPolicy,codingRuntime,autonomousRuntime,hostPolicy});
260
+ return createToolAudit({stateRoot:runtimeStateRoot,signingKeyPath,contextProvider});
261
+ });
248
262
  const skillRoot=path.join(runtimeStateRoot,'skills');
249
263
  await mkdir(skillRoot,{recursive:true});
250
- const skillRuntime=await createSkillPlane({root:skillRoot,verifyKeyPath});
264
+ planeRegistry.define('skill',{configured:true,required:false});
265
+ const skillRuntime=await planeRegistry.initialize('skill',async()=>createSkillPlane({root:skillRoot,verifyKeyPath}));
251
266
  const commanderExtendedRuntime=createCommanderExtendedRuntime({stateRoot:runtimeStateRoot});
252
267
  const commanderExternalProcessRuntime=observationRuntime?createCommanderExternalProcessRuntime({
253
268
  observationRuntime,hostPolicy,hostExecInlineFn:hostExecInline
@@ -259,6 +274,48 @@ const remoteCapabilities=new Set(String(process.env.DEADBYTE_REMOTE_CAPABILITIES
259
274
  const remoteRelay=remoteRelayEndpoint?await createCommanderRemoteRelayR47({endpoint:remoteRelayEndpoint}):null;
260
275
  const remoteDevicePlane=remoteRelay?await createRemoteDevicePlaneR44({stateDir:path.join(runtimeStateRoot,'remote-device-r44'),relay:remoteRelay,authorizeCapability:async capability=>remoteCapabilities.has(capability)}):null;
261
276
 
277
+ function runtimeForRegistration(plane,runtime){
278
+ const state=planeRegistry.state(plane);
279
+ return runtime??(state.configured?createUnavailableRuntime(plane,state.diagnostic??{}):null);
280
+ }
281
+ function requirePlane(plane,runtime){
282
+ if(runtime) return runtime;
283
+ const state=planeRegistry.state(plane);
284
+ throw new RuntimePlaneUnavailableError(plane,state.diagnostic??{});
285
+ }
286
+ function capabilityPlaneSnapshot(){
287
+ const planes=planeRegistry.snapshot().planes;
288
+ return {
289
+ DEADBYTE_MACHINE_RUNTIME:planes.machine,
290
+ DEADBYTE_PROCESS_RUNTIME:planes.process,
291
+ DEADBYTE_CODING_RUNTIME:planes.coding,
292
+ DEADBYTE_MACHINE_FS_RUNTIME:planes.machine_fs,
293
+ DEADBYTE_OBSERVATION_RUNTIME:planes.observation,
294
+ DEADBYTE_DESKTOP_RUNTIME:planes.desktop,
295
+ DEADBYTE_AUTONOMOUS_RUNTIME:planes.autonomous,
296
+ DEADBYTE_PRIVILEGED_POLICY:planes.host
297
+ };
298
+ }
299
+ async function currentReleaseBindings(){
300
+ if(machineRuntime){
301
+ try{return await machineRuntime.status();}catch{}
302
+ }
303
+ return {release_id:`package-${packageManifestSha256.slice(0,16)}`,
304
+ release_manifest_sha256:packageManifestSha256,generation_manifest_sha256:null};
305
+ }
306
+ const registeredMachineRuntime=runtimeForRegistration('machine',machineRuntime);
307
+ const registeredAgentRuntime=runtimeForRegistration('agent',agentRuntime);
308
+ const registeredProcessRuntime=runtimeForRegistration('process',processRuntime);
309
+ const registeredCodingRuntime=runtimeForRegistration('coding',codingRuntime);
310
+ const registeredCodingTaskRuntime=codingTaskRuntime??(planeRegistry.state('coding').configured?createUnavailableRuntime('coding',planeRegistry.state('coding').diagnostic??{}):null);
311
+ const registeredSemanticRuntime=runtimeForRegistration('semantic',semanticRuntime);
312
+ const registeredMachineFsRuntime=runtimeForRegistration('machine_fs',machineFsRuntime);
313
+ const registeredObservationRuntime=runtimeForRegistration('observation',observationRuntime);
314
+ const registeredDesktopRuntime=runtimeForRegistration('desktop',desktopRuntime);
315
+ const registeredAutonomousRuntime=runtimeForRegistration('autonomous',autonomousRuntime);
316
+ const registeredNativeDiffRuntime=nativeDiffRuntime??(planeRegistry.state('autonomous').configured?createUnavailableRuntime('autonomous',planeRegistry.state('autonomous').diagnostic??{}):null);
317
+ const registeredSkillRuntime=runtimeForRegistration('skill',skillRuntime);
318
+
262
319
  installStdioConsoleGuard();
263
320
  if (process.env.DEADBYTE_STDIO_CONSOLE_GUARD_PROBE === '1') console.log('DEADBYTE_STDIO_CONSOLE_GUARD_PROBE');
264
321
 
@@ -437,54 +494,58 @@ serveStdio(() => {
437
494
  }
438
495
  );
439
496
 
440
- if (machineRuntime) {
497
+ if (registeredMachineRuntime) {
441
498
  registerMachineTools(toolServer, {
442
- runtime: machineRuntime,
499
+ runtime: registeredMachineRuntime,
443
500
  assertRevokeAuthority: async () => {
444
501
  if (!hostPolicy) throw new Error('privileged host plane is not configured');
445
- await assertHostArmed(hostPolicy);
502
+ await assertHostArmed(requirePlane('host',hostPolicy));
446
503
  }
447
504
  });
448
505
  }
449
506
 
450
- if (agentRuntime && surfaceProfile === 'full') {
451
- registerAgentTools(toolServer, { runtime: agentRuntime, workspacePathFromId });
507
+ if (registeredAgentRuntime && surfaceProfile === 'full') {
508
+ registerAgentTools(toolServer, { runtime: registeredAgentRuntime, workspacePathFromId });
452
509
  }
453
510
 
454
- if (processRuntime && surfaceProfile === 'full') {
455
- registerProcessTools(toolServer, { runtime: processRuntime });
511
+ if (registeredProcessRuntime && surfaceProfile === 'full') {
512
+ registerProcessTools(toolServer, { runtime: registeredProcessRuntime });
456
513
  }
457
514
 
458
- if (codingRuntime && codingTaskRuntime && semanticRuntime) {
515
+ if (registeredCodingRuntime && registeredCodingTaskRuntime && registeredSemanticRuntime) {
459
516
  const codingServer=surfaceProfile==='full'?toolServer:filteredToolServer(toolServer,COMPACT_CODING_DIRECT_TOOLS);
460
- registerCodingTools(codingServer, { codingRuntime, taskRuntime: codingTaskRuntime, semanticRuntime });
517
+ registerCodingTools(codingServer, { codingRuntime:registeredCodingRuntime, taskRuntime:registeredCodingTaskRuntime, semanticRuntime:registeredSemanticRuntime });
461
518
  }
462
519
 
463
- if (machineFsRuntime && surfaceProfile === 'full') {
464
- registerMachineFsTools(toolServer, { runtime: machineFsRuntime });
520
+ if (registeredMachineFsRuntime && surfaceProfile === 'full') {
521
+ registerMachineFsTools(toolServer, { runtime: registeredMachineFsRuntime });
465
522
  }
466
523
 
467
- if (observationRuntime && surfaceProfile === 'full') {
468
- registerObservationTools(toolServer, { runtime: observationRuntime });
524
+ if (registeredObservationRuntime && surfaceProfile === 'full') {
525
+ registerObservationTools(toolServer, { runtime: registeredObservationRuntime });
469
526
  }
470
527
 
471
- if (desktopRuntime && surfaceProfile === 'full') {
472
- registerDesktopTools(toolServer,{runtime:desktopRuntime});
528
+ if (registeredDesktopRuntime && surfaceProfile === 'full') {
529
+ registerDesktopTools(toolServer,{runtime:registeredDesktopRuntime});
473
530
  }
474
531
 
475
- if (autonomousRuntime && nativeDiffRuntime) {
476
- registerAutonomousTools(toolServer, { autonomousRuntime, nativeDiffRuntime });
532
+ if (registeredAutonomousRuntime && registeredNativeDiffRuntime) {
533
+ registerAutonomousTools(toolServer, { autonomousRuntime:registeredAutonomousRuntime, nativeDiffRuntime:registeredNativeDiffRuntime });
477
534
  }
478
535
 
479
- registerSkillToolsR44(toolServer,{runtime:skillRuntime});
536
+ registerSkillToolsR44(toolServer,{runtime:registeredSkillRuntime});
480
537
 
481
538
  registerCompactGatewayTools(toolServer,{
482
- profile:surfaceProfile,ledger:R36_CAPABILITY_LEDGER,codingRuntime,semanticRuntime,machineFsRuntime,
483
- processRuntime,observationRuntime,machineRuntime,desktopRuntime,skillRuntime,autonomousRuntime,hostPolicy,
484
- catalogProvider:()=>[...registeredToolNames]
539
+ profile:surfaceProfile,ledger:R36_CAPABILITY_LEDGER,codingRuntime:registeredCodingRuntime,
540
+ semanticRuntime:registeredSemanticRuntime,machineFsRuntime:registeredMachineFsRuntime,
541
+ processRuntime:registeredProcessRuntime,observationRuntime:registeredObservationRuntime,
542
+ machineRuntime:registeredMachineRuntime,desktopRuntime:registeredDesktopRuntime,
543
+ skillRuntime:registeredSkillRuntime,autonomousRuntime:registeredAutonomousRuntime,hostPolicy,
544
+ catalogProvider:()=>[...registeredToolNames],runtimePlanes:capabilityPlaneSnapshot,
545
+ releaseBindingProvider:currentReleaseBindings
485
546
  });
486
547
 
487
- if (hostPolicy) {
548
+ if (planeRegistry.state('host').configured) {
488
549
  toolServer.registerTool(
489
550
  'host_file_read',
490
551
  {
@@ -498,7 +559,7 @@ serveStdio(() => {
498
559
  },
499
560
  async ({ root_id, path: relativePath, encoding }) => {
500
561
  try {
501
- const result = await hostFileRead(hostPolicy, { rootId: root_id, relativePath, encoding });
562
+ const result = await hostFileRead(requirePlane('host',hostPolicy), { rootId: root_id, relativePath, encoding });
502
563
  return textResult(hostFileReadOutputSchema, { status: 'ok', root_id, path: relativePath, ...result });
503
564
  } catch (error) {
504
565
  return textResult(hostFileReadOutputSchema, { status: 'denied', error: String(error) }, true);
@@ -521,7 +582,7 @@ serveStdio(() => {
521
582
  },
522
583
  async ({ root_id, path: relativePath, content, encoding, expected_sha256 }) => {
523
584
  try {
524
- const result = await hostFileWrite(hostPolicy, {
585
+ const result = await hostFileWrite(requirePlane('host',hostPolicy), {
525
586
  rootId: root_id,
526
587
  relativePath,
527
588
  content,
@@ -585,7 +646,7 @@ serveStdio(() => {
585
646
  try {
586
647
  let result;
587
648
  if (args.mode === 'inline') {
588
- result = await hostExecInline(hostPolicy, {
649
+ result = await hostExecInline(requirePlane('host',hostPolicy), {
589
650
  commandId: args.command_id,
590
651
  rootId: args.root_id,
591
652
  command: args.command,
@@ -593,7 +654,7 @@ serveStdio(() => {
593
654
  timeoutMs: args.timeout_ms
594
655
  });
595
656
  } else if (args.mode === 'native') {
596
- result = await hostExecNative(hostPolicy, {
657
+ result = await hostExecNative(requirePlane('host',hostPolicy), {
597
658
  rootId: args.root_id,
598
659
  executable: args.executable,
599
660
  executableSha256: args.executable_sha256,
@@ -602,7 +663,7 @@ serveStdio(() => {
602
663
  timeoutMs: args.timeout_ms
603
664
  });
604
665
  } else {
605
- result = await hostExec(hostPolicy, {
666
+ result = await hostExec(requirePlane('host',hostPolicy), {
606
667
  commandId: args.command_id,
607
668
  rootId: args.root_id,
608
669
  scriptPath: args.script_path,
@@ -622,8 +683,8 @@ serveStdio(() => {
622
683
  }
623
684
 
624
685
  if (surfaceProfile === 'full') {
625
- registerCommanderCoreBridge(toolServer,{machineFsRuntime,processRuntime,searchRuntime:codingRuntime?.search??null,extendedRuntime:commanderExtendedRuntime,externalProcessRuntime:commanderExternalProcessRuntime,includeMarkdownEditor:true});
626
- registerCommanderExtendedBridge(toolServer,{extendedRuntime:commanderExtendedRuntime,observability:commanderObservability,skillPlane:skillRuntime});
686
+ registerCommanderCoreBridge(toolServer,{machineFsRuntime:registeredMachineFsRuntime,processRuntime:registeredProcessRuntime,searchRuntime:registeredCodingRuntime?.search??null,extendedRuntime:commanderExtendedRuntime,externalProcessRuntime:commanderExternalProcessRuntime,includeMarkdownEditor:true});
687
+ registerCommanderExtendedBridge(toolServer,{extendedRuntime:commanderExtendedRuntime,observability:commanderObservability,skillPlane:registeredSkillRuntime});
627
688
  registerCommanderRemoteBridge(toolServer,{remoteDevicePlane});
628
689
  registerCommanderHiddenUiDispatch(server);
629
690
  registerCommanderUiResources(server);
@@ -41,7 +41,7 @@ export async function probeR40CompactDisarmed(endpointText){
41
41
  for(const name of R40_COMPACT_GATEWAYS)if(!names.includes(name))throw new Error('R40 compact gateway missing '+name);
42
42
  for(const tool of listed.tools)if(tool.outputSchema?.type!=='object'||tool.outputSchema?.additionalProperties!==false||!tool.outputSchema?.properties)throw new Error('tool '+tool.name+' missing strict output schema');
43
43
  const manifest=gateway(await client.callTool({name:'capability_manifest',arguments:{}}),'capability_manifest');
44
- if(manifest.schema!=='deadbyte.capability-manifest.v2'||manifest.profile!=='compact'||manifest.tool_count!==names.length||
44
+ if(!['deadbyte.capability-manifest.v2','deadbyte.capability-manifest.v3'].includes(manifest.schema)||manifest.profile!=='compact'||manifest.tool_count!==names.length||
45
45
  JSON.stringify(manifest.tool_catalog)!==JSON.stringify(names))throw new Error('R40 compact manifest malformed');
46
46
  const required=manifest.capabilities.filter(x=>x?.production===true&&x?.host_only!==true);
47
47
  for(const item of required)if(typeof item.compact_tool!=='string'||!names.includes(item.compact_tool))throw new Error('compact route missing '+String(item.id));
@@ -41,7 +41,7 @@ export async function probeR44CompactDisarmed(endpointText){
41
41
  for(const name of R44_COMPACT_GATEWAYS)if(!names.includes(name))throw new Error('R44 compact gateway missing '+name);
42
42
  for(const tool of listed.tools)if(tool.outputSchema?.type!=='object'||tool.outputSchema?.additionalProperties!==false||!tool.outputSchema?.properties)throw new Error('tool '+tool.name+' missing strict output schema');
43
43
  const manifest=gateway(await client.callTool({name:'capability_manifest',arguments:{}}),'capability_manifest');
44
- if(manifest.schema!=='deadbyte.capability-manifest.v2'||manifest.profile!=='compact'||manifest.tool_count!==names.length||
44
+ if(!['deadbyte.capability-manifest.v2','deadbyte.capability-manifest.v3'].includes(manifest.schema)||manifest.profile!=='compact'||manifest.tool_count!==names.length||
45
45
  JSON.stringify(manifest.tool_catalog)!==JSON.stringify(names))throw new Error('R44 compact manifest malformed');
46
46
  const required=manifest.capabilities.filter(x=>x?.production===true&&x?.host_only!==true);
47
47
  for(const item of required)if(typeof item.compact_tool!=='string'||!names.includes(item.compact_tool))throw new Error('compact route missing '+String(item.id));
@@ -41,7 +41,7 @@ export async function probeR45CompactDisarmed(endpointText){
41
41
  for(const name of R45_COMPACT_GATEWAYS)if(!names.includes(name))throw new Error('R45 compact gateway missing '+name);
42
42
  for(const tool of listed.tools)if(tool.outputSchema?.type!=='object'||tool.outputSchema?.additionalProperties!==false||!tool.outputSchema?.properties)throw new Error('tool '+tool.name+' missing strict output schema');
43
43
  const manifest=gateway(await client.callTool({name:'capability_manifest',arguments:{}}),'capability_manifest');
44
- if(manifest.schema!=='deadbyte.capability-manifest.v2'||manifest.profile!=='compact'||manifest.tool_count!==names.length||
44
+ if(!['deadbyte.capability-manifest.v2','deadbyte.capability-manifest.v3'].includes(manifest.schema)||manifest.profile!=='compact'||manifest.tool_count!==names.length||
45
45
  JSON.stringify(manifest.tool_catalog)!==JSON.stringify(names))throw new Error('R45 compact manifest malformed');
46
46
  const required=manifest.capabilities.filter(x=>x?.production===true&&x?.host_only!==true);
47
47
  for(const item of required)if(typeof item.compact_tool!=='string'||!names.includes(item.compact_tool))throw new Error('compact route missing '+String(item.id));
@@ -0,0 +1,56 @@
1
+ import path from 'node:path';
2
+
3
+ export const AUTHORITY_PLANES=Object.freeze(['process','coding','autonomous','desktop','host']);
4
+
5
+ export function authorityVector(mode='default'){
6
+ if(!['default','desktop','host','full'].includes(mode)) throw new Error('remote authority mode invalid');
7
+ return Object.freeze({
8
+ process:true,coding:true,autonomous:true,
9
+ desktop:mode==='desktop'||mode==='full',
10
+ host:mode==='host'||mode==='full'
11
+ });
12
+ }
13
+
14
+ export function parseAuthorityObservation(raw){
15
+ let value;
16
+ try{value=typeof raw==='string'?JSON.parse(raw.replace(/^\uFEFF/,'')):raw;}
17
+ catch{throw new Error('controller observation JSON invalid');}
18
+ if(value?.schema!=='deadbyte.controller-observation.v1'||!value.authority||typeof value.authority!=='object'||Array.isArray(value.authority))
19
+ throw new Error('controller observation schema invalid');
20
+ const authority={};
21
+ for(const plane of AUTHORITY_PLANES){
22
+ const entry=value.authority[plane];
23
+ if(!entry||typeof entry!=='object'||typeof entry.armed!=='boolean'||typeof entry.configured!=='boolean'||typeof entry.reason!=='string')
24
+ throw new Error(`controller authority ${plane} observation invalid`);
25
+ authority[plane]=Object.freeze({configured:entry.configured,armed:entry.armed,reason:entry.reason.slice(0,128)});
26
+ }
27
+ return Object.freeze({...value,authority:Object.freeze(authority)});
28
+ }
29
+
30
+ export function assertAuthorityVector(snapshot,expected){
31
+ for(const plane of AUTHORITY_PLANES){
32
+ const entry=snapshot?.authority?.[plane];
33
+ if(!entry||typeof expected?.[plane]!=='boolean') throw new Error(`authority ${plane} observation or expectation invalid`);
34
+ if(entry.armed!==expected[plane]) throw new Error(`${plane} authority expected ${expected[plane]?'ARMED':'DISARMED'}; observed ${entry.armed?'ARMED':'DISARMED'} (${entry.reason})`);
35
+ if(expected[plane]&&!entry.configured) throw new Error(`${plane} authority unconfigured`);
36
+ }
37
+ return snapshot;
38
+ }
39
+
40
+ export function authorityBanner(snapshot){
41
+ return AUTHORITY_PLANES.map(plane=>`${plane} ${snapshot.authority[plane].armed?'ARMED':'DISARMED'}`).join(' | ');
42
+ }
43
+
44
+ export function assertRuntimeReadyObservation(snapshot,{coreRoot=null}={}){
45
+ if(snapshot?.state!=='ONLINE') throw new Error(`runtime state not ONLINE: ${String(snapshot?.state)}`);
46
+ for(const name of ['bridge','core','cloud']){
47
+ if(snapshot[name]?.alive!==true||snapshot[name]?.reason!=='verified') throw new Error(`${name} runtime identity unverified`);
48
+ }
49
+ if(snapshot.local_ready!==true) throw new Error('local MCP readiness unverified');
50
+ if(snapshot.supervisor?.running!==true) throw new Error('autonomous supervisor not running');
51
+ if(coreRoot!==null){
52
+ if(typeof snapshot.core_root!=='string'||path.win32.resolve(snapshot.core_root).toLowerCase()!==path.win32.resolve(coreRoot).toLowerCase())
53
+ throw new Error('core root does not match active release');
54
+ }
55
+ return snapshot;
56
+ }
@@ -0,0 +1,17 @@
1
+ import { authorityVector } from './remote-authority.mjs';
2
+
3
+ export async function probeRemoteEnforcement({client,mode='default'}={}){
4
+ if(!client||typeof client.callTool!=='function')throw new Error('remote enforcement client invalid');
5
+ const expected=mode==='revoked'?{desktop:false,host:false}:authorityVector(mode);
6
+ const desktop=await client.callTool({name:'desktop_control',arguments:{op:'status'}});
7
+ const desktopValue=desktop?.structuredContent;
8
+ const desktopArmed=desktop?.isError===false&&desktopValue?.status==='ok'&&desktopValue?.result?.armed===true;
9
+ const desktopUnavailable=desktop?.isError===true&&desktopValue?.status==='unavailable';
10
+ if(expected.desktop?!desktopArmed:desktopArmed||(!desktopUnavailable&&desktopValue?.result?.armed!==false))
11
+ throw new Error('Desktop enforcement does not match requested authority');
12
+ const host=await client.callTool({name:'host_file_read',arguments:{root_id:'core',path:'package.json',encoding:'utf8'}});
13
+ const hostArmed=host?.isError===false&&host?.structuredContent?.status==='ok'&&/^[0-9a-f]{64}$/.test(String(host.structuredContent.sha256??''));
14
+ const hostDenied=host?.isError===true&&host?.structuredContent?.status==='denied';
15
+ if(expected.host?!hostArmed:!hostDenied) throw new Error('Host enforcement does not match requested authority');
16
+ return Object.freeze({desktop_armed:desktopArmed,host_armed:hostArmed});
17
+ }
@@ -319,19 +319,21 @@ export function createLiveTimelineWriter({stream=process.stdout,displayMode='uni
319
319
  return Object.freeze({write,flush,pending(){return active?{...active}:null;}});
320
320
  }
321
321
 
322
- export function createLiveTimelineTracker({clock=()=>Date.now(),verbose=false,heartbeatBurstLimit=10,heartbeatWindowMs=3000,displayMode='unicode',rootPaths={},trace=false,slowCallMs=1000}={}){
322
+ export function createLiveTimelineTracker({clock=()=>Date.now(),verbose=false,foldHeartbeats=false,heartbeatBurstLimit=10,heartbeatWindowMs=3000,displayMode='unicode',rootPaths={},trace=false,slowCallMs=1000}={}){
323
323
  if(typeof clock!=='function') throw new Error('live timeline clock must be a function');
324
324
  if(!REMOTE_DISPLAY_MODES.includes(displayMode)) throw new Error('remote display mode invalid');
325
325
  if(!Number.isInteger(heartbeatBurstLimit)||heartbeatBurstLimit<2||heartbeatBurstLimit>100) throw new Error('heartbeatBurstLimit invalid');
326
326
  if(!Number.isInteger(heartbeatWindowMs)||heartbeatWindowMs<250||heartbeatWindowMs>60000) throw new Error('heartbeatWindowMs invalid');
327
327
  if(!rootPaths||typeof rootPaths!=='object'||Array.isArray(rootPaths)) throw new Error('live timeline rootPaths invalid');
328
328
  if(typeof trace!=='boolean') throw new Error('live timeline trace invalid');
329
+ if(typeof foldHeartbeats!=='boolean') throw new Error('live timeline foldHeartbeats invalid');
329
330
  if(!Number.isInteger(slowCallMs)||slowCallMs<100||slowCallMs>600000) throw new Error('live timeline slowCallMs invalid');
330
331
  const pending=new Map();
331
332
  const completed=new Set();
332
333
  const toolCounts=new Map();
333
334
  const durationSamples=[];
334
335
  let resultCount=0,okCount=0,errorCount=0,unknownCount=0,mutationCount=0,totalDurationMs=0,slowest=null,burst=null,foldedHeartbeatLines=0,peakInFlight=0;
336
+ let lastCapability=null,suppressedCapability=0,suppressedCapabilityReported=false;
335
337
 
336
338
  function eventPrefix(event,sequence,{displayTool=null,icon=null}={}){
337
339
  const seq=Number.isSafeInteger(sequence)&&sequence>0?'#'+sequence+' ':'';
@@ -419,7 +421,18 @@ export function createLiveTimelineTracker({clock=()=>Date.now(),verbose=false,he
419
421
  addStats(event,span);
420
422
  const error=event.outcome?.is_error===true;
421
423
  const nowMs=eventMs(event,clock);
422
- if(HEARTBEAT_TOOLS.has(tool)&&!error){
424
+ if(tool==='capability_manifest'&&!error){
425
+ const snapshot=event.outcome?.snapshot_id,epoch=event.outcome?.state_epoch;
426
+ if(/^[0-9a-f]{64}$/.test(String(snapshot??''))&&Number.isInteger(epoch)&&epoch>0){
427
+ const identity=`${snapshot}:${epoch}`;
428
+ if(identity===lastCapability){suppressedCapability++;return null;}
429
+ lastCapability=identity;
430
+ const prior=flushBurst();
431
+ const line=resultLine(event,span,sequence)+` snapshot=${snapshot.slice(0,8)} epoch=${epoch}`;
432
+ return prior?[prior,line]:line;
433
+ }
434
+ }
435
+ if(foldHeartbeats&&HEARTBEAT_TOOLS.has(tool)&&!error){
423
436
  const duration=Number(event.outcome?.duration_ms);
424
437
  if(burst&&burst.tool===tool&&nowMs-burst.last_ms<=heartbeatWindowMs){
425
438
  burst.count++;
@@ -449,6 +462,10 @@ export function createLiveTimelineTracker({clock=()=>Date.now(),verbose=false,he
449
462
  const lines=[];
450
463
  const folded=flushBurst();
451
464
  if(folded) lines.push(folded);
465
+ if(suppressedCapability>0&&!suppressedCapabilityReported){
466
+ lines.push(remoteDisplayText(`capability_manifest ×${suppressedCapability} unchanged suppressed`,displayMode));
467
+ suppressedCapabilityReported=true;
468
+ }
452
469
  for(const item of pending.values()) lines.push(remoteDisplayText((displayMode==='ascii'?'[WARN]':'⚠')+' ['+shortSpanId(item.request_id)+'] OUTCOME_UNKNOWN '+item.tool+' — '+suffix+'; inspect state before retry',displayMode));
453
470
  pending.clear();
454
471
  return lines;