deadbyte-mcp 0.15.55 → 0.15.58

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 (37) hide show
  1. package/MANIFEST.SHA256 +35 -23
  2. package/PROVENANCE.json +11 -11
  3. package/README.txt +18 -18
  4. package/RELEASE.json +24 -8
  5. package/SBOM.cdx.json +2 -2
  6. package/TEST-MATRIX.json +2 -2
  7. package/bridge/package.json +1 -1
  8. package/package.json +1 -1
  9. package/scripts/bootstrap-uac-migration-r153.ps1 +226 -0
  10. package/scripts/deploy-r48.mjs +133 -11
  11. package/scripts/issue-uac-migration-r153.mjs +107 -0
  12. package/scripts/r153-prepublish-identity.mjs +57 -0
  13. package/scripts/request-uac-migration-r153.ps1 +165 -0
  14. package/scripts/verify-protected-stage-r153.mjs +20 -0
  15. package/src/activation-preflight-r65.mjs +2 -1
  16. package/src/clean-activation-recovery-r153.mjs +297 -0
  17. package/src/deadbyte-cli.mjs +925 -720
  18. package/src/foreground-process-identity.mjs +31 -0
  19. package/src/legacy-offline-policy-proof-r146.mjs +31 -10
  20. package/src/runtime-update.mjs +19 -4
  21. package/src/uac-approval-contract-r153.mjs +104 -0
  22. package/src/version.mjs +1 -1
  23. package/test/commander-protocol-r47.test.mjs +6 -1
  24. package/test/r130-release-security-contract.test.mjs +8 -7
  25. package/test/r132-release-identity.test.mjs +8 -7
  26. package/test/r146-legacy-offline-policy-proof.test.mjs +31 -1
  27. package/test/r153-clean-activation-recovery.test.mjs +213 -0
  28. package/test/r153-prepublish-identity.test.mjs +40 -0
  29. package/test/r153-restricted-reused-pid.test.mjs +31 -0
  30. package/test/r153-uac-approval-contract.test.mjs +92 -0
  31. package/test/r153-uac-installed-manifest-contract.test.mjs +19 -0
  32. package/test/r153-uac-launch-parameter-contract.test.mjs +59 -0
  33. package/test/r58-concurrent-recovery.test.mjs +1 -1
  34. package/test/r59-tool-surface-compat.test.mjs +1 -1
  35. package/test/r65-activation-orchestration.test.mjs +20 -0
  36. package/test/remote-session-cli.test.mjs +1 -1
  37. package/node_modules/which/CHANGELOG.md +0 -166
@@ -1,653 +1,858 @@
1
1
  #!/usr/bin/env node
2
- import { closeSync, openSync } from 'node:fs';
3
- import { lstat, mkdir, open, readFile, readdir, stat, writeFile } from 'node:fs/promises';
4
- import { spawn, spawnSync } from 'node:child_process';
5
- import { createHash, randomBytes } from 'node:crypto';
6
- import os from 'node:os';
7
- import path from 'node:path';
8
- import { setTimeout as sleep } from 'node:timers/promises';
9
- import { fileURLToPath } from 'node:url';
10
- import { defaultPublicKeyPath } from './trust.mjs';
11
- import { verifyAuditChain } from './audit-verify.mjs';
12
- import { openRemoteResultJournal, parseRemoteResultCursor } from './remote-result-journal.mjs';
13
- import { DEADBYTE_VERSION } from './version.mjs';
14
- import { runNativeInspect } from './native-inspector-r67.mjs';
15
- import { exportOfflineDiagnostics } from './r67-diagnostic-export.mjs';
16
- import { verifyOfflineDiagnosticsZip } from './r67-diagnostics-verify.mjs';
17
- import { parseActivePointer } from './release-slot.mjs';
18
- import { printDoctor } from './doctor-r45.mjs';
19
- import { classifyRemoteAuditOutcome, createLiveTimelineFilter, createLiveTimelineTracker, createLiveTimelineWriter, formatCompactAuditEvent, formatRemoteLifecycle, formatRemoteToolCall, formatRuntimeDiagnosticLine, selectLiveLogNames } from './remote-live-log.mjs';
20
- import { prepareRemoteConsole, remoteDisplayText } from './remote-console.mjs';
21
- import { ensureRuntimeCoherence } from './runtime-coherence.mjs';
22
- import { windowsPowerShellEnvironment } from './runtime-update.mjs';
23
- import { resolveStateRoot } from './state-root.mjs';
24
- import {foregroundIdentityMatches,queryForegroundIdentity,validForegroundIdentity} from './foreground-process-identity.mjs';
25
- import {readRemoteMarkerSnapshot,deletePinnedRemoteMarker} from './foreground-marker-cas-win32.mjs';
26
- import {acquireForegroundSessionLock} from './foreground-session-lock.mjs';
27
- import { AUTHORITY_PLANES, authorityVector, authorityRestorePlan, parseAuthorityObservation, assertAuthorityVector, assertRuntimeReadyObservation, authorityBanner } from './remote-authority.mjs';
28
- import { decodeRemoteLogBytes, boundedRemoteDiagnostic, readRemoteLogAppend } from './remote-log-decode-r60.mjs';
29
-
30
- const REMOTE_COMMANDS=new Set([
31
- 'menu','start','resume','park','stop','restart','status','url','test','fulltest','toggle','clean','machinetest',
32
- 'armprocess','disarmprocess','processstatus','armhost','disarmhost','hoststatus','hosttest',
33
- 'armdesktop','disarmdesktop','desktopstatus',
34
- 'armcoding','disarmcoding','codingstatus','codingtest','armautonomous','disarmautonomous','autonomousstatus','autonomoustest'
35
- ]);
36
- const REMOTE_STATUS_TIMEOUT_MS=30000;
37
- const REMOTE_START_TIMEOUT_MS=150000;
38
- const SESSION_CLEANUP=['disarmautonomous','disarmcoding','disarmprocess','disarmdesktop','disarmhost'];
39
- const SUPERVISOR_COMMANDS=Object.freeze({
40
- start:'supervisorstart',stop:'supervisorstop',status:'supervisorstatus',recover:'supervisorrecover'
41
- });
42
- const CURRENT_PACKAGE_ROOT=path.resolve(fileURLToPath(new URL('..',import.meta.url)));
43
- const CURRENT_DEPLOY_SCRIPT=path.join(CURRENT_PACKAGE_ROOT,'scripts','deploy-r48.mjs');
44
- const REMOTE_UPDATE_TIMEOUT_MS=900000;
45
- const LIVE_LOG_DISCOVERY_INTERVAL_MS=1000;
2
+ import { closeSync, openSync } from 'node:fs';
3
+ import { lstat, mkdir, open, readFile, readdir, stat, writeFile } from 'node:fs/promises';
4
+ import { spawn, spawnSync } from 'node:child_process';
5
+ import { createHash, randomBytes } from 'node:crypto';
6
+ import os from 'node:os';
7
+ import path from 'node:path';
8
+ import { setTimeout as sleep } from 'node:timers/promises';
9
+ import { fileURLToPath } from 'node:url';
10
+ import { defaultPublicKeyPath } from './trust.mjs';
11
+ import { verifyAuditChain } from './audit-verify.mjs';
12
+ import { openRemoteResultJournal, parseRemoteResultCursor } from './remote-result-journal.mjs';
13
+ import { DEADBYTE_VERSION } from './version.mjs';
14
+ import { runNativeInspect } from './native-inspector-r67.mjs';
15
+ import { exportOfflineDiagnostics } from './r67-diagnostic-export.mjs';
16
+ import { verifyOfflineDiagnosticsZip } from './r67-diagnostics-verify.mjs';
17
+ import { parseActivePointer } from './release-slot.mjs';
18
+ import { printDoctor } from './doctor-r45.mjs';
19
+ import { classifyRemoteAuditOutcome, createLiveTimelineFilter, createLiveTimelineTracker, createLiveTimelineWriter, formatCompactAuditEvent, formatRemoteLifecycle, formatRemoteToolCall, formatRuntimeDiagnosticLine, selectLiveLogNames } from './remote-live-log.mjs';
20
+ import { prepareRemoteConsole, remoteDisplayText } from './remote-console.mjs';
21
+ import { ensureRuntimeCoherence } from './runtime-coherence.mjs';
22
+ import { windowsPowerShellEnvironment } from './runtime-update.mjs';
23
+ import { resolveStateRoot } from './state-root.mjs';
24
+ import {foregroundIdentityMatches,queryForegroundIdentity,validForegroundIdentity,proveRestrictedPidReuse} from './foreground-process-identity.mjs';
25
+ import {readRemoteMarkerSnapshot,deletePinnedRemoteMarker} from './foreground-marker-cas-win32.mjs';
26
+ import {acquireForegroundSessionLock} from './foreground-session-lock.mjs';
27
+ import { AUTHORITY_PLANES, authorityVector, authorityRestorePlan, parseAuthorityObservation, assertAuthorityVector, assertRuntimeReadyObservation, authorityBanner } from './remote-authority.mjs';
28
+ import { decodeRemoteLogBytes, boundedRemoteDiagnostic, readRemoteLogAppend } from './remote-log-decode-r60.mjs';
29
+ import {reconcileStaleMarker,resumeMarkerReconciliation,recoverPublishedMarkerTerminal} from './clean-activation-recovery-r153.mjs';
30
+
31
+ const REMOTE_COMMANDS=new Set([
32
+ 'menu','start','resume','park','stop','restart','status','url','test','fulltest','toggle','clean','machinetest',
33
+ 'armprocess','disarmprocess','processstatus','armhost','disarmhost','hoststatus','hosttest',
34
+ 'armdesktop','disarmdesktop','desktopstatus',
35
+ 'armcoding','disarmcoding','codingstatus','codingtest','armautonomous','disarmautonomous','autonomousstatus','autonomoustest'
36
+ ]);
37
+ const REMOTE_STATUS_TIMEOUT_MS=30000;
38
+ const REMOTE_START_TIMEOUT_MS=150000;
39
+ const SESSION_CLEANUP=['disarmautonomous','disarmcoding','disarmprocess','disarmdesktop','disarmhost'];
40
+ const SUPERVISOR_COMMANDS=Object.freeze({
41
+ start:'supervisorstart',stop:'supervisorstop',status:'supervisorstatus',recover:'supervisorrecover'
42
+ });
43
+ const CURRENT_PACKAGE_ROOT=path.resolve(fileURLToPath(new URL('..',import.meta.url)));
44
+ const CURRENT_DEPLOY_SCRIPT=path.join(CURRENT_PACKAGE_ROOT,'scripts','deploy-r48.mjs');
45
+ const UAC_BOOTSTRAP_SCRIPT=path.join(CURRENT_PACKAGE_ROOT,'scripts','bootstrap-uac-migration-r153.ps1');
46
+ const REMOTE_UPDATE_TIMEOUT_MS=900000;
47
+ const LIVE_LOG_DISCOVERY_INTERVAL_MS=1000;
46
48
  const TRUSTED_WINDOWS_ROOT='C:\\Windows';
47
-
48
- function stateRoot(){return resolveStateRoot();}
49
- async function requireRegular(file,label){const info=await lstat(file);if(!info.isFile()||info.isSymbolicLink()) throw new Error(`${label} must be a regular non-symlink file`);return file;}
50
- function printHelp(){
51
- const exact=`deadbyte-mcp@${DEADBYTE_VERSION}`;
52
- process.stdout.write([
53
- 'DEADBYTE MCP CLI','',
54
- ` npx -y ${exact} doctor # verify current package/release truth`,
55
- ` npx -y ${exact} mcp # stdio MCP server for local clients`,
56
- ` npx -y ${exact} remote # safe observation-only foreground session`,
57
- ` npx -y ${exact} remote --operator # process/coding/autonomous; explicit owner gates still apply`,
58
- ` npx -y ${exact} remote --desktop # session with Desktop authority; Host remains disarmed`,
59
- ` npx -y ${exact} remote --host # session with Host authority; Desktop remains disarmed`,
60
- ` npx -y ${exact} remote --full # explicit five-plane foreground session`,
61
- ` npx -y ${exact} remote --resume <cursor> # replay missed results, then reconnect`,
62
- ` npx -y ${exact} remote --trace # show trace/span identity without payload detail`,
63
- ` npx -y ${exact} remote --filter <expr> # presentation filter: tool/category/status/trace`,
64
- ` npx -y ${exact} remote status`,
65
- ` npx -y ${exact} remote restart`,
66
- ` npx -y ${exact} supervisor status`,
67
- ` npx -y ${exact} supervisor recover`,
68
- ` npx -y ${exact} audit verify`,
69
- ` npx -y ${exact} audit status`,
70
- ` npx -y ${exact} diagnostics export --output <local.zip> # offline, never uploads`,
71
- ` npx -y ${exact} diagnostics verify --input <local.zip> # local structural/CRC verify`,
72
- ` npx -y ${exact} inspect process [limit] # local native process snapshot`,
73
- ` npx -y ${exact} inspect identity PID # native process creation token`,
74
- ` npx -y ${exact} inspect memory self [limit] # local VirtualQueryEx metadata only`,
75
- ` npx -y ${exact} inspect memory PID <creation_filetime> [limit] # PID-reuse guarded`,
76
- ` npx -y ${exact} inspect pe <file> # local native PE32/PE32+ inspection`,''
77
- ].join('\n'));
78
- }
79
- async function remoteContext(){
80
- if(process.platform!=='win32') throw new Error('remote controller is currently Windows-only');
81
- const root=stateRoot();
82
- const launcher=await requireRegular(path.join(root,'bin','DEADBYTE-MCP.ps1'),'stable DEADBYTE launcher');
49
+
50
+ function stateRoot(){return resolveStateRoot();}
51
+ async function requireRegular(file,label){const info=await lstat(file);if(!info.isFile()||info.isSymbolicLink()) throw new Error(`${label} must be a regular non-symlink file`);return file;}
52
+ function printHelp(){
53
+ const exact=`deadbyte-mcp@${DEADBYTE_VERSION}`;
54
+ process.stdout.write([
55
+ 'DEADBYTE MCP CLI','',
56
+ ` npx -y ${exact} doctor # verify current package/release truth`,
57
+ ` npx -y ${exact} mcp # stdio MCP server for local clients`,
58
+ ` npx -y ${exact} remote # safe observation-only foreground session`,
59
+ ` npx -y ${exact} remote --operator # process/coding/autonomous; explicit owner gates still apply`,
60
+ ` npx -y ${exact} remote --desktop # session with Desktop authority; Host remains disarmed`,
61
+ ` npx -y ${exact} remote --host # session with Host authority; Desktop remains disarmed`,
62
+ ` npx -y ${exact} remote --full # explicit five-plane foreground session`,
63
+ ` npx -y ${exact} remote --resume <cursor> # replay missed results, then reconnect`,
64
+ ` npx -y ${exact} remote --trace # show trace/span identity without payload detail`,
65
+ ` npx -y ${exact} remote --filter <expr> # presentation filter: tool/category/status/trace`,
66
+ ` npx -y ${exact} remote status`,
67
+ ` npx -y ${exact} remote restart`,
68
+ ` npx -y ${exact} supervisor status`,
69
+ ` npx -y ${exact} supervisor recover`,
70
+ ` npx -y ${exact} audit verify`,
71
+ ` npx -y ${exact} audit status`,
72
+ ` npx -y ${exact} diagnostics export --output <local.zip> # offline, never uploads`,
73
+ ` npx -y ${exact} diagnostics verify --input <local.zip> # local structural/CRC verify`,
74
+ ` npx -y ${exact} inspect process [limit] # local native process snapshot`,
75
+ ` npx -y ${exact} inspect identity PID # native process creation token`,
76
+ ` npx -y ${exact} inspect memory self [limit] # local VirtualQueryEx metadata only`,
77
+ ` npx -y ${exact} inspect memory PID <creation_filetime> [limit] # PID-reuse guarded`,
78
+ ` npx -y ${exact} inspect pe <file> # local native PE32/PE32+ inspection`,''
79
+ ].join('\n'));
80
+ }
81
+ async function remoteContext(){
82
+ if(process.platform!=='win32') throw new Error('remote controller is currently Windows-only');
83
+ const root=stateRoot();
84
+ const launcher=await requireRegular(path.join(root,'bin','DEADBYTE-MCP.ps1'),'stable DEADBYTE launcher');
83
85
  const powershell=await requireRegular(path.join(TRUSTED_WINDOWS_ROOT,'System32','WindowsPowerShell','v1.0','powershell.exe'),'Windows PowerShell');
84
- return {root,launcher,powershell};
85
- }
86
- function boundedSingleLine(value,maxChars=2048){
87
- return boundedRemoteDiagnostic(value,maxChars);
88
- }
89
- async function readActiveRuntimeBinding(root){
90
- const file=path.join(root,'active-release.json');
91
- try{return parseActivePointer(await readFile(file,'utf8'));}
92
- catch(error){if(error?.code==='ENOENT') return null;throw new Error(`active runtime pointer invalid: ${boundedSingleLine(error?.message||error,512)}`);}
93
- }
94
- async function readLiveRootPaths(root){
95
- const active=await readActiveRuntimeBinding(root);
96
- if(!active) return Object.freeze({});
97
- const file=path.join(active.generation_root,'coding-policy.json');
98
- let raw;
99
- try{raw=JSON.parse(await readFile(file,'utf8'));}
100
- catch(error){if(error?.code==='ENOENT') return Object.freeze({});throw new Error(`live root policy invalid: ${boundedSingleLine(error?.message||error,512)}`);}
101
- if(raw?.schema!=='deadbyte.coding-policy.v1'||!raw.roots||typeof raw.roots!=='object'||Array.isArray(raw.roots)) throw new Error('live root policy schema invalid');
102
- const roots={};
103
- for(const [id,spec] of Object.entries(raw.roots)){
104
- if(!/^[A-Za-z0-9._-]{1,64}$/.test(id)||!spec||typeof spec!=='object'||typeof spec.path!=='string'||!path.isAbsolute(spec.path)) continue;
105
- roots[id]=path.resolve(spec.path);
106
- }
107
- return Object.freeze(roots);
108
- }
109
- async function reportVersionCoherence(root,{displayMode='ascii'}={}){
110
- const active=await readActiveRuntimeBinding(root);
111
- if(!active||active.version===DEADBYTE_VERSION) return active;
112
- writeRemote(process.stderr,`${remoteTag('warn',displayMode)} VERSION SKEW: CLI package ${DEADBYTE_VERSION}; active runtime ${active.version} (${active.release_id})\n`,displayMode);
113
- return active;
114
- }
115
- async function synchronizeForegroundRuntime(ctx,{displayMode='unicode'}={}){
116
- const packageManifestSha256=createHash('sha256').update(await readFile(path.join(CURRENT_PACKAGE_ROOT,'MANIFEST.SHA256'))).digest('hex');
117
- return ensureRuntimeCoherence({
118
- cliVersion:DEADBYTE_VERSION,
119
- packageManifestSha256,
120
- readActive:()=>readActiveRuntimeBinding(ctx.root),
121
- disarmPrivileged:async()=>{
122
- for(const command of ['disarmhost','disarmdesktop']){
123
- const result=invokeController(ctx,command,{capture:true,allowFailure:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
124
- if(result.status!==0) throw new Error(`runtime coherence '${command}' failed exit=${result.status}`);
125
- }
126
- },
127
- activateCurrentPackage:async()=>{
128
- const result=spawnSync(process.execPath,[CURRENT_DEPLOY_SCRIPT],{
129
- cwd:CURRENT_PACKAGE_ROOT,
130
- env:{...process.env,DEADBYTE_STATE_ROOT:ctx.root},
131
- encoding:'utf8',
132
- windowsHide:true,
133
- shell:false,
134
- timeout:REMOTE_UPDATE_TIMEOUT_MS,
135
- maxBuffer:16*1024*1024
136
- });
137
- if(result.error){
138
- if(result.error?.code==='ETIMEDOUT') throw new Error(`runtime coherence activation timed out after ${REMOTE_UPDATE_TIMEOUT_MS}ms`);
139
- throw result.error;
140
- }
141
- if(result.status!==0){
142
- const detail=boundedSingleLine(result.stderr||result.stdout||'no deployment output',2048);
143
- throw new Error(`runtime coherence activation failed exit=${String(result.status)}: ${detail}`);
144
- }
145
- },
146
- onEvent:event=>{
147
- if(event.phase==='upgrade_start') writeRemote(process.stdout,`[UPDATE] Runtime ${event.from_version} -> ${event.to_version}; activating current package...\n`,displayMode);
148
- else if(event.phase==='upgrade_complete') writeRemote(process.stdout,`[UPDATE] Runtime synchronized: ${event.release_id||event.to_version}\n`,displayMode);
149
- }
150
- });
151
- }
152
- async function synchronizeOneShotRuntime(ctx,{displayMode='ascii'}={}){
153
- const active=await readActiveRuntimeBinding(ctx.root);
154
- if(!active||active.version===DEADBYTE_VERSION) return synchronizeForegroundRuntime(ctx,{displayMode});
155
- const before=observedAuthority(ctx);
156
- const expected=Object.fromEntries(AUTHORITY_PLANES.map(plane=>[plane,before.authority[plane].armed]));
157
- const result=await synchronizeForegroundRuntime(ctx,{displayMode});
158
- if(result.status!=='upgraded') return result;
159
- for(const command of authorityRestorePlan(before)){
160
- const restored=invokeController(ctx,command,{capture:true,allowFailure:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
161
- if(restored.status!==0) throw new Error(`runtime coherence authority restore '${command}' failed exit=${restored.status}`);
162
- }
163
- assertAuthorityVector(observedAuthority(ctx),expected);
164
- return result;
165
- }
166
- async function readControllerStartFailure(root,command,{maxChars=2048}={}){
167
- const file=path.join(root,'runtime','controller-start-failure.json');
168
- let raw;
169
- try{raw=await readFile(file,'utf8');}catch(error){if(error?.code==='ENOENT') return null;throw error;}
170
- let value;
171
- try{value=JSON.parse(String(raw).replace(/^\uFEFF/,''));}catch{return null;}
172
- if(value?.schema!=='deadbyte.controller-start-failure.v1'||String(value?.command||'')!==command||typeof value?.message!=='string') return null;
173
- const message=boundedSingleLine(value.message,maxChars);
174
- return message?{file,message}:null;
175
- }
176
- async function readTailBounded(file,maxBytes=4096){
177
- try{
178
- const info=await stat(file);
179
- const length=Math.min(info.size,maxBytes);
180
- if(length===0) return '';
181
- const buffer=Buffer.alloc(length);
182
- const handle=await open(file,'r');
183
- let encoding=null;
184
- try{
185
- const header=Buffer.alloc(2);await handle.read(header,0,2,0);
186
- if(header[0]===0xff&&header[1]===0xfe)encoding='utf16le';
187
- await handle.read(buffer,0,length,info.size-length);
188
- }finally{await handle.close();}
189
- return boundedSingleLine(decodeRemoteLogBytes(file,buffer,{encoding}),maxBytes);
190
- }catch(error){if(error?.code==='ENOENT') return '';throw error;}
191
- }
192
- function invokeController(ctx,command,{capture=false,allowFailure=false,echoCaptured=true,timeoutMs=null,discardOutput=false,redirectOutput=null,json=false,probeMode=null}={}){
193
- if(capture&&discardOutput) throw new Error('invokeController cannot capture and discard output together');
194
- if(capture&&redirectOutput) throw new Error('invokeController cannot capture and redirect output together');
195
- if(discardOutput&&redirectOutput) throw new Error('invokeController cannot discard and redirect output together');
196
- let stdoutFd=null,stderrFd=null,result;
197
- try{
198
- let stdio;
199
- if(discardOutput) stdio=['ignore','ignore','ignore'];
200
- else if(redirectOutput){
201
- stdoutFd=openSync(redirectOutput.stdout_path,'w');
202
- stderrFd=openSync(redirectOutput.stderr_path,'w');
203
- stdio=['ignore',stdoutFd,stderrFd];
204
- }else stdio=capture?['ignore','pipe','pipe']:'inherit';
205
- const options={stdio,encoding:capture?'utf8':undefined,windowsHide:false,shell:false,
86
+ return {root,launcher,powershell};
87
+ }
88
+ function boundedSingleLine(value,maxChars=2048){
89
+ return boundedRemoteDiagnostic(value,maxChars);
90
+ }
91
+ async function readActiveRuntimeBinding(root){
92
+ const file=path.join(root,'active-release.json');
93
+ try{return parseActivePointer(await readFile(file,'utf8'));}
94
+ catch(error){if(error?.code==='ENOENT') return null;throw new Error(`active runtime pointer invalid: ${boundedSingleLine(error?.message||error,512)}`);}
95
+ }
96
+ async function readLiveRootPaths(root){
97
+ const active=await readActiveRuntimeBinding(root);
98
+ if(!active) return Object.freeze({});
99
+ const file=path.join(active.generation_root,'coding-policy.json');
100
+ let raw;
101
+ try{raw=JSON.parse(await readFile(file,'utf8'));}
102
+ catch(error){if(error?.code==='ENOENT') return Object.freeze({});throw new Error(`live root policy invalid: ${boundedSingleLine(error?.message||error,512)}`);}
103
+ if(raw?.schema!=='deadbyte.coding-policy.v1'||!raw.roots||typeof raw.roots!=='object'||Array.isArray(raw.roots)) throw new Error('live root policy schema invalid');
104
+ const roots={};
105
+ for(const [id,spec] of Object.entries(raw.roots)){
106
+ if(!/^[A-Za-z0-9._-]{1,64}$/.test(id)||!spec||typeof spec!=='object'||typeof spec.path!=='string'||!path.isAbsolute(spec.path)) continue;
107
+ roots[id]=path.resolve(spec.path);
108
+ }
109
+ return Object.freeze(roots);
110
+ }
111
+ async function reportVersionCoherence(root,{displayMode='ascii'}={}){
112
+ const active=await readActiveRuntimeBinding(root);
113
+ if(!active||active.version===DEADBYTE_VERSION) return active;
114
+ writeRemote(process.stderr,`${remoteTag('warn',displayMode)} VERSION SKEW: CLI package ${DEADBYTE_VERSION}; active runtime ${active.version} (${active.release_id})\n`,displayMode);
115
+ return active;
116
+ }
117
+ async function synchronizeForegroundRuntime(ctx,{displayMode='unicode',migrationContext=null}={}){
118
+ const packageManifestSha256=createHash('sha256').update(await readFile(path.join(CURRENT_PACKAGE_ROOT,'MANIFEST.SHA256'))).digest('hex');
119
+ return ensureRuntimeCoherence({
120
+ cliVersion:DEADBYTE_VERSION,
121
+ packageManifestSha256,
122
+ readActive:()=>readActiveRuntimeBinding(ctx.root),
123
+ disarmPrivileged:async()=>{
124
+ for(const command of ['disarmhost','disarmdesktop']){
125
+ const result=invokeController(ctx,command,{capture:true,allowFailure:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
126
+ if(result.status!==0) throw new Error(`runtime coherence '${command}' failed exit=${result.status}`);
127
+ }
128
+ },
129
+ activateCurrentPackage:async()=>{
130
+ let result=spawnSync(process.execPath,[CURRENT_DEPLOY_SCRIPT],{
131
+ cwd:CURRENT_PACKAGE_ROOT,
132
+ env:{...process.env,DEADBYTE_STATE_ROOT:ctx.root},
133
+ encoding:'utf8',
134
+ windowsHide:true,
135
+ shell:false,
136
+ timeout:REMOTE_UPDATE_TIMEOUT_MS,
137
+ maxBuffer:16*1024*1024
138
+ });
139
+ if(result.error){
140
+ if(result.error?.code==='ETIMEDOUT') throw new Error(`runtime coherence activation timed out after ${REMOTE_UPDATE_TIMEOUT_MS}ms`);
141
+ throw result.error;
142
+ }
143
+ if(result.status!==0){
144
+ const detail=boundedSingleLine(result.stderr||result.stdout||'no deployment output',2048);
145
+ if(/activation preflight rejected:\s*AUTHORITY_UNVERIFIED\b/.test(detail)){
146
+ if(!migrationContext?.receipt_path||!/^[0-9a-f]{64}$/.test(String(migrationContext.receipt_sha256??'')))
147
+ throw new Error('runtime legacy migration marker reconciliation receipt unavailable');
148
+ const expectedArtifact=path.join(ctx.root,'evidence','npm-publication',DEADBYTE_VERSION,`deadbyte-mcp-${DEADBYTE_VERSION}.tgz`);
149
+ await requireRegular(expectedArtifact,'exact release tarball');
150
+ const publicationDir=path.dirname(expectedArtifact),claimPath=path.join(publicationDir,'claim.json');
151
+ await requireRegular(claimPath,'npm publication claim');
152
+ const claim=JSON.parse((await readFile(claimPath,'utf8')).replace(/^\uFEFF/,''));
153
+ const artifactBytes=await readFile(expectedArtifact),artifactSha256=createHash('sha256').update(artifactBytes).digest('hex');
154
+ if(claim?.schema!=='deadbyte.npm-publication-claim.r65.v1'||claim.version!==DEADBYTE_VERSION||
155
+ claim.tarball_sha256!==artifactSha256||!/^[0-9a-f]{64}$/.test(String(claim.manifest_sha256??'')))
156
+ throw new Error('exact release tarball differs from immutable npm publication claim');
157
+ const publicationEvents=(await readdir(publicationDir)).filter(name=>/^event-\d+-[0-9a-f]{16}\.json$/.test(name));
158
+ let registryVerified=false;
159
+ for(const name of publicationEvents){
160
+ const event=JSON.parse((await readFile(path.join(publicationDir,name),'utf8')).replace(/^\uFEFF/,''));
161
+ if(event?.schema==='deadbyte.npm-publication-event.r65.v1'&&event.state==='REGISTRY_IDENTITY_VERIFIED'&&
162
+ event.tarball_sha256===artifactSha256)registryVerified=true;
163
+ }
164
+ if(!registryVerified)throw new Error('exact release tarball lacks registry identity verification evidence');
165
+ const systemTar=await requireRegular(path.join(TRUSTED_WINDOWS_ROOT,'System32','tar.exe'),'Windows tar');
166
+ const manifestRead=spawnSync(systemTar,['-xOf',expectedArtifact,'package/MANIFEST.SHA256'],{
167
+ encoding:'utf8',windowsHide:true,shell:false,timeout:30000,maxBuffer:4*1024*1024});
168
+ if(manifestRead.error||manifestRead.status!==0)throw new Error('exact release tarball manifest extraction failed');
169
+ const packagedManifest=manifestRead.stdout,packagedManifestSha256=createHash('sha256').update(packagedManifest,'utf8').digest('hex');
170
+ if(packagedManifestSha256!==claim.manifest_sha256)throw new Error('exact release tarball manifest identity mismatch');
171
+ const bootstrapLine=packagedManifest.split(/\r?\n/).find(line=>line.endsWith(' scripts/bootstrap-uac-migration-r153.ps1'));
172
+ const bootstrapMatch=/^([0-9a-f]{64}) scripts\/bootstrap-uac-migration-r153\.ps1$/.exec(bootstrapLine??'');
173
+ if(!bootstrapMatch)throw new Error('exact release tarball bootstrap identity missing');
174
+ const evidenceDir=path.join(ctx.root,'evidence','legacy-migration');
175
+ await mkdir(evidenceDir,{recursive:true});
176
+ const id=`r153-${Date.now()}-${randomBytes(8).toString('hex')}`;
177
+ const stdoutPath=path.join(evidenceDir,`${id}.stdout.log`),stderrPath=path.join(evidenceDir,`${id}.stderr.log`);
178
+ writeRemote(process.stdout,`${remoteTag('auth',displayMode)} Legacy broad-root migration requires one-time Windows UAC confirmation.\n`,displayMode);
179
+ result=spawnSync(ctx.powershell,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',UAC_BOOTSTRAP_SCRIPT,
180
+ '-ExpectedVersion',DEADBYTE_VERSION,'-StateRoot',ctx.root,'-TarballPath',expectedArtifact,
181
+ '-ExpectedTarballSha256',artifactSha256,'-ExpectedManifestSha256',packagedManifestSha256,
182
+ '-ExpectedBootstrapSha256',bootstrapMatch[1],
183
+ '-StdoutPath',stdoutPath,'-StderrPath',stderrPath,
184
+ '-MarkerReceiptPath',migrationContext.receipt_path,'-MarkerReceiptSha256',migrationContext.receipt_sha256],{
185
+ cwd:CURRENT_PACKAGE_ROOT,env:windowsPowerShellEnvironment(process.env),encoding:'utf8',windowsHide:true,shell:false,
186
+ timeout:REMOTE_UPDATE_TIMEOUT_MS,maxBuffer:16*1024*1024
187
+ });
188
+ if(result.error){
189
+ if(result.error?.code==='ETIMEDOUT')throw new Error(`runtime migration UAC timed out after ${REMOTE_UPDATE_TIMEOUT_MS}ms`);
190
+ throw result.error;
191
+ }
192
+ if(result.status===0)return;
193
+ const uacDetail=boundedSingleLine(result.stderr||result.stdout||'UAC was cancelled or migration failed',2048);
194
+ throw new Error(`runtime coherence UAC migration failed exit=${String(result.status)}: ${uacDetail}`);
195
+ }
196
+ throw new Error(`runtime coherence activation failed exit=${String(result.status)}: ${detail}`);
197
+ }
198
+ },
199
+ onEvent:event=>{
200
+ if(event.phase==='upgrade_start') writeRemote(process.stdout,`[UPDATE] Runtime ${event.from_version} -> ${event.to_version}; activating current package...\n`,displayMode);
201
+ else if(event.phase==='upgrade_complete') writeRemote(process.stdout,`[UPDATE] Runtime synchronized: ${event.release_id||event.to_version}\n`,displayMode);
202
+ }
203
+ });
204
+ }
205
+ async function synchronizeOneShotRuntime(ctx,{displayMode='ascii'}={}){
206
+ const active=await readActiveRuntimeBinding(ctx.root);
207
+ if(!active||active.version===DEADBYTE_VERSION) return synchronizeForegroundRuntime(ctx,{displayMode});
208
+ const before=observedAuthority(ctx);
209
+ const expected=Object.fromEntries(AUTHORITY_PLANES.map(plane=>[plane,before.authority[plane].armed]));
210
+ const result=await synchronizeForegroundRuntime(ctx,{displayMode});
211
+ if(result.status!=='upgraded') return result;
212
+ for(const command of authorityRestorePlan(before)){
213
+ const restored=invokeController(ctx,command,{capture:true,allowFailure:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
214
+ if(restored.status!==0) throw new Error(`runtime coherence authority restore '${command}' failed exit=${restored.status}`);
215
+ }
216
+ assertAuthorityVector(observedAuthority(ctx),expected);
217
+ return result;
218
+ }
219
+ async function readControllerStartFailure(root,command,{maxChars=2048}={}){
220
+ const file=path.join(root,'runtime','controller-start-failure.json');
221
+ let raw;
222
+ try{raw=await readFile(file,'utf8');}catch(error){if(error?.code==='ENOENT') return null;throw error;}
223
+ let value;
224
+ try{value=JSON.parse(String(raw).replace(/^\uFEFF/,''));}catch{return null;}
225
+ if(value?.schema!=='deadbyte.controller-start-failure.v1'||String(value?.command||'')!==command||typeof value?.message!=='string') return null;
226
+ const message=boundedSingleLine(value.message,maxChars);
227
+ return message?{file,message}:null;
228
+ }
229
+ async function readTailBounded(file,maxBytes=4096){
230
+ try{
231
+ const info=await stat(file);
232
+ const length=Math.min(info.size,maxBytes);
233
+ if(length===0) return '';
234
+ const buffer=Buffer.alloc(length);
235
+ const handle=await open(file,'r');
236
+ let encoding=null;
237
+ try{
238
+ const header=Buffer.alloc(2);await handle.read(header,0,2,0);
239
+ if(header[0]===0xff&&header[1]===0xfe)encoding='utf16le';
240
+ await handle.read(buffer,0,length,info.size-length);
241
+ }finally{await handle.close();}
242
+ return boundedSingleLine(decodeRemoteLogBytes(file,buffer,{encoding}),maxBytes);
243
+ }catch(error){if(error?.code==='ENOENT') return '';throw error;}
244
+ }
245
+ function invokeController(ctx,command,{capture=false,allowFailure=false,echoCaptured=true,timeoutMs=null,discardOutput=false,redirectOutput=null,json=false,probeMode=null}={}){
246
+ if(capture&&discardOutput) throw new Error('invokeController cannot capture and discard output together');
247
+ if(capture&&redirectOutput) throw new Error('invokeController cannot capture and redirect output together');
248
+ if(discardOutput&&redirectOutput) throw new Error('invokeController cannot discard and redirect output together');
249
+ let stdoutFd=null,stderrFd=null,result;
250
+ try{
251
+ let stdio;
252
+ if(discardOutput) stdio=['ignore','ignore','ignore'];
253
+ else if(redirectOutput){
254
+ stdoutFd=openSync(redirectOutput.stdout_path,'w');
255
+ stderrFd=openSync(redirectOutput.stderr_path,'w');
256
+ stdio=['ignore',stdoutFd,stderrFd];
257
+ }else stdio=capture?['ignore','pipe','pipe']:'inherit';
258
+ const options={stdio,encoding:capture?'utf8':undefined,windowsHide:false,shell:false,
206
259
  env:windowsPowerShellEnvironment({...process.env,SystemRoot:TRUSTED_WINDOWS_ROOT,WINDIR:TRUSTED_WINDOWS_ROOT,
207
260
  ...(probeMode?{DEADBYTE_REMOTE_PROBE_MODE:probeMode}:{})})};
208
- if(Number.isInteger(timeoutMs)&&timeoutMs>0) options.timeout=timeoutMs;
209
- result=spawnSync(ctx.powershell,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',ctx.launcher,command,...(json?['-Json']:[])],options);
210
- }finally{
211
- if(stdoutFd!==null) closeSync(stdoutFd);
212
- if(stderrFd!==null) closeSync(stderrFd);
213
- }
214
- if(result.error){
215
- if(result.error?.code==='ETIMEDOUT') throw new Error(`remote controller '${command}' timed out after ${timeoutMs}ms`);
216
- throw result.error;
217
- }
218
- const status=Number.isInteger(result.status)?result.status:1;
219
- const stdout=capture?String(result.stdout||''):'';
220
- const stderr=capture?String(result.stderr||''):'';
221
- if(capture&&echoCaptured){if(stdout) process.stdout.write(stdout);if(stderr) process.stderr.write(stderr);}
222
- if(status!==0&&!allowFailure) throw new Error(`remote controller '${command}' failed exit=${status}`);
223
- return {status,stdout,stderr};
224
- }
225
- function observedAuthority(ctx){
226
- const result=invokeController(ctx,'status',{capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS,json:true});
227
- return parseAuthorityObservation(result.stdout);
228
- }
229
- function controllerRuntimeReady(text){
230
- const value=String(text||'');
231
- return /^DEADBYTE MCP\s*=\s*ONLINE\s*$/m.test(value)&&
232
- /^Bridge PID\s*:\s*\d+\s+\[verified\]\s*$/m.test(value)&&
233
- /^Cloud PID\s*:\s*\d+\s+\[verified\]\s*$/m.test(value)&&
234
- /^Local ready\s*:\s*True\s*$/m.test(value)&&
235
- /^Loop supervisor:\s*RUNNING\s+\[verified\]\s*$/m.test(value);
236
- }
237
- function controllerRuntimeDegraded(text){
238
- return /^DEADBYTE MCP\s*=\s*(?:DEGRADED|FAILED)\s*$/m.test(String(text||''));
239
- }
240
- async function listLogFiles(root){
241
- const auditDir=path.join(root,'audit');
242
- const runtimeDir=path.join(root,'runtime','logs');
243
- let auditNames=[],runtimeNames=[];
244
- try{auditNames=await readdir(auditDir);}catch(error){if(error?.code!=='ENOENT') throw error;}
245
- try{runtimeNames=await readdir(runtimeDir);}catch(error){if(error?.code!=='ENOENT') throw error;}
246
- const selected=selectLiveLogNames({auditNames,runtimeNames});
247
- return [
248
- ...selected.audit.map(name=>path.join(auditDir,name)),
249
- ...selected.runtime.map(name=>path.join(runtimeDir,name))
250
- ];
251
- }
252
- function parseAuditLogLine(file,line){
253
- if(!/^segment-\d{8}\.jsonl$/.test(path.basename(file))||!line) return null;
254
- try{return JSON.parse(line);}catch{return null;}
255
- }
256
- function formatLogLine(file,line,{auditEvent=null,activityTracker=null,sequence=null,sourceSequence=null,verbose=false,displayMode='unicode'}={}){
257
- if(!line) return null;
258
- if(/^segment-\d{8}\.jsonl$/.test(path.basename(file))){
259
- const event=auditEvent??parseAuditLogLine(file,line);
260
- if(!event) return null;
261
- return activityTracker?activityTracker.observe(event,{sequence,sourceSequence}):formatCompactAuditEvent(event);
262
- }
263
- return formatRuntimeDiagnosticLine(file,line,{verbose,displayMode});
264
- }
265
- function remoteResultJournalPath(root,sessionId){return path.join(root,'runtime','remote-results',`${sessionId}.json`);}
266
- function auditTimelineRecord(file,line,auditEvent=null){
267
- const event=auditEvent??parseAuditLogLine(file,line);
268
- if(!event) return null;
269
- if(typeof event?.request_id!=='string'||!event.request_id||typeof event.tool!=='string'||!event.tool) return null;
270
- const stamp=[event.ts,event.created_at_utc,event.observed_at_utc].find(value=>typeof value==='string'&&Number.isFinite(Date.parse(value)));
271
- const observed=stamp?new Date(Date.parse(stamp)).toISOString():new Date().toISOString();
272
- const payload_sha256=createHash('sha256').update(Buffer.from(line,'utf8')).digest('hex');
273
- if(event.event_type==='tool.request') return {event_type:'tool.call',request_id:event.request_id,tool:event.tool,
274
- observed_at_utc:observed,arguments:event.args??{},payload_sha256};
275
- if(event.event_type==='tool.result'){
276
- const classified=classifyRemoteAuditOutcome(event);
277
- const unknown=classified==='unknown';
278
- const recoveryReason=unknown&&typeof event.outcome?.recovery?.reason==='string'?event.outcome.recovery.reason:null;
279
- return {event_type:'tool.result',request_id:event.request_id,tool:event.tool,
280
- status:classified==='pending'?'pending':classified==='ok'?'ok':'error',observed_at_utc:observed,payload_sha256,
281
- ...(Number.isFinite(Number(event.outcome?.duration_ms))?{duration_ms:Number(event.outcome.duration_ms)}:{}),
282
- ...(unknown?{side_effect_state:'unknown'}:{}),
283
- ...(typeof event.outcome?.reason==='string'&&event.outcome.reason?{reason:event.outcome.reason}:(recoveryReason?{reason:recoveryReason}:
284
- (classified==='pending'&&typeof event.outcome?.status==='string'?{reason:event.outcome.status}:{})))};
285
- }
286
- return null;
287
- }
288
- async function replayRemoteResults(root,cursor,{displayMode='unicode'}={}){
289
- const parsed=parseRemoteResultCursor(cursor);
290
- const file=remoteResultJournalPath(root,parsed.session_id);
291
- await requireRegular(file,'remote result journal');
292
- const journal=await openRemoteResultJournal({filePath:file,sessionId:parsed.session_id,maxEntries:2048});
293
- let next=cursor;
294
- for(;;){
295
- const page=await journal.replayAfter(next,{limit:200});
296
- for(const event of page.events){
297
- if(event.event_type==='tool.call'){
298
- const line=formatRemoteToolCall({event_type:'tool.request',tool:event.tool,request_id:event.request_id,
299
- observed_at_utc:event.observed_at_utc,args:event.arguments},{displayMode});
300
- process.stdout.write(remoteDisplayText(`${line} | REPLAY #${event.seq}\n`,displayMode));
301
- continue;
302
- }
303
- const unknown=event.side_effect_state==='unknown';
304
- const marker=unknown?'OUTCOME_UNKNOWN':event.status==='pending'?'PENDING':event.status==='error'?(displayMode==='ascii'?'ERR':'✗'):(displayMode==='ascii'?'OK':'✓');
305
- const duration=Number.isFinite(Number(event.duration_ms))?` ${event.duration_ms<1000?Math.round(event.duration_ms)+'ms':(event.duration_ms/1000).toFixed(2)+'s'}`:'';
306
- const reason=(event.status==='error'||event.status==='pending'||unknown)&&typeof event.reason==='string'&&event.reason?` — ${event.reason}`:'';
307
- process.stdout.write(remoteDisplayText(`[REPLAY] #${event.seq} ${event.tool}${duration} ${marker}${reason}\n`,displayMode));
308
- }
309
- next=page.next_cursor;
310
- if(!page.has_more) return next;
311
- }
312
- }
313
- async function readAppend(file,cursor){
314
- return readRemoteLogAppend(file,cursor);
315
- }
316
- async function snapshotRemoteLogOffsets(root){
317
- const offsets=new Map();
318
- const files=await listLogFiles(root);
319
- for(const file of files){
320
- const snapshot=await readRemoteLogAppend(file,null,{startAtEnd:true});
321
- if(snapshot.cursor)offsets.set(file,snapshot.cursor);
322
- }
323
- return offsets;
324
- }
325
- function timelineFilterEvent(timeline){
326
- if(!timeline) return null;
327
- if(timeline.event_type==='tool.call') return {
328
- event_type:'tool.request',request_id:timeline.request_id,tool:timeline.tool,args:timeline.arguments??{}
329
- };
330
- return {
331
- event_type:'tool.result',request_id:timeline.request_id,tool:timeline.tool,
332
- outcome:{
333
- status:timeline.side_effect_state==='unknown'?'interrupted':timeline.status,
334
- is_error:timeline.status==='error',
335
- ...(Number.isFinite(Number(timeline.duration_ms))?{duration_ms:Number(timeline.duration_ms)}:{}),
336
- ...(timeline.side_effect_state?{side_effect_state:timeline.side_effect_state}:{}),
337
- ...(timeline.reason?{reason:timeline.reason}:{})
338
- }
339
- };
340
- }
341
- async function tailRemoteLogs(root,signal,{journal=null,offsets=null,activityTracker=null,timelineFilter=null,timelineWriter=null,verbose=false,displayMode='unicode'}={}){
342
- process.stdout.write(verbose
343
- ? '[LOG] Verbose live timeline. Full sanitized request detail enabled; Ctrl+C disconnects and revokes authority.\n'
344
- : '[LOG] Human live timeline. Transport IN/OUT hidden; full replay/audit detail remains on disk. START/DONE retained; heartbeat bursts folded; Ctrl+C disconnects and revokes authority.\n');
345
- const activeOffsets=offsets??await snapshotRemoteLogOffsets(root);
346
- const partialLines=new Map();
347
- let liveFiles=[...activeOffsets.keys()];
348
- let nextDiscoveryAt=0;
349
- while(!signal.aborted){
350
- const now=Date.now();
351
- if(now>=nextDiscoveryAt){
352
- liveFiles=await listLogFiles(root);
353
- nextDiscoveryAt=now+LIVE_LOG_DISCOVERY_INTERVAL_MS;
354
- }
355
- for(const file of liveFiles){
356
- const prior=activeOffsets.has(file)?activeOffsets.get(file):null;
357
- const next=await readAppend(file,prior);
358
- activeOffsets.set(file,next.cursor);
359
- if(next.reset){
360
- partialLines.delete(file);
361
- process.stderr.write('[LIVELOG] STREAM_RESET '+path.basename(file)+' — '+next.resetReason+'; check audit continuity before trusting coverage\n');
362
- }
363
- if(!next.text)continue;
364
- const lines=((partialLines.get(file)??'')+next.text).split(/\r?\n/);
365
- partialLines.set(file,lines.pop()??'');
366
- if(Buffer.byteLength(partialLines.get(file),'utf8')>1024*1024) throw new Error(`remote log line exceeds bounded decode limit: ${path.basename(file)}`);
367
- for(const line of lines){
368
- if(Buffer.byteLength(line,'utf8')>1024*1024) throw new Error(`remote log line exceeds bounded decode limit: ${path.basename(file)}`);
369
- const auditEvent=parseAuditLogLine(file,line);
370
- if(/^segment-\d{8}\.jsonl$/.test(path.basename(file))&&!auditEvent)
371
- throw new Error('LIVELOG_AUDIT_RECORD_INVALID '+path.basename(file)+'; refusing to silently skip audit bytes');
372
- const timeline=auditTimelineRecord(file,line,auditEvent);
373
- let recorded=null;
374
- if(timeline&&journal) recorded=timeline.event_type==='tool.call'
375
- ? await journal.recordCall(timeline)
376
- : await journal.recordTerminal(timeline);
377
- if(recorded?.duplicate) continue;
378
- const accepted=timelineFilter&&timeline?timelineFilter.accept(timelineFilterEvent(timeline)):true;
379
- const formatted=formatLogLine(file,line,{auditEvent,activityTracker,sequence:recorded?.event?.seq??null,
380
- sourceSequence:Number.isSafeInteger(auditEvent?.seq)?auditEvent.seq:null,verbose,displayMode});
381
- if(!formatted||!accepted) continue;
382
- const output=Array.isArray(formatted)?formatted:[formatted];
383
- for(const item of output) if(item){
384
- if(timelineWriter) timelineWriter.write(item,{event_type:timeline?.event_type??null,request_id:timeline?.request_id??null});
385
- else process.stdout.write(`${item}\n`);
386
- }
387
- }
388
- }
389
- try{await sleep(250,null,{signal});}catch(error){if(error?.name!=='AbortError') throw error;}
390
- }
391
- }
392
- function remoteTag(kind,displayMode){
393
- const unicode={warn:'⚠️ [WARN]',recovery:'♻️ [RECOVERY]',auth:'🔐 [AUTH]'};
394
- const ascii={warn:'[WARN]',recovery:'[RECOVERY]',auth:'[AUTH]'};
395
- return (displayMode==='ascii'?ascii:unicode)[kind];
396
- }
397
- function writeRemote(stream,text,displayMode){stream.write(remoteDisplayText(text,displayMode));}
398
- async function cleanupRemoteSession(ctx,{displayMode='unicode'}={}){
399
- const failed=[];
400
- for(const command of SESSION_CLEANUP){
401
- try{
402
- const result=invokeController(ctx,command,{allowFailure:true,capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
261
+ if(Number.isInteger(timeoutMs)&&timeoutMs>0) options.timeout=timeoutMs;
262
+ result=spawnSync(ctx.powershell,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',ctx.launcher,command,...(json?['-Json']:[])],options);
263
+ }finally{
264
+ if(stdoutFd!==null) closeSync(stdoutFd);
265
+ if(stderrFd!==null) closeSync(stderrFd);
266
+ }
267
+ if(result.error){
268
+ if(result.error?.code==='ETIMEDOUT') throw new Error(`remote controller '${command}' timed out after ${timeoutMs}ms`);
269
+ throw result.error;
270
+ }
271
+ const status=Number.isInteger(result.status)?result.status:1;
272
+ const stdout=capture?String(result.stdout||''):'';
273
+ const stderr=capture?String(result.stderr||''):'';
274
+ if(capture&&echoCaptured){if(stdout) process.stdout.write(stdout);if(stderr) process.stderr.write(stderr);}
275
+ if(status!==0&&!allowFailure) throw new Error(`remote controller '${command}' failed exit=${status}`);
276
+ return {status,stdout,stderr};
277
+ }
278
+ function observedAuthority(ctx){
279
+ const result=invokeController(ctx,'status',{capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS,json:true});
280
+ return parseAuthorityObservation(result.stdout);
281
+ }
282
+ function controllerRuntimeReady(text){
283
+ const value=String(text||'');
284
+ return /^DEADBYTE MCP\s*=\s*ONLINE\s*$/m.test(value)&&
285
+ /^Bridge PID\s*:\s*\d+\s+\[verified\]\s*$/m.test(value)&&
286
+ /^Cloud PID\s*:\s*\d+\s+\[verified\]\s*$/m.test(value)&&
287
+ /^Local ready\s*:\s*True\s*$/m.test(value)&&
288
+ /^Loop supervisor:\s*RUNNING\s+\[verified\]\s*$/m.test(value);
289
+ }
290
+ function controllerRuntimeDegraded(text){
291
+ return /^DEADBYTE MCP\s*=\s*(?:DEGRADED|FAILED)\s*$/m.test(String(text||''));
292
+ }
293
+ async function listLogFiles(root){
294
+ const auditDir=path.join(root,'audit');
295
+ const runtimeDir=path.join(root,'runtime','logs');
296
+ let auditNames=[],runtimeNames=[];
297
+ try{auditNames=await readdir(auditDir);}catch(error){if(error?.code!=='ENOENT') throw error;}
298
+ try{runtimeNames=await readdir(runtimeDir);}catch(error){if(error?.code!=='ENOENT') throw error;}
299
+ const selected=selectLiveLogNames({auditNames,runtimeNames});
300
+ return [
301
+ ...selected.audit.map(name=>path.join(auditDir,name)),
302
+ ...selected.runtime.map(name=>path.join(runtimeDir,name))
303
+ ];
304
+ }
305
+ function parseAuditLogLine(file,line){
306
+ if(!/^segment-\d{8}\.jsonl$/.test(path.basename(file))||!line) return null;
307
+ try{return JSON.parse(line);}catch{return null;}
308
+ }
309
+ function formatLogLine(file,line,{auditEvent=null,activityTracker=null,sequence=null,sourceSequence=null,verbose=false,displayMode='unicode'}={}){
310
+ if(!line) return null;
311
+ if(/^segment-\d{8}\.jsonl$/.test(path.basename(file))){
312
+ const event=auditEvent??parseAuditLogLine(file,line);
313
+ if(!event) return null;
314
+ return activityTracker?activityTracker.observe(event,{sequence,sourceSequence}):formatCompactAuditEvent(event);
315
+ }
316
+ return formatRuntimeDiagnosticLine(file,line,{verbose,displayMode});
317
+ }
318
+ function remoteResultJournalPath(root,sessionId){return path.join(root,'runtime','remote-results',`${sessionId}.json`);}
319
+ function auditTimelineRecord(file,line,auditEvent=null){
320
+ const event=auditEvent??parseAuditLogLine(file,line);
321
+ if(!event) return null;
322
+ if(typeof event?.request_id!=='string'||!event.request_id||typeof event.tool!=='string'||!event.tool) return null;
323
+ const stamp=[event.ts,event.created_at_utc,event.observed_at_utc].find(value=>typeof value==='string'&&Number.isFinite(Date.parse(value)));
324
+ const observed=stamp?new Date(Date.parse(stamp)).toISOString():new Date().toISOString();
325
+ const payload_sha256=createHash('sha256').update(Buffer.from(line,'utf8')).digest('hex');
326
+ if(event.event_type==='tool.request') return {event_type:'tool.call',request_id:event.request_id,tool:event.tool,
327
+ observed_at_utc:observed,arguments:event.args??{},payload_sha256};
328
+ if(event.event_type==='tool.result'){
329
+ const classified=classifyRemoteAuditOutcome(event);
330
+ const unknown=classified==='unknown';
331
+ const recoveryReason=unknown&&typeof event.outcome?.recovery?.reason==='string'?event.outcome.recovery.reason:null;
332
+ return {event_type:'tool.result',request_id:event.request_id,tool:event.tool,
333
+ status:classified==='pending'?'pending':classified==='ok'?'ok':'error',observed_at_utc:observed,payload_sha256,
334
+ ...(Number.isFinite(Number(event.outcome?.duration_ms))?{duration_ms:Number(event.outcome.duration_ms)}:{}),
335
+ ...(unknown?{side_effect_state:'unknown'}:{}),
336
+ ...(typeof event.outcome?.reason==='string'&&event.outcome.reason?{reason:event.outcome.reason}:(recoveryReason?{reason:recoveryReason}:
337
+ (classified==='pending'&&typeof event.outcome?.status==='string'?{reason:event.outcome.status}:{})))};
338
+ }
339
+ return null;
340
+ }
341
+ async function replayRemoteResults(root,cursor,{displayMode='unicode'}={}){
342
+ const parsed=parseRemoteResultCursor(cursor);
343
+ const file=remoteResultJournalPath(root,parsed.session_id);
344
+ await requireRegular(file,'remote result journal');
345
+ const journal=await openRemoteResultJournal({filePath:file,sessionId:parsed.session_id,maxEntries:2048});
346
+ let next=cursor;
347
+ for(;;){
348
+ const page=await journal.replayAfter(next,{limit:200});
349
+ for(const event of page.events){
350
+ if(event.event_type==='tool.call'){
351
+ const line=formatRemoteToolCall({event_type:'tool.request',tool:event.tool,request_id:event.request_id,
352
+ observed_at_utc:event.observed_at_utc,args:event.arguments},{displayMode});
353
+ process.stdout.write(remoteDisplayText(`${line} | REPLAY #${event.seq}\n`,displayMode));
354
+ continue;
355
+ }
356
+ const unknown=event.side_effect_state==='unknown';
357
+ const marker=unknown?'OUTCOME_UNKNOWN':event.status==='pending'?'PENDING':event.status==='error'?(displayMode==='ascii'?'ERR':'✗'):(displayMode==='ascii'?'OK':'✓');
358
+ const duration=Number.isFinite(Number(event.duration_ms))?` ${event.duration_ms<1000?Math.round(event.duration_ms)+'ms':(event.duration_ms/1000).toFixed(2)+'s'}`:'';
359
+ const reason=(event.status==='error'||event.status==='pending'||unknown)&&typeof event.reason==='string'&&event.reason?` — ${event.reason}`:'';
360
+ process.stdout.write(remoteDisplayText(`[REPLAY] #${event.seq} ${event.tool}${duration} ${marker}${reason}\n`,displayMode));
361
+ }
362
+ next=page.next_cursor;
363
+ if(!page.has_more) return next;
364
+ }
365
+ }
366
+ async function readAppend(file,cursor){
367
+ return readRemoteLogAppend(file,cursor);
368
+ }
369
+ async function snapshotRemoteLogOffsets(root){
370
+ const offsets=new Map();
371
+ const files=await listLogFiles(root);
372
+ for(const file of files){
373
+ const snapshot=await readRemoteLogAppend(file,null,{startAtEnd:true});
374
+ if(snapshot.cursor)offsets.set(file,snapshot.cursor);
375
+ }
376
+ return offsets;
377
+ }
378
+ function timelineFilterEvent(timeline){
379
+ if(!timeline) return null;
380
+ if(timeline.event_type==='tool.call') return {
381
+ event_type:'tool.request',request_id:timeline.request_id,tool:timeline.tool,args:timeline.arguments??{}
382
+ };
383
+ return {
384
+ event_type:'tool.result',request_id:timeline.request_id,tool:timeline.tool,
385
+ outcome:{
386
+ status:timeline.side_effect_state==='unknown'?'interrupted':timeline.status,
387
+ is_error:timeline.status==='error',
388
+ ...(Number.isFinite(Number(timeline.duration_ms))?{duration_ms:Number(timeline.duration_ms)}:{}),
389
+ ...(timeline.side_effect_state?{side_effect_state:timeline.side_effect_state}:{}),
390
+ ...(timeline.reason?{reason:timeline.reason}:{})
391
+ }
392
+ };
393
+ }
394
+ async function tailRemoteLogs(root,signal,{journal=null,offsets=null,activityTracker=null,timelineFilter=null,timelineWriter=null,verbose=false,displayMode='unicode'}={}){
395
+ process.stdout.write(verbose
396
+ ? '[LOG] Verbose live timeline. Full sanitized request detail enabled; Ctrl+C disconnects and revokes authority.\n'
397
+ : '[LOG] Human live timeline. Transport IN/OUT hidden; full replay/audit detail remains on disk. START/DONE retained; heartbeat bursts folded; Ctrl+C disconnects and revokes authority.\n');
398
+ const activeOffsets=offsets??await snapshotRemoteLogOffsets(root);
399
+ const partialLines=new Map();
400
+ let liveFiles=[...activeOffsets.keys()];
401
+ let nextDiscoveryAt=0;
402
+ while(!signal.aborted){
403
+ const now=Date.now();
404
+ if(now>=nextDiscoveryAt){
405
+ liveFiles=await listLogFiles(root);
406
+ nextDiscoveryAt=now+LIVE_LOG_DISCOVERY_INTERVAL_MS;
407
+ }
408
+ for(const file of liveFiles){
409
+ const prior=activeOffsets.has(file)?activeOffsets.get(file):null;
410
+ const next=await readAppend(file,prior);
411
+ activeOffsets.set(file,next.cursor);
412
+ if(next.reset){
413
+ partialLines.delete(file);
414
+ process.stderr.write('[LIVELOG] STREAM_RESET '+path.basename(file)+' — '+next.resetReason+'; check audit continuity before trusting coverage\n');
415
+ }
416
+ if(!next.text)continue;
417
+ const lines=((partialLines.get(file)??'')+next.text).split(/\r?\n/);
418
+ partialLines.set(file,lines.pop()??'');
419
+ if(Buffer.byteLength(partialLines.get(file),'utf8')>1024*1024) throw new Error(`remote log line exceeds bounded decode limit: ${path.basename(file)}`);
420
+ for(const line of lines){
421
+ if(Buffer.byteLength(line,'utf8')>1024*1024) throw new Error(`remote log line exceeds bounded decode limit: ${path.basename(file)}`);
422
+ const auditEvent=parseAuditLogLine(file,line);
423
+ if(/^segment-\d{8}\.jsonl$/.test(path.basename(file))&&!auditEvent)
424
+ throw new Error('LIVELOG_AUDIT_RECORD_INVALID '+path.basename(file)+'; refusing to silently skip audit bytes');
425
+ const timeline=auditTimelineRecord(file,line,auditEvent);
426
+ let recorded=null;
427
+ if(timeline&&journal) recorded=timeline.event_type==='tool.call'
428
+ ? await journal.recordCall(timeline)
429
+ : await journal.recordTerminal(timeline);
430
+ if(recorded?.duplicate) continue;
431
+ const accepted=timelineFilter&&timeline?timelineFilter.accept(timelineFilterEvent(timeline)):true;
432
+ const formatted=formatLogLine(file,line,{auditEvent,activityTracker,sequence:recorded?.event?.seq??null,
433
+ sourceSequence:Number.isSafeInteger(auditEvent?.seq)?auditEvent.seq:null,verbose,displayMode});
434
+ if(!formatted||!accepted) continue;
435
+ const output=Array.isArray(formatted)?formatted:[formatted];
436
+ for(const item of output) if(item){
437
+ if(timelineWriter) timelineWriter.write(item,{event_type:timeline?.event_type??null,request_id:timeline?.request_id??null});
438
+ else process.stdout.write(`${item}\n`);
439
+ }
440
+ }
441
+ }
442
+ try{await sleep(250,null,{signal});}catch(error){if(error?.name!=='AbortError') throw error;}
443
+ }
444
+ }
445
+ function remoteTag(kind,displayMode){
446
+ const unicode={warn:'⚠️ [WARN]',recovery:'♻️ [RECOVERY]',auth:'🔐 [AUTH]'};
447
+ const ascii={warn:'[WARN]',recovery:'[RECOVERY]',auth:'[AUTH]'};
448
+ return (displayMode==='ascii'?ascii:unicode)[kind];
449
+ }
450
+ function writeRemote(stream,text,displayMode){stream.write(remoteDisplayText(text,displayMode));}
451
+ async function cleanupRemoteSession(ctx,{displayMode='unicode'}={}){
452
+ const failed=[];
453
+ for(const command of SESSION_CLEANUP){
454
+ try{
455
+ const result=invokeController(ctx,command,{allowFailure:true,capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
403
456
  if(result.status!==0){
404
457
  failed.push(command);
405
458
  const detail=boundedSingleLine(result.stderr||result.stdout||'controller returned no diagnostic',512);
406
459
  writeRemote(process.stderr,`${remoteTag('warn',displayMode)} cleanup ${command} exit=${result.status}: ${detail}\n`,displayMode);
407
- }
408
- }
409
- catch(error){failed.push(command);writeRemote(process.stderr,`${remoteTag('warn',displayMode)} cleanup ${command}: ${String(error?.message||error)}\n`,displayMode);}
410
- }
411
- if(failed.length) throw new Error(`remote session cleanup failed; ownership marker retained: ${failed.join(',')}`);
412
- let snapshot;
413
- try{snapshot=assertAuthorityVector(observedAuthority(ctx),Object.fromEntries(AUTHORITY_PLANES.map(plane=>[plane,false])));}
414
- catch(error){throw new Error(`remote session cleanup verification failed; ownership marker retained: ${String(error?.message||error)}`);}
415
- if(snapshot.state==='ONLINE'){
416
- try{invokeController(ctx,'machinetest',{capture:true,echoCaptured:false,timeoutMs:REMOTE_START_TIMEOUT_MS,probeMode:'revoked'});}
417
- catch(error){throw new Error(`remote session enforcement cleanup verification failed; ownership marker retained: ${String(error?.message||error)}`);}
418
- }
419
- const parked=invokeController(ctx,'park',{allowFailure:true,capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
420
- if(parked.status!==0) throw new Error(`remote session park failed exit=${parked.status}; ownership marker retained`);
421
- }
422
- const GUARDIAN_SCRIPT=fileURLToPath(new URL('./remote-session-guardian.mjs',import.meta.url));
423
- function remoteSessionMarker(root){return path.join(root,'runtime','remote-session.json');}
424
- function pidAlive(pid){
425
- if(!Number.isInteger(pid)||pid<1)return false;
426
- try{process.kill(pid,0);return true;}
427
- catch(error){return error?.code!=='ESRCH';}
428
- }
429
- function remoteOwnerPid(marker){return marker?.schema==='deadbyte.remote-session.v2'?marker.owner_pid:marker?.pid;}
430
- async function readRemoteSessionMarker(root){
431
- const file=remoteSessionMarker(root);
432
- let text;try{text=await readFile(file,'utf8');}catch(error){if(error?.code==='ENOENT') return null;throw error;}
433
- let value;try{value=JSON.parse(text);}catch{throw new Error('remote session marker is invalid JSON');}
434
- if(value?.schema==='deadbyte.remote-session.v1'){
435
- if(!Number.isInteger(value?.pid)||value.pid<1) throw new Error('remote session marker schema invalid');
436
- return value;
437
- }
438
- if(value?.schema==='deadbyte.remote-session.v2'){
439
- for(const key of ['owner_identity','guardian_identity'])if(value[key]!==undefined&&!validForegroundIdentity(value[key]))throw new Error('remote session ownership identity invalid');
440
- if(!Number.isInteger(value?.owner_pid)||value.owner_pid<1||
441
- !/^[0-9a-f]{64}$/.test(String(value?.session_nonce||''))||
442
- !Number.isInteger(value?.guardian_pid)||value.guardian_pid<0||
443
- (value.result_session_id!==undefined&&!/^[0-9a-f]{24}$/.test(String(value.result_session_id)))) throw new Error('remote session marker schema invalid');
444
- return value;
445
- }
446
- throw new Error('remote session marker schema invalid');
447
- }
448
- async function recoverRemoteSession(ctx,{displayMode='unicode'}={}){
449
- let prior=await readRemoteSessionMarker(ctx.root);
450
- if(!prior) return;
451
- const ownerPid=remoteOwnerPid(prior);
452
- if(pidAlive(ownerPid)){
453
- if(!prior.owner_identity)throw new Error(`remote session ownership unverified for legacy pid=${ownerPid}; marker retained`);
460
+ }
461
+ }
462
+ catch(error){failed.push(command);writeRemote(process.stderr,`${remoteTag('warn',displayMode)} cleanup ${command}: ${String(error?.message||error)}\n`,displayMode);}
463
+ }
464
+ if(failed.length) throw new Error(`remote session cleanup failed; ownership marker retained: ${failed.join(',')}`);
465
+ let snapshot;
466
+ try{snapshot=assertAuthorityVector(observedAuthority(ctx),Object.fromEntries(AUTHORITY_PLANES.map(plane=>[plane,false])));}
467
+ catch(error){throw new Error(`remote session cleanup verification failed; ownership marker retained: ${String(error?.message||error)}`);}
468
+ if(snapshot.state==='ONLINE'){
469
+ try{invokeController(ctx,'machinetest',{capture:true,echoCaptured:false,timeoutMs:REMOTE_START_TIMEOUT_MS,probeMode:'revoked'});}
470
+ catch(error){throw new Error(`remote session enforcement cleanup verification failed; ownership marker retained: ${String(error?.message||error)}`);}
471
+ }
472
+ const parked=invokeController(ctx,'park',{allowFailure:true,capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
473
+ if(parked.status!==0) throw new Error(`remote session park failed exit=${parked.status}; ownership marker retained`);
474
+ }
475
+ const GUARDIAN_SCRIPT=fileURLToPath(new URL('./remote-session-guardian.mjs',import.meta.url));
476
+ function remoteSessionMarker(root){return path.join(root,'runtime','remote-session.json');}
477
+ function pidAlive(pid){
478
+ if(!Number.isInteger(pid)||pid<1)return false;
479
+ try{process.kill(pid,0);return true;}
480
+ catch(error){return error?.code!=='ESRCH';}
481
+ }
482
+ function remoteOwnerPid(marker){return marker?.schema==='deadbyte.remote-session.v2'?marker.owner_pid:marker?.pid;}
483
+ async function readRemoteSessionMarker(root){
484
+ const file=remoteSessionMarker(root);
485
+ let text;try{text=await readFile(file,'utf8');}catch(error){if(error?.code==='ENOENT') return null;throw error;}
486
+ let value;try{value=JSON.parse(text);}catch{throw new Error('remote session marker is invalid JSON');}
487
+ if(value?.schema==='deadbyte.remote-session.v1'){
488
+ if(!Number.isInteger(value?.pid)||value.pid<1) throw new Error('remote session marker schema invalid');
489
+ return value;
490
+ }
491
+ if(value?.schema==='deadbyte.remote-session.v2'){
492
+ for(const key of ['owner_identity','guardian_identity'])if(value[key]!==undefined&&!validForegroundIdentity(value[key]))throw new Error('remote session ownership identity invalid');
493
+ if(!Number.isInteger(value?.owner_pid)||value.owner_pid<1||
494
+ !/^[0-9a-f]{64}$/.test(String(value?.session_nonce||''))||
495
+ !Number.isInteger(value?.guardian_pid)||value.guardian_pid<0||
496
+ (value.result_session_id!==undefined&&!/^[0-9a-f]{24}$/.test(String(value.result_session_id)))) throw new Error('remote session marker schema invalid');
497
+ return value;
498
+ }
499
+ throw new Error('remote session marker schema invalid');
500
+ }
501
+ async function publishExclusiveJson(file,value){
502
+ const bytes=Buffer.from(`${JSON.stringify(value)}\n`,'utf8');
503
+ await mkdir(path.dirname(file),{recursive:true});
504
+ try{
505
+ const handle=await open(file,'wx',0o600);
506
+ try{await handle.writeFile(bytes);await handle.sync();}finally{await handle.close();}
507
+ }catch(error){
508
+ if(error?.code!=='EEXIST')throw error;
509
+ const existing=await readFile(file);
510
+ if(!existing.equals(bytes))throw new Error(`exclusive evidence identity collision: ${path.basename(file)}`);
511
+ }
512
+ return {path:file,sha256:createHash('sha256').update(bytes).digest('hex')};
513
+ }
514
+ async function recoverRemoteSession(ctx,{displayMode='unicode'}={}){
515
+ let prior=await readRemoteSessionMarker(ctx.root);
516
+ const evidenceDir=path.join(ctx.root,'evidence','legacy-migration');
517
+ const locatorPath=path.join(evidenceDir,'r153-pending-migration.json');
518
+ if(!prior){
519
+ try{
520
+ const locator=JSON.parse(await readFile(locatorPath,'utf8'));
521
+ if(locator?.schema!=='deadbyte.r153-pending-migration.v1'||
522
+ typeof locator.receipt_path!=='string'||!path.isAbsolute(locator.receipt_path)||
523
+ path.resolve(path.dirname(locator.receipt_path)).toLowerCase()!==path.resolve(evidenceDir).toLowerCase()||
524
+ !/^[0-9a-f]{64}$/.test(String(locator.receipt_sha256??'')))throw new Error('pending migration locator invalid');
525
+ const bytes=await readFile(locator.receipt_path);
526
+ if(createHash('sha256').update(bytes).digest('hex')!==locator.receipt_sha256)
527
+ throw new Error('pending migration receipt hash mismatch');
528
+ return {state:'MARKER_RECONCILED',receipt_path:locator.receipt_path,
529
+ receipt_sha256:locator.receipt_sha256};
530
+ }catch(error){if(error?.code!=='ENOENT')throw error;}
531
+ // Crash recovery for the narrow window after marker CAS deletion and
532
+ // before terminal receipt publication. Never infer completion from the
533
+ // missing marker alone: require exactly one durable intent and re-observe
534
+ // the full predecessor/policy/grant/runtime subject.
535
+ let entries=[];
536
+ try{entries=await readdir(evidenceDir,{withFileTypes:true});}
537
+ catch(error){if(error?.code==='ENOENT')return null;throw error;}
538
+ const candidates=[];
539
+ for(const entry of entries){
540
+ const match=/^marker-([0-9a-f]{64})\.intent\.json$/.exec(entry.name);
541
+ if(!match||!entry.isFile())continue;
542
+ const terminal=path.join(evidenceDir,`marker-${match[1]}.terminal.json`);
543
+ let terminalExists=true;
544
+ try{await lstat(terminal);}
545
+ catch(error){if(error?.code==='ENOENT')terminalExists=false;else throw error;}
546
+ candidates.push({markerSha256:match[1],intent:path.join(evidenceDir,entry.name),terminal,terminalExists});
547
+ }
548
+ if(candidates.length===0)return null;
549
+ if(candidates.length!==1)throw new Error('multiple unlocated marker reconciliation claims; manual reconciliation required');
550
+ const pending=candidates[0],intentInfo=await lstat(pending.intent);
551
+ if(!intentInfo.isFile()||intentInfo.isSymbolicLink())throw new Error('marker reconciliation intent is not a regular file');
552
+ const intentBytes=await readFile(pending.intent),intent=JSON.parse(intentBytes.toString('utf8').replace(/^\uFEFF/,''));
553
+ if(intent.marker_sha256!==pending.markerSha256)throw new Error('marker reconciliation intent filename identity mismatch');
554
+ const active=await readActiveRuntimeBinding(ctx.root);
555
+ if(!active)throw new Error('marker reconciliation predecessor pointer missing');
556
+ const observed=observedAuthority(ctx);
557
+ const grantField={process:'grant_file',coding:'lease_file',autonomous:'lease_file',desktop:'grant_file',host:'arm_file'};
558
+ const policySha256={},grantPresence={};
559
+ for(const plane of AUTHORITY_PLANES){
560
+ const policyFile=path.join(active.generation_root,`${plane}-policy.json`),info=await lstat(policyFile);
561
+ if(!info.isFile()||info.isSymbolicLink()||path.resolve(path.dirname(policyFile)).toLowerCase()!==path.resolve(active.generation_root).toLowerCase())
562
+ throw new Error(`marker reconciliation ${plane} policy identity invalid`);
563
+ const bytes=await readFile(policyFile),policy=JSON.parse(bytes.toString('utf8').replace(/^\uFEFF/,''));
564
+ policySha256[plane]=createHash('sha256').update(bytes).digest('hex');
565
+ const grant=policy?.[grantField[plane]];
566
+ if(typeof grant!=='string'||!path.isAbsolute(grant)||
567
+ path.resolve(path.dirname(grant)).toLowerCase()!==path.resolve(ctx.root,'runtime').toLowerCase())
568
+ throw new Error(`marker reconciliation ${plane} grant path invalid`);
569
+ try{await lstat(grant);grantPresence[plane]=true;}
570
+ catch(error){if(error?.code==='ENOENT')grantPresence[plane]=false;else throw error;}
571
+ }
572
+ if(await readRemoteMarkerSnapshot(remoteSessionMarker(ctx.root))!==null)
573
+ throw new Error('marker reconciliation marker reappeared');
574
+ const intentSha256=createHash('sha256').update(intentBytes).digest('hex');
575
+ let reconciled;
576
+ if(pending.terminalExists){
577
+ const terminalInfo=await lstat(pending.terminal);
578
+ if(!terminalInfo.isFile()||terminalInfo.isSymbolicLink())throw new Error('marker reconciliation terminal is not a regular file');
579
+ const terminalBytes=await readFile(pending.terminal),terminal=JSON.parse(terminalBytes.toString('utf8').replace(/^\uFEFF/,''));
580
+ reconciled=recoverPublishedMarkerTerminal({stateRoot:ctx.root,pointer:active,observation:observed,
581
+ policySha256,grantPresence,intent,intentSha256,terminal,
582
+ terminalSha256:createHash('sha256').update(terminalBytes).digest('hex'),markerPresent:false});
583
+ }else{
584
+ reconciled=await resumeMarkerReconciliation({stateRoot:ctx.root,pointer:active,observation:observed,
585
+ policySha256,grantPresence,intent,intentSha256,markerPresent:false,
586
+ publishTerminal:async terminal=>publishExclusiveJson(pending.terminal,terminal)});
587
+ }
588
+ const locator={schema:'deadbyte.r153-pending-migration.v1',receipt_path:pending.terminal,
589
+ receipt_sha256:reconciled.receipt_sha256,marker_sha256:reconciled.marker_sha256};
590
+ await publishExclusiveJson(locatorPath,locator);
591
+ writeRemote(process.stdout,`${remoteTag('recovery',displayMode)} Interrupted marker reconciliation completed (${reconciled.marker_sha256.slice(0,12)}).\n`,displayMode);
592
+ return {...reconciled,receipt_path:pending.terminal};
593
+ }
594
+ const ownerPid=remoteOwnerPid(prior);
595
+ let restrictedReusedOwner=false;
596
+ if(pidAlive(ownerPid)){
597
+ if(!prior.owner_identity)throw new Error(`remote session ownership unverified for legacy pid=${ownerPid}; marker retained`);
454
598
  if(prior.owner_identity.pid!==ownerPid)throw new Error('remote session owner identity PID binding mismatch; marker retained');
455
- if(!foregroundIdentityMatches(prior.owner_identity,queryForegroundIdentity(ownerPid)))throw new Error('remote session owner identity mismatch; marker retained');
456
- throw new Error(`remote session already active pid=${ownerPid}`);
457
- }
458
- let guardianAlive=prior.schema==='deadbyte.remote-session.v2'&&pidAlive(prior.guardian_pid);
459
- if(guardianAlive){
460
- if(!prior.guardian_identity)throw new Error('remote guardian ownership unverified; marker retained');
461
- if(prior.guardian_identity.pid!==prior.guardian_pid)throw new Error('remote guardian identity PID binding mismatch');
462
- guardianAlive=foregroundIdentityMatches(prior.guardian_identity,queryForegroundIdentity(prior.guardian_pid));
463
- }
464
- if(guardianAlive){
465
- const deadline=Date.now()+3000;
466
- while(Date.now()<deadline){
467
- await sleep(100);
468
- prior=await readRemoteSessionMarker(ctx.root);
469
- if(!prior) return;
470
- if(remoteOwnerPid(prior)!==ownerPid) throw new Error('remote session ownership changed during guardian recovery');
471
- }
472
- throw new Error(`remote session guardian cleanup still active pid=${prior.guardian_pid}`);
473
- }
474
- throw new Error(`remote session ownership unverified for stale pid=${ownerPid}; marker retained`);
475
- }
476
- async function claimRemoteSession(ctx){
477
- const dir=path.join(ctx.root,'runtime');await mkdir(dir,{recursive:true});
478
- const nonce=randomBytes(32).toString('hex');
479
- const resultSessionId=randomBytes(12).toString('hex');
480
- const marker={schema:'deadbyte.remote-session.v2',owner_pid:process.pid,guardian_pid:0,session_nonce:nonce,
481
- result_session_id:resultSessionId,started_at_utc:new Date().toISOString()};
482
- marker.owner_identity=queryForegroundIdentity(process.pid);
483
- if(!marker.owner_identity)throw new Error('remote foreground identity unavailable');
484
- const markerPath=remoteSessionMarker(ctx.root);
485
- try{await writeFile(markerPath,`${JSON.stringify(marker)}\n`,{encoding:'utf8',flag:'wx'});}
486
- catch(error){if(error?.code==='EEXIST') throw new Error('remote session already claimed');throw error;}
487
- let guardian=null;
488
- try{
489
- guardian=spawn(process.execPath,[GUARDIAN_SCRIPT,'--state-root',ctx.root,'--owner-pid',String(process.pid),'--session-nonce',nonce,'--owner-channel','ipc'],{
490
- detached:true,stdio:['ignore','ignore','ignore','ipc'],windowsHide:true,shell:false,env:process.env
491
- });
492
- if(!Number.isInteger(guardian.pid)||guardian.pid<1) throw new Error('remote session guardian did not start');
493
- marker.guardian_pid=guardian.pid;
494
- marker.guardian_identity=queryForegroundIdentity(guardian.pid);
495
- if(!marker.guardian_identity||marker.guardian_identity.parent_pid!==process.pid)throw new Error('remote guardian parent identity mismatch');
496
- await writeFile(markerPath,`${JSON.stringify(marker)}\n`,'utf8');
497
- guardian.unref();
498
- guardian.channel?.unref();
499
- return marker;
500
- }catch(error){
501
- try{guardian?.kill();}catch{}
502
- try{
503
- const snapshot=await readRemoteMarkerSnapshot(markerPath);
504
- if(!snapshot||snapshot.marker?.owner_pid!==marker.owner_pid||snapshot.marker?.session_nonce!==marker.session_nonce)
505
- throw new Error('claim marker ownership changed or missing');
506
- if(deletePinnedRemoteMarker(markerPath,snapshot.sha256)!=='REMOVED')
507
- throw new Error('claim marker changed before native deletion');
508
- }catch(cleanupError){
509
- throw new AggregateError([error,cleanupError],
510
- 'remote session claim failed; marker cleanup unverified and marker retained');
511
- }
512
- throw error;
513
- }
514
- }
515
- async function releaseRemoteSession(ctx,marker,{displayMode='unicode'}={}){
599
+ let actualOwner;
600
+ try{actualOwner=queryForegroundIdentity(ownerPid);}
601
+ catch(error){restrictedReusedOwner=proveRestrictedPidReuse(prior.owner_identity,error);}
602
+ if(!restrictedReusedOwner){
603
+ if(!foregroundIdentityMatches(prior.owner_identity,actualOwner))throw new Error('remote session owner identity mismatch; marker retained');
604
+ throw new Error(`remote session already active pid=${ownerPid}`);
605
+ }
606
+ }
607
+ if(prior.schema!=='deadbyte.remote-session.v2'||!prior.owner_identity)
608
+ throw new Error(`remote session ownership identity unverified for stale pid=${ownerPid}; marker retained`);
609
+ let guardianAlive=pidAlive(prior.guardian_pid);
610
+ if(guardianAlive){
611
+ if(!prior.guardian_identity)throw new Error('remote guardian ownership unverified; marker retained');
612
+ if(prior.guardian_identity.pid!==prior.guardian_pid)throw new Error('remote guardian identity PID binding mismatch');
613
+ const actualGuardian=queryForegroundIdentity(prior.guardian_pid);
614
+ if(!actualGuardian||!foregroundIdentityMatches(prior.guardian_identity,actualGuardian))
615
+ throw new Error('remote guardian identity mismatch or PID reuse; marker retained');
616
+ }
617
+ if(guardianAlive){
618
+ const deadline=Date.now()+3000;
619
+ while(Date.now()<deadline){
620
+ await sleep(100);
621
+ prior=await readRemoteSessionMarker(ctx.root);
622
+ if(!prior) return;
623
+ if(remoteOwnerPid(prior)!==ownerPid) throw new Error('remote session ownership changed during guardian recovery');
624
+ }
625
+ throw new Error(`remote session guardian cleanup still active pid=${prior.guardian_pid}`);
626
+ }
627
+ const markerPath=remoteSessionMarker(ctx.root);
628
+ const snapshot=await readRemoteMarkerSnapshot(markerPath);
629
+ if(!snapshot) return null;
630
+ const active=await readActiveRuntimeBinding(ctx.root);
631
+ if(!active)throw new Error(`remote session ownership unverified for stale pid=${ownerPid}; active pointer missing; marker retained`);
632
+ const observed=observedAuthority(ctx);
633
+ const grantField={process:'grant_file',coding:'lease_file',autonomous:'lease_file',desktop:'grant_file',host:'arm_file'};
634
+ const policySha256={},grantPresence={};
635
+ for(const plane of AUTHORITY_PLANES){
636
+ const policyFile=path.join(active.generation_root,`${plane}-policy.json`);
637
+ const info=await lstat(policyFile);
638
+ if(!info.isFile()||info.isSymbolicLink()||path.resolve(path.dirname(policyFile)).toLowerCase()!==path.resolve(active.generation_root).toLowerCase())
639
+ throw new Error(`remote stale marker ${plane} policy identity invalid; marker retained`);
640
+ const bytes=await readFile(policyFile),policy=JSON.parse(bytes.toString('utf8').replace(/^\uFEFF/,''));
641
+ policySha256[plane]=createHash('sha256').update(bytes).digest('hex');
642
+ const grant=policy?.[grantField[plane]];
643
+ if(typeof grant!=='string'||!path.isAbsolute(grant)||
644
+ path.resolve(path.dirname(grant)).toLowerCase()!==path.resolve(ctx.root,'runtime').toLowerCase())
645
+ throw new Error(`remote stale marker ${plane} grant path invalid; marker retained`);
646
+ try{await lstat(grant);grantPresence[plane]=true;}
647
+ catch(error){if(error?.code==='ENOENT')grantPresence[plane]=false;else throw error;}
648
+ }
649
+ const identityLive=identity=>{
650
+ if(!identity||!validForegroundIdentity(identity))throw new Error('remote stale marker identity unverified; marker retained');
651
+ // A later-created protected svchost is not the signed original Node owner.
652
+ // This negative proof is limited to the exact owner and never exempts the guardian.
653
+ if(restrictedReusedOwner&&identity.pid===ownerPid)return false;
654
+ const actual=queryForegroundIdentity(identity.pid);
655
+ if(actual===null)return false;
656
+ if(!foregroundIdentityMatches(identity,actual))throw new Error('remote stale marker PID reuse detected; marker retained');
657
+ return true;
658
+ };
659
+ const revalidate=async phase=>{
660
+ const current=await readActiveRuntimeBinding(ctx.root);
661
+ for(const key of ['release_id','manifest_sha256','generation_manifest_sha256','generation_root'])
662
+ if(current?.[key]!==active[key])throw new Error(`remote stale marker pointer drift during ${phase}`);
663
+ const fresh=observedAuthority(ctx);
664
+ if(fresh.state!=='OFFLINE'||fresh.local_ready!==false||fresh.bridge?.alive!==false||fresh.core?.alive!==false||
665
+ fresh.cloud?.alive!==false||fresh.supervisor?.running!==false)throw new Error(`remote stale marker runtime drift during ${phase}`);
666
+ for(const plane of AUTHORITY_PLANES){
667
+ if(fresh.authority?.[plane]?.configured!==true||fresh.authority?.[plane]?.armed!==false)
668
+ throw new Error(`remote stale marker ${plane} authority drift during ${phase}`);
669
+ const policyFile=path.join(active.generation_root,`${plane}-policy.json`),bytes=await readFile(policyFile);
670
+ if(createHash('sha256').update(bytes).digest('hex')!==policySha256[plane])
671
+ throw new Error(`remote stale marker ${plane} policy drift during ${phase}`);
672
+ const policy=JSON.parse(bytes.toString('utf8').replace(/^\uFEFF/,'')),grant=policy?.[grantField[plane]];
673
+ try{await lstat(grant);throw new Error(`remote stale marker ${plane} grant appeared during ${phase}`);}
674
+ catch(error){if(error?.code!=='ENOENT')throw error;}
675
+ }
676
+ const currentMarker=await readRemoteMarkerSnapshot(markerPath);
677
+ if(phase==='before_delete'&&currentMarker?.sha256!==snapshot.sha256)
678
+ throw new Error('remote stale marker changed before deletion');
679
+ if(phase==='after_delete'&&currentMarker!==null)
680
+ throw new Error('remote stale marker remained or reappeared after deletion');
681
+ };
682
+ const intentPath=path.join(evidenceDir,`marker-${snapshot.sha256}.intent.json`);
683
+ const terminalPath=path.join(evidenceDir,`marker-${snapshot.sha256}.terminal.json`);
684
+ const reconciled=await reconcileStaleMarker({stateRoot:ctx.root,pointer:active,observation:observed,
685
+ policySha256,grantPresence,marker:{sha256:snapshot.sha256,
686
+ owner_live:identityLive(prior.owner_identity),
687
+ guardian_live:prior.guardian_pid===0?false:identityLive(prior.guardian_identity)},
688
+ publishIntent:async intent=>publishExclusiveJson(intentPath,intent),
689
+ publishTerminal:async terminal=>publishExclusiveJson(terminalPath,terminal),revalidate,
690
+ deleteIfHash:async expected=>deletePinnedRemoteMarker(markerPath,expected)});
691
+ const locator={schema:'deadbyte.r153-pending-migration.v1',receipt_path:terminalPath,
692
+ receipt_sha256:reconciled.receipt_sha256,marker_sha256:reconciled.marker_sha256};
693
+ await publishExclusiveJson(locatorPath,locator);
694
+ writeRemote(process.stdout,`${remoteTag('recovery',displayMode)} Stale session evidence reconciled (${reconciled.marker_sha256.slice(0,12)}).\n`,displayMode);
695
+ return {...reconciled,receipt_path:terminalPath};
696
+ }
697
+ async function claimRemoteSession(ctx){
698
+ const dir=path.join(ctx.root,'runtime');await mkdir(dir,{recursive:true});
699
+ const nonce=randomBytes(32).toString('hex');
700
+ const resultSessionId=randomBytes(12).toString('hex');
701
+ const marker={schema:'deadbyte.remote-session.v2',owner_pid:process.pid,guardian_pid:0,session_nonce:nonce,
702
+ result_session_id:resultSessionId,started_at_utc:new Date().toISOString()};
703
+ marker.owner_identity=queryForegroundIdentity(process.pid);
704
+ if(!marker.owner_identity)throw new Error('remote foreground identity unavailable');
705
+ const markerPath=remoteSessionMarker(ctx.root);
706
+ try{await writeFile(markerPath,`${JSON.stringify(marker)}\n`,{encoding:'utf8',flag:'wx'});}
707
+ catch(error){if(error?.code==='EEXIST') throw new Error('remote session already claimed');throw error;}
708
+ let guardian=null;
709
+ try{
710
+ guardian=spawn(process.execPath,[GUARDIAN_SCRIPT,'--state-root',ctx.root,'--owner-pid',String(process.pid),'--session-nonce',nonce,'--owner-channel','ipc'],{
711
+ detached:true,stdio:['ignore','ignore','ignore','ipc'],windowsHide:true,shell:false,env:process.env
712
+ });
713
+ if(!Number.isInteger(guardian.pid)||guardian.pid<1) throw new Error('remote session guardian did not start');
714
+ marker.guardian_pid=guardian.pid;
715
+ marker.guardian_identity=queryForegroundIdentity(guardian.pid);
716
+ if(!marker.guardian_identity||marker.guardian_identity.parent_pid!==process.pid)throw new Error('remote guardian parent identity mismatch');
717
+ await writeFile(markerPath,`${JSON.stringify(marker)}\n`,'utf8');
718
+ guardian.unref();
719
+ guardian.channel?.unref();
720
+ return marker;
721
+ }catch(error){
722
+ try{guardian?.kill();}catch{}
723
+ try{
724
+ const snapshot=await readRemoteMarkerSnapshot(markerPath);
725
+ if(!snapshot||snapshot.marker?.owner_pid!==marker.owner_pid||snapshot.marker?.session_nonce!==marker.session_nonce)
726
+ throw new Error('claim marker ownership changed or missing');
727
+ if(deletePinnedRemoteMarker(markerPath,snapshot.sha256)!=='REMOVED')
728
+ throw new Error('claim marker changed before native deletion');
729
+ }catch(cleanupError){
730
+ throw new AggregateError([error,cleanupError],
731
+ 'remote session claim failed; marker cleanup unverified and marker retained');
732
+ }
733
+ throw error;
734
+ }
735
+ }
736
+ async function releaseRemoteSession(ctx,marker,{displayMode='unicode'}={}){
516
737
  let snapshot;
517
738
  try{snapshot=await readRemoteMarkerSnapshot(remoteSessionMarker(ctx.root));}
518
739
  catch(error){writeRemote(process.stderr,`${remoteTag('warn',displayMode)} remote session marker cleanup: ${String(error?.message||error)}\n`,displayMode);throw new Error(`remote session ownership marker retained: ${String(error?.message||error)}`);}
519
740
  const current=snapshot?.marker;
520
- const same=current?.schema==='deadbyte.remote-session.v2'&&current.owner_pid===marker.owner_pid&&current.session_nonce===marker.session_nonce;
741
+ const same=current?.schema==='deadbyte.remote-session.v2'&&current.owner_pid===marker.owner_pid&&current.session_nonce===marker.session_nonce;
521
742
  if(!same)throw new Error('remote session ownership marker changed or missing; marker retained');
522
743
  if(deletePinnedRemoteMarker(remoteSessionMarker(ctx.root),snapshot.sha256)!=='REMOVED')
523
744
  throw new Error('remote session ownership marker replaced before native deletion; marker retained');
524
- }
525
- async function runRemoteSession({resumeCursor=null,verbose=false,trace=false,filterExpression='',mode='default'}={}){
526
- const display=prepareRemoteConsole();
527
- const displayMode=display.mode;
528
- const ctx=await remoteContext();
529
- if(displayMode==='ascii') writeRemote(process.stdout,`[DISPLAY] ASCII fallback: ${display.reason}\n`,displayMode);
530
- if(resumeCursor!==null) await replayRemoteResults(ctx.root,resumeCursor,{displayMode});
531
- const startupLock=await acquireForegroundSessionLock({root:ctx.root,powershell:ctx.powershell});
532
- let marker;
533
- try{
534
- startupLock.assertHeld();
535
- await recoverRemoteSession(ctx,{displayMode});
536
- startupLock.assertHeld();
537
- marker=await claimRemoteSession(ctx);
538
- startupLock.assertHeld();
539
- }finally{await startupLock.release();}
540
- try{
541
- await synchronizeForegroundRuntime(ctx,{displayMode});
542
- }catch(primaryError){
543
- let cleanupError=null;
544
- try{await cleanupRemoteSession(ctx,{displayMode});}
545
- catch(error){cleanupError=error;}
546
- if(!cleanupError){
547
- try{await releaseRemoteSession(ctx,marker,{displayMode});}
548
- catch(error){cleanupError=error;}
549
- }
550
- if(cleanupError){
551
- const primaryDetail=String(primaryError?.message||primaryError);
552
- const cleanupDetail=String(cleanupError?.message||cleanupError);
553
- throw new AggregateError([primaryError,cleanupError],
554
- `remote activation failed: ${primaryDetail}; cleanup failed, ownership marker retained: ${cleanupDetail}`);
555
- }
556
- throw primaryError;
557
- }
558
- const resultJournal=await openRemoteResultJournal({
559
- filePath:remoteResultJournalPath(ctx.root,marker.result_session_id),sessionId:marker.result_session_id,maxEntries:2048
560
- });
561
- const rootPaths=await readLiveRootPaths(ctx.root);
562
- const activityTracker=createLiveTimelineTracker({verbose,displayMode,rootPaths,trace,foldHeartbeats:!verbose});
563
- const timelineFilter=filterExpression?createLiveTimelineFilter(filterExpression):null;
564
- const timelineWriter=createLiveTimelineWriter({stream:process.stdout,displayMode,rewrite:false});
565
- const aborter=new AbortController();
566
- const abort=()=>aborter.abort();
567
- const watchStdin=!process.stdin.isTTY;
568
- process.once('SIGINT',abort);process.once('SIGTERM',abort);
569
- if(watchStdin){process.stdin.once('end',abort);process.stdin.once('close',abort);process.stdin.resume();}
570
- let ready=false;
571
- let logTask=null;
745
+ }
746
+ async function runRemoteSession({resumeCursor=null,verbose=false,trace=false,filterExpression='',mode='default'}={}){
747
+ const display=prepareRemoteConsole();
748
+ const displayMode=display.mode;
749
+ const ctx=await remoteContext();
750
+ if(displayMode==='ascii') writeRemote(process.stdout,`[DISPLAY] ASCII fallback: ${display.reason}\n`,displayMode);
751
+ if(resumeCursor!==null) await replayRemoteResults(ctx.root,resumeCursor,{displayMode});
752
+ const startupLock=await acquireForegroundSessionLock({root:ctx.root,powershell:ctx.powershell});
753
+ let marker;
754
+ try{
755
+ startupLock.assertHeld();
756
+ const migrationContext=await recoverRemoteSession(ctx,{displayMode});
757
+ startupLock.assertHeld();
758
+ await synchronizeForegroundRuntime(ctx,{displayMode,migrationContext});
759
+ startupLock.assertHeld();
760
+ marker=await claimRemoteSession(ctx);
761
+ startupLock.assertHeld();
762
+ }finally{await startupLock.release();}
763
+ const resultJournal=await openRemoteResultJournal({
764
+ filePath:remoteResultJournalPath(ctx.root,marker.result_session_id),sessionId:marker.result_session_id,maxEntries:2048
765
+ });
766
+ const rootPaths=await readLiveRootPaths(ctx.root);
767
+ const activityTracker=createLiveTimelineTracker({verbose,displayMode,rootPaths,trace,foldHeartbeats:!verbose});
768
+ const timelineFilter=filterExpression?createLiveTimelineFilter(filterExpression):null;
769
+ const timelineWriter=createLiveTimelineWriter({stream:process.stdout,displayMode,rewrite:false});
770
+ const aborter=new AbortController();
771
+ const abort=()=>aborter.abort();
772
+ const watchStdin=!process.stdin.isTTY;
773
+ process.once('SIGINT',abort);process.once('SIGTERM',abort);
774
+ if(watchStdin){process.stdin.once('end',abort);process.stdin.once('close',abort);process.stdin.resume();}
775
+ let ready=false;
776
+ let logTask=null;
572
777
  let sessionError=null;
573
- try{
574
- process.stdout.write('DEADBYTE MCP\n');
575
- process.stdout.write(`${formatRemoteLifecycle('device_start',{displayMode})}\n`);
576
- process.stdout.write(`${formatRemoteLifecycle(resumeCursor!==null?'session_restored':'session_new',{displayMode})}\n`);
577
- const logOffsets=await snapshotRemoteLogOffsets(ctx.root);
578
- logTask=tailRemoteLogs(ctx.root,aborter.signal,{journal:resultJournal,offsets:logOffsets,activityTracker,timelineFilter,timelineWriter,verbose,displayMode});
579
- process.stdout.write('[BOOT] Starting local + remote runtime...\n');
580
- const preflight=invokeController(ctx,'status',{capture:true,allowFailure:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
581
- let startText=preflight.stdout||'';
582
- if(preflight.status===0&&controllerRuntimeReady(preflight.stdout)){
583
- process.stdout.write('[BOOT] Runtime already ONLINE; reusing verified bridge/cloud/supervisor.\n');
584
- }else{
585
- const recovery=preflight.status===0&&controllerRuntimeDegraded(preflight.stdout);
586
- process.stdout.write(recovery?'[RECOVERY] Runtime failed readiness; restarting verified owned components...\n':'[BOOT] Starting bridge/runtime...\n');
587
- const startCommand=recovery?'restart':'start';
588
- const controllerLogDir=path.join(ctx.root,'runtime','logs');
589
- await mkdir(controllerLogDir,{recursive:true});
590
- const launchOutput={
591
- stdout_path:path.join(controllerLogDir,`controller-${startCommand}.stdout.log`),
592
- stderr_path:path.join(controllerLogDir,`controller-${startCommand}.stderr.log`)
593
- };
594
- const launch=invokeController(ctx,startCommand,{allowFailure:true,redirectOutput:launchOutput,timeoutMs:REMOTE_START_TIMEOUT_MS});
595
- if(launch.status!==0){
596
- const evidence=await readControllerStartFailure(ctx.root,startCommand);
597
- const fallback=evidence?'':await readTailBounded(launchOutput.stderr_path,2048);
598
- const detail=evidence?`; controller-start-failure: ${evidence.message}`:(fallback?`; controller-stderr: ${fallback}`:'');
599
- throw new Error(`remote controller '${startCommand}' failed exit=${launch.status}${detail}`);
600
- }
601
- const started=invokeController(ctx,'status',{capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
602
- if(started.status!==0||!controllerRuntimeReady(started.stdout)) throw new Error(`remote controller ${recovery?'restart':'start'} returned without a verified ONLINE runtime`);
603
- startText=started.stdout||'';
604
- }
605
- process.stdout.write(`${formatRemoteLifecycle('bridge_connected',{displayMode})}\n`);
606
- process.stdout.write(`${formatRemoteLifecycle('cloud_connected',{displayMode})}\n`);
607
- const desired=authorityVector(mode);
608
- const priorAuthority=observedAuthority(ctx);
609
- for(const plane of ['host','desktop','autonomous','coding','process'].filter(name=>!desired[name]&&priorAuthority.authority[name].armed)){
610
- const command=`disarm${plane}`;
611
- writeRemote(process.stdout,`${remoteTag('auth',displayMode)} Revoking unwanted ${plane} authority...\n`,displayMode);
612
- invokeController(ctx,command,{capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
613
- }
614
- for(const plane of AUTHORITY_PLANES.filter(name=>desired[name])){
615
- const command=`arm${plane}`;
616
- writeRemote(process.stdout,`${remoteTag('auth',displayMode)} Arming ${command.slice(3)}...\n`,displayMode);
617
- invokeController(ctx,command,{capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
618
- }
619
- const url=startText.match(/^URL\s*:\s*(\S+)/m)?.[1]||'';
620
- writeRemote(process.stdout,`${remoteTag('auth',displayMode)} Verifying exact ${mode} authority vector...\n`,displayMode);
621
- const current=await readActiveRuntimeBinding(ctx.root);
622
- const authority=assertAuthorityVector(assertRuntimeReadyObservation(observedAuthority(ctx),{
623
- coreRoot:current?.release_root??null
624
- }),desired);
625
- process.stdout.write('[BOOT] Verifying public signed MCP execution path...\n');
626
- invokeController(ctx,'machinetest',{capture:true,echoCaptured:false,timeoutMs:REMOTE_START_TIMEOUT_MS,probeMode:mode==='default'?'revoked':mode});
627
- ready=true;
628
- writeRemote(process.stdout,`${remoteTag('auth',displayMode)} ${authorityBanner(authority)}\n`,displayMode);
629
- process.stdout.write('[OK] ONLINE\n');
630
- process.stdout.write(`${formatRemoteLifecycle('ready',{displayMode})}\n`);
631
- if(url) writeRemote(process.stdout,`URL: ${url}\n`,displayMode);
778
+ try{
779
+ process.stdout.write('DEADBYTE MCP\n');
780
+ process.stdout.write(`${formatRemoteLifecycle('device_start',{displayMode})}\n`);
781
+ process.stdout.write(`${formatRemoteLifecycle(resumeCursor!==null?'session_restored':'session_new',{displayMode})}\n`);
782
+ const logOffsets=await snapshotRemoteLogOffsets(ctx.root);
783
+ logTask=tailRemoteLogs(ctx.root,aborter.signal,{journal:resultJournal,offsets:logOffsets,activityTracker,timelineFilter,timelineWriter,verbose,displayMode});
784
+ process.stdout.write('[BOOT] Starting local + remote runtime...\n');
785
+ const preflight=invokeController(ctx,'status',{capture:true,allowFailure:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
786
+ let startText=preflight.stdout||'';
787
+ if(preflight.status===0&&controllerRuntimeReady(preflight.stdout)){
788
+ process.stdout.write('[BOOT] Runtime already ONLINE; reusing verified bridge/cloud/supervisor.\n');
789
+ }else{
790
+ const recovery=preflight.status===0&&controllerRuntimeDegraded(preflight.stdout);
791
+ process.stdout.write(recovery?'[RECOVERY] Runtime failed readiness; restarting verified owned components...\n':'[BOOT] Starting bridge/runtime...\n');
792
+ const startCommand=recovery?'restart':'start';
793
+ const controllerLogDir=path.join(ctx.root,'runtime','logs');
794
+ await mkdir(controllerLogDir,{recursive:true});
795
+ const launchOutput={
796
+ stdout_path:path.join(controllerLogDir,`controller-${startCommand}.stdout.log`),
797
+ stderr_path:path.join(controllerLogDir,`controller-${startCommand}.stderr.log`)
798
+ };
799
+ const launch=invokeController(ctx,startCommand,{allowFailure:true,redirectOutput:launchOutput,timeoutMs:REMOTE_START_TIMEOUT_MS});
800
+ if(launch.status!==0){
801
+ const evidence=await readControllerStartFailure(ctx.root,startCommand);
802
+ const fallback=evidence?'':await readTailBounded(launchOutput.stderr_path,2048);
803
+ const detail=evidence?`; controller-start-failure: ${evidence.message}`:(fallback?`; controller-stderr: ${fallback}`:'');
804
+ throw new Error(`remote controller '${startCommand}' failed exit=${launch.status}${detail}`);
805
+ }
806
+ const started=invokeController(ctx,'status',{capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
807
+ if(started.status!==0||!controllerRuntimeReady(started.stdout)) throw new Error(`remote controller ${recovery?'restart':'start'} returned without a verified ONLINE runtime`);
808
+ startText=started.stdout||'';
809
+ }
810
+ process.stdout.write(`${formatRemoteLifecycle('bridge_connected',{displayMode})}\n`);
811
+ process.stdout.write(`${formatRemoteLifecycle('cloud_connected',{displayMode})}\n`);
812
+ const desired=authorityVector(mode);
813
+ const priorAuthority=observedAuthority(ctx);
814
+ for(const plane of ['host','desktop','autonomous','coding','process'].filter(name=>!desired[name]&&priorAuthority.authority[name].armed)){
815
+ const command=`disarm${plane}`;
816
+ writeRemote(process.stdout,`${remoteTag('auth',displayMode)} Revoking unwanted ${plane} authority...\n`,displayMode);
817
+ invokeController(ctx,command,{capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
818
+ }
819
+ for(const plane of AUTHORITY_PLANES.filter(name=>desired[name])){
820
+ const command=`arm${plane}`;
821
+ writeRemote(process.stdout,`${remoteTag('auth',displayMode)} Arming ${command.slice(3)}...\n`,displayMode);
822
+ invokeController(ctx,command,{capture:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
823
+ }
824
+ const url=startText.match(/^URL\s*:\s*(\S+)/m)?.[1]||'';
825
+ writeRemote(process.stdout,`${remoteTag('auth',displayMode)} Verifying exact ${mode} authority vector...\n`,displayMode);
826
+ const current=await readActiveRuntimeBinding(ctx.root);
827
+ const authority=assertAuthorityVector(assertRuntimeReadyObservation(observedAuthority(ctx),{
828
+ coreRoot:current?.release_root??null
829
+ }),desired);
830
+ process.stdout.write('[BOOT] Verifying public signed MCP execution path...\n');
831
+ invokeController(ctx,'machinetest',{capture:true,echoCaptured:false,timeoutMs:REMOTE_START_TIMEOUT_MS,probeMode:mode==='default'?'revoked':mode});
832
+ ready=true;
833
+ writeRemote(process.stdout,`${remoteTag('auth',displayMode)} ${authorityBanner(authority)}\n`,displayMode);
834
+ process.stdout.write('[OK] ONLINE\n');
835
+ process.stdout.write(`${formatRemoteLifecycle('ready',{displayMode})}\n`);
836
+ if(url) writeRemote(process.stdout,`URL: ${url}\n`,displayMode);
632
837
  await logTask;
633
838
  }catch(error){sessionError=error;throw error;}
634
839
  finally{
635
- const wasAborted=aborter.signal.aborted;
636
- aborter.abort();
637
- if(logTask) await logTask.catch(()=>{});
840
+ const wasAborted=aborter.signal.aborted;
841
+ aborter.abort();
842
+ if(logTask) await logTask.catch(()=>{});
638
843
  timelineWriter.flush();
639
844
  const liveLogDelivery=timelineWriter.retention();
640
845
  if(liveLogDelivery.suppressed_since_drain>0){
641
846
  process.stderr.write(`[WARN] LIVELOG ${liveLogDelivery.suppressed_since_drain} display lines still suppressed at disconnect due to stdout backpressure; inspect signed audit and runtime logs.\n`);
642
- }
643
- for(const line of activityTracker.reconcileInterrupted('session_end')) process.stdout.write(`${line}\n`);
644
- const filterRetention=timelineFilter?.retention();
645
- if(filterRetention?.evicted>0) process.stdout.write(`[WARN] LIVELOG filter evicted ${filterRetention.evicted} presentation identities; full audit remains on disk.\n`);
646
- process.stdout.write(`${activityTracker.summary()}\n`);
647
- process.removeListener('SIGINT',abort);process.removeListener('SIGTERM',abort);
648
- if(watchStdin){process.stdin.removeListener('end',abort);process.stdin.removeListener('close',abort);process.stdin.pause();}
649
- process.stdout.write(`${formatRemoteLifecycle('cleanup',{displayMode})}\n`);
650
- if(ready||!wasAborted) process.stdout.write('[INFO] Disconnecting; revoking authority...\n');
847
+ }
848
+ for(const line of activityTracker.reconcileInterrupted('session_end')) process.stdout.write(`${line}\n`);
849
+ const filterRetention=timelineFilter?.retention();
850
+ if(filterRetention?.evicted>0) process.stdout.write(`[WARN] LIVELOG filter evicted ${filterRetention.evicted} presentation identities; full audit remains on disk.\n`);
851
+ process.stdout.write(`${activityTracker.summary()}\n`);
852
+ process.removeListener('SIGINT',abort);process.removeListener('SIGTERM',abort);
853
+ if(watchStdin){process.stdin.removeListener('end',abort);process.stdin.removeListener('close',abort);process.stdin.pause();}
854
+ process.stdout.write(`${formatRemoteLifecycle('cleanup',{displayMode})}\n`);
855
+ if(ready||!wasAborted) process.stdout.write('[INFO] Disconnecting; revoking authority...\n');
651
856
  try{await cleanupRemoteSession(ctx,{displayMode});}
652
857
  catch(cleanupError){
653
858
  if(sessionError) throw new AggregateError([sessionError,cleanupError],
@@ -660,98 +865,98 @@ async function runRemoteSession({resumeCursor=null,verbose=false,trace=false,fil
660
865
  `remote activation failed: ${String(sessionError?.message||sessionError)}; marker cleanup failed: ${String(markerError?.message||markerError)}`);
661
866
  throw markerError;
662
867
  }
663
- }
664
- }
665
- async function runRemote(args){
666
- let verbose=false,trace=false,filterExpression='',resumeCursor=null,mode='default';
667
- const positional=[];
668
- for(let index=0;index<args.length;index++){
669
- const arg=args[index];
670
- if(arg==='--verbose'||arg==='-v'){verbose=true;continue;}
671
- if(arg==='--trace'){trace=true;continue;}
672
- if(['--operator','--desktop','--host','--full'].includes(arg)){
673
- if(mode!=='default') throw new Error('remote authority modes are mutually exclusive');
674
- mode=arg.slice(2);continue;
675
- }
676
- if(arg==='--filter'){
677
- if(filterExpression) throw new Error('remote --filter may be specified once');
678
- if(index+1>=args.length) throw new Error('remote --filter requires an expression');
679
- filterExpression=args[++index];continue;
680
- }
681
- if(arg==='--resume'){
682
- if(resumeCursor!==null) throw new Error('remote --resume may be specified once');
683
- if(index+1>=args.length) throw new Error('remote --resume requires a cursor');
684
- resumeCursor=args[++index];continue;
685
- }
686
- positional.push(arg);
687
- }
688
- const presentation=verbose||trace||Boolean(filterExpression)||resumeCursor!==null||mode!=='default';
689
- if(positional.length===0){await runRemoteSession({resumeCursor,verbose,trace,filterExpression,mode});return;}
690
- if(presentation) throw new Error('remote presentation flags are valid only for foreground session');
691
- if(positional.length>1) throw new Error('remote accepts one controller command');
692
- const command=positional[0];if(!REMOTE_COMMANDS.has(command)) throw new Error(`unsupported remote command '${command}'`);
693
- const ctx=await remoteContext();
694
- await synchronizeOneShotRuntime(ctx,{displayMode:'ascii'});
695
- const result=invokeController(ctx,command,{allowFailure:true});
696
- process.exitCode=result.status;
697
- }
698
- async function runSupervisor(args){
699
- const action=args[0]||'status';
700
- if(args.length>1||!Object.hasOwn(SUPERVISOR_COMMANDS,action)) throw new Error(`unsupported supervisor command '${action}'`);
701
- const ctx=await remoteContext();
702
- const result=invokeController(ctx,SUPERVISOR_COMMANDS[action],{allowFailure:true});
703
- process.exitCode=result.status;
704
- }
705
- async function runAudit(args){
706
- const command=args[0]||'status';if(args.length>1) throw new Error('audit accepts one command');
707
- if(!['verify','status'].includes(command)) throw new Error(`unsupported audit command '${command}'`);
708
- const result=await verifyAuditChain({stateRoot:stateRoot(),verifyKeyPath:process.env.DEADBYTE_VERIFY_KEY||defaultPublicKeyPath(),requireComplete:command==='verify'});
709
- const output=command==='status'?{...result,mode:'status'}:result;
710
- process.stdout.write(`${JSON.stringify(output,null,2)}\n`);
711
- if(command==='verify'&&!result.ok) process.exitCode=1;
712
- }
713
- async function main(argv){
714
- const [command,...rest]=argv;
715
- if(command==='--version'||command==='-v'||command==='version'){
716
- if(rest.length) throw new Error('version accepts no arguments');
717
- process.stdout.write(`${DEADBYTE_VERSION}\n`);return;
718
- }
719
- if(!command||command==='help'||command==='--help'||command==='-h'){printHelp();return;}
720
- if(command==='doctor'){
721
- if(rest.length) throw new Error('doctor accepts no arguments');
722
- await printDoctor();return;
723
- }
724
- if(command==='mcp'){
725
- if(rest.length) throw new Error('mcp accepts no arguments');
726
- await import('./mcp-server.mjs');
727
- return;
728
- }
729
- if(command==='remote'){await runRemote(rest);return;}
730
- if(command==='supervisor'){await runSupervisor(rest);return;}
731
- if(command==='audit'){await runAudit(rest);return;}
732
- if(command==='diagnostics'){
733
- if(rest.length!==3)throw new Error('diagnostics export --output or verify --input; no network upload supported');
734
- if(rest[0]==='export'&&rest[1]==='--output'){
735
- const report=await exportOfflineDiagnostics({stateRoot:stateRoot(),outputPath:rest[2]});
736
- process.stdout.write(`${JSON.stringify(report)}\n`);
737
- return;
738
- }
739
- if(rest[0]==='verify'&&rest[1]==='--input'){
740
- const file=path.resolve(rest[2]);
741
- await requireRegular(file,'diagnostic ZIP');
742
- const report=verifyOfflineDiagnosticsZip(await readFile(file));
743
- process.stdout.write(`${JSON.stringify(report)}\n`);
744
- return;
745
- }
746
- throw new Error('unsupported diagnostics mode; network upload is forbidden');
747
- }
748
- if(command==='inspect'){
749
- const result=await runNativeInspect(rest);
750
- process.stdout.write(`${JSON.stringify(result)}\n`);
751
- if(result.status!=='ok')process.exitCode=2;
752
- return;
753
- }
754
- throw new Error(`unknown command '${command}'`);
755
- }
756
-
757
- main(process.argv.slice(2)).catch(error=>{process.stderr.write(`DEADBYTE CLI: ${String(error?.message||error)}\n`);process.exitCode=1;});
868
+ }
869
+ }
870
+ async function runRemote(args){
871
+ let verbose=false,trace=false,filterExpression='',resumeCursor=null,mode='default';
872
+ const positional=[];
873
+ for(let index=0;index<args.length;index++){
874
+ const arg=args[index];
875
+ if(arg==='--verbose'||arg==='-v'){verbose=true;continue;}
876
+ if(arg==='--trace'){trace=true;continue;}
877
+ if(['--operator','--desktop','--host','--full'].includes(arg)){
878
+ if(mode!=='default') throw new Error('remote authority modes are mutually exclusive');
879
+ mode=arg.slice(2);continue;
880
+ }
881
+ if(arg==='--filter'){
882
+ if(filterExpression) throw new Error('remote --filter may be specified once');
883
+ if(index+1>=args.length) throw new Error('remote --filter requires an expression');
884
+ filterExpression=args[++index];continue;
885
+ }
886
+ if(arg==='--resume'){
887
+ if(resumeCursor!==null) throw new Error('remote --resume may be specified once');
888
+ if(index+1>=args.length) throw new Error('remote --resume requires a cursor');
889
+ resumeCursor=args[++index];continue;
890
+ }
891
+ positional.push(arg);
892
+ }
893
+ const presentation=verbose||trace||Boolean(filterExpression)||resumeCursor!==null||mode!=='default';
894
+ if(positional.length===0){await runRemoteSession({resumeCursor,verbose,trace,filterExpression,mode});return;}
895
+ if(presentation) throw new Error('remote presentation flags are valid only for foreground session');
896
+ if(positional.length>1) throw new Error('remote accepts one controller command');
897
+ const command=positional[0];if(!REMOTE_COMMANDS.has(command)) throw new Error(`unsupported remote command '${command}'`);
898
+ const ctx=await remoteContext();
899
+ await synchronizeOneShotRuntime(ctx,{displayMode:'ascii'});
900
+ const result=invokeController(ctx,command,{allowFailure:true});
901
+ process.exitCode=result.status;
902
+ }
903
+ async function runSupervisor(args){
904
+ const action=args[0]||'status';
905
+ if(args.length>1||!Object.hasOwn(SUPERVISOR_COMMANDS,action)) throw new Error(`unsupported supervisor command '${action}'`);
906
+ const ctx=await remoteContext();
907
+ const result=invokeController(ctx,SUPERVISOR_COMMANDS[action],{allowFailure:true});
908
+ process.exitCode=result.status;
909
+ }
910
+ async function runAudit(args){
911
+ const command=args[0]||'status';if(args.length>1) throw new Error('audit accepts one command');
912
+ if(!['verify','status'].includes(command)) throw new Error(`unsupported audit command '${command}'`);
913
+ const result=await verifyAuditChain({stateRoot:stateRoot(),verifyKeyPath:process.env.DEADBYTE_VERIFY_KEY||defaultPublicKeyPath(),requireComplete:command==='verify'});
914
+ const output=command==='status'?{...result,mode:'status'}:result;
915
+ process.stdout.write(`${JSON.stringify(output,null,2)}\n`);
916
+ if(command==='verify'&&!result.ok) process.exitCode=1;
917
+ }
918
+ async function main(argv){
919
+ const [command,...rest]=argv;
920
+ if(command==='--version'||command==='-v'||command==='version'){
921
+ if(rest.length) throw new Error('version accepts no arguments');
922
+ process.stdout.write(`${DEADBYTE_VERSION}\n`);return;
923
+ }
924
+ if(!command||command==='help'||command==='--help'||command==='-h'){printHelp();return;}
925
+ if(command==='doctor'){
926
+ if(rest.length) throw new Error('doctor accepts no arguments');
927
+ await printDoctor();return;
928
+ }
929
+ if(command==='mcp'){
930
+ if(rest.length) throw new Error('mcp accepts no arguments');
931
+ await import('./mcp-server.mjs');
932
+ return;
933
+ }
934
+ if(command==='remote'){await runRemote(rest);return;}
935
+ if(command==='supervisor'){await runSupervisor(rest);return;}
936
+ if(command==='audit'){await runAudit(rest);return;}
937
+ if(command==='diagnostics'){
938
+ if(rest.length!==3)throw new Error('diagnostics export --output or verify --input; no network upload supported');
939
+ if(rest[0]==='export'&&rest[1]==='--output'){
940
+ const report=await exportOfflineDiagnostics({stateRoot:stateRoot(),outputPath:rest[2]});
941
+ process.stdout.write(`${JSON.stringify(report)}\n`);
942
+ return;
943
+ }
944
+ if(rest[0]==='verify'&&rest[1]==='--input'){
945
+ const file=path.resolve(rest[2]);
946
+ await requireRegular(file,'diagnostic ZIP');
947
+ const report=verifyOfflineDiagnosticsZip(await readFile(file));
948
+ process.stdout.write(`${JSON.stringify(report)}\n`);
949
+ return;
950
+ }
951
+ throw new Error('unsupported diagnostics mode; network upload is forbidden');
952
+ }
953
+ if(command==='inspect'){
954
+ const result=await runNativeInspect(rest);
955
+ process.stdout.write(`${JSON.stringify(result)}\n`);
956
+ if(result.status!=='ok')process.exitCode=2;
957
+ return;
958
+ }
959
+ throw new Error(`unknown command '${command}'`);
960
+ }
961
+
962
+ main(process.argv.slice(2)).catch(error=>{process.stderr.write(`DEADBYTE CLI: ${String(error?.message||error)}\n`);process.exitCode=1;});