deadbyte-mcp 0.11.2 → 0.11.3

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.
@@ -5,7 +5,7 @@ import { mkdtemp, mkdir, readFile, rm, writeFile, readdir } from 'node:fs/promis
5
5
  import os from 'node:os';
6
6
  import path from 'node:path';
7
7
  import { spawn } from 'node:child_process';
8
- import * as parity from '../scripts/release-parity-r38.mjs';
8
+ import * as parity from '../scripts/release-parity-r39.mjs';
9
9
  import { createToolAudit } from '../src/tool-audit.mjs';
10
10
  import { verifyAuditChain } from '../src/audit-verify.mjs';
11
11
  import { generateTrustKeypair } from '../src/trust.mjs';
@@ -86,12 +86,12 @@ test('audit restart reconciles an orphan request with an explicit interrupted re
86
86
  }finally{await rm(stateRoot,{recursive:true,force:true});}
87
87
  });
88
88
 
89
- test('Windows R38 gate emits manifest-bound machine-readable evidence outside the candidate tree', async()=>{
89
+ test('Windows R39 gate emits manifest-bound machine-readable evidence outside the candidate tree', async()=>{
90
90
  const stateRoot=await temp('deadbyte-r33-windows-evidence-');
91
91
  try{
92
- const gate=await readFile(path.join(root,'scripts','gate-windows-r38.ps1'),'utf8');
93
- assert.match(gate,/windows-gate-evidence-r38\.mjs/,'gate-windows-r38.ps1 must invoke the evidence writer');
94
- const result=await run(process.execPath,[path.join(root,'scripts','windows-gate-evidence-r38.mjs')],{
92
+ const gate=await readFile(path.join(root,'scripts','gate-windows-r39.ps1'),'utf8');
93
+ assert.match(gate,/windows-gate-evidence-r39\.mjs/,'gate-windows-r39.ps1 must invoke the evidence writer');
94
+ const result=await run(process.execPath,[path.join(root,'scripts','windows-gate-evidence-r39.mjs')],{
95
95
  cwd:root,env:{...process.env,DEADBYTE_STATE_ROOT:stateRoot}
96
96
  });
97
97
  assert.equal(result.code,0,result.stderr||result.stdout);
@@ -99,12 +99,12 @@ test('Windows R38 gate emits manifest-bound machine-readable evidence outside th
99
99
  assert.equal(summary.status,'written');
100
100
  const evidence=JSON.parse(await readFile(summary.path,'utf8'));
101
101
  const manifestSha=sha256(await readFile(path.join(root,'MANIFEST.SHA256')));
102
- assert.equal(evidence.schema,'deadbyte.r38-windows-gate.v1');
102
+ assert.equal(evidence.schema,'deadbyte.r39-windows-gate.v1');
103
103
  assert.equal(evidence.status,'passed');
104
104
  assert.equal(evidence.exit_code,0);
105
- assert.equal(evidence.version,'0.11.2');
105
+ assert.equal(evidence.version,'0.11.3');
106
106
  assert.equal(evidence.manifest_sha256,manifestSha);
107
- assert.equal(evidence.marker,'DEADBYTE V0.11.2 / R38 WINDOWS BATCH GATE: PASS');
107
+ assert.equal(evidence.marker,'DEADBYTE V0.11.3 / R39 WINDOWS BATCH GATE: PASS');
108
108
  assert.ok(summary.path.startsWith(path.join(stateRoot,'evidence','release')));
109
109
  }finally{await rm(stateRoot,{recursive:true,force:true});}
110
110
  });
@@ -2,8 +2,8 @@ import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import { readFile } from 'node:fs/promises';
4
4
  import { R34_EXPECTED_TOOLS } from '../src/remote-mcp-r34-parity-client.mjs';
5
- import { validateParityEvidence } from '../scripts/release-parity-r38.mjs';
6
- import { verifyFinalClosureObject } from '../scripts/final-closure-verify-r38.mjs';
5
+ import { validateParityEvidence } from '../scripts/release-parity-r39.mjs';
6
+ import { verifyFinalClosureObject } from '../scripts/final-closure-verify-r39.mjs';
7
7
 
8
8
  const root = new URL('../', import.meta.url);
9
9
  const text = rel => readFile(new URL(rel, root), 'utf8');
@@ -19,28 +19,28 @@ test('R34 public parity catalog is exact, unique, and includes production coding
19
19
 
20
20
  test('release parity and final verifier are package entry points', async () => {
21
21
  const pkg = JSON.parse(await text('package.json'));
22
- assert.equal(pkg.scripts['release:parity'], 'node scripts/release-parity-r38.mjs');
23
- assert.equal(pkg.scripts['release:final:write'], 'node scripts/final-closure-r38.mjs');
24
- assert.equal(pkg.scripts['release:final:verify'], 'node scripts/final-closure-verify-r38.mjs');
22
+ assert.equal(pkg.scripts['release:parity'], 'node scripts/release-parity-r39.mjs');
23
+ assert.equal(pkg.scripts['release:final:write'], 'node scripts/final-closure-r39.mjs');
24
+ assert.equal(pkg.scripts['release:final:verify'], 'node scripts/final-closure-verify-r39.mjs');
25
25
  assert.equal(typeof validateParityEvidence, 'function');
26
26
  assert.equal(typeof verifyFinalClosureObject, 'function');
27
27
  });
28
28
 
29
- test('R38 final closure verifier is implementation-independent from production helpers', async () => {
30
- const verifier = await text('scripts/final-closure-verify-r38.mjs');
31
- const writer = await text('scripts/final-closure-r38.mjs');
29
+ test('R39 final closure verifier is implementation-independent from production helpers', async () => {
30
+ const verifier = await text('scripts/final-closure-verify-r39.mjs');
31
+ const writer = await text('scripts/final-closure-r39.mjs');
32
32
  assert.doesNotMatch(verifier, /from ['"]\.\.\/src\//);
33
33
  assert.match(verifier, /DEADBYTE-R27-SLOT-UPDATE-V1/);
34
34
  assert.match(verifier, /DEADBYTE-MACHINE-PING-V1/);
35
- assert.match(verifier, /DEADBYTE-R38-FINAL-CLOSURE-V1/);
36
- assert.match(writer, /pointer\.version==='0\.11\.2'/);
37
- assert.match(verifier, /envelope\.body\.version==='0\.11\.2'/);
38
- assert.match(verifier, /release_label==='R38 FINAL MACHINE BASELINE'/);
39
- assert.match(verifier, /220fac89dd82cdcdddb82cd7d0b71b768f84a5c87d57ebaca0f5383f33d97a76/);
35
+ assert.match(verifier, /DEADBYTE-R39-FINAL-CLOSURE-V1/);
36
+ assert.match(writer, /pointer\.version==='0\.11\.3'/);
37
+ assert.match(verifier, /envelope\.body\.version==='0\.11\.3'/);
38
+ assert.match(verifier, /release_label==='R39 FINAL MACHINE BASELINE'/);
39
+ assert.match(verifier, /058605dfccaa3035a57c6393d53f2421c14e5a92bd145c2334477ba24d7cab8b/);
40
40
  });
41
41
 
42
42
  test('final closure verifier canonicalizes traversal order before exact-tree comparison', async () => {
43
- const verifier = await text('scripts/final-closure-verify-r38.mjs');
43
+ const verifier = await text('scripts/final-closure-verify-r39.mjs');
44
44
  assert.match(verifier, /const actual=\(await walk\(root\)\)\.filter\(rel=>rel!==manifestName\)\.sort\(\(a,b\)=>a\.localeCompare\(b,'en'\)\);/);
45
45
  assert.match(verifier, /const expected=\[\.\.\.entries\.keys\(\)\]\.sort\(\(a,b\)=>a\.localeCompare\(b,'en'\)\);/);
46
46
  });
@@ -24,7 +24,7 @@ test('R37 unified timeline renders one sanitized tool-call line with ISO timesta
24
24
  }
25
25
  };
26
26
  const line=formatRemoteToolCall(event);
27
- assert.match(line,/^2026-09-18T16:24:30\.125Z \| coding_file_write\s+\| Arguments: \{/);
27
+ assert.match(line,/^2026-09-18T23:24:30\.125\+07:00 \| coding_file_write\s+\| Arguments: \{/);
28
28
  assert.match(line,/"root_id":"projects"/);
29
29
  assert.match(line,/"path":"src\/example\.mjs"/);
30
30
  assert.match(line,/"reason":"payload"/);
@@ -37,7 +37,7 @@ test('R37 live tracker uses the tool-call line for request and keeps correlated
37
37
  const tracker=createLiveTimelineTracker({clock:()=>now});
38
38
  const call=tracker.observe({event_type:'tool.request',request_id:'abcdef1234567890',tool:'coding_tree',
39
39
  created_at_utc:'2026-09-18T16:24:30.125Z',args:{root_id:'projects',path:'src'}});
40
- assert.match(call,/^2026-09-18T16:24:30\.125Z \| coding_tree\s+\| Arguments: \{"path":"src","root_id":"projects"\}$/);
40
+ assert.match(call,/^2026-09-18T23:24:30\.125\+07:00 \| coding_tree\s+\| Arguments: \{"path":"src","root_id":"projects"\}$/);
41
41
  now+=250;
42
42
  assert.equal(tracker.observe({event_type:'tool.result',request_id:'abcdef1234567890',tool:'coding_tree',
43
43
  outcome:{is_error:false,duration_ms:250}}),'✓ [abcdef12] OK coding_tree 250ms');
@@ -0,0 +1,74 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { readFile } from 'node:fs/promises';
4
+ import { validateParityEvidence, R39_PREDECESSOR_RELEASE_ID, R39_PREDECESSOR_MANIFEST } from '../scripts/release-parity-r39.mjs';
5
+ import { verifyFinalClosureObject } from '../scripts/final-closure-verify-r39.mjs';
6
+
7
+ const root=new URL('../',import.meta.url);
8
+ const text=rel=>readFile(new URL(rel,root),'utf8');
9
+
10
+ function parityFixture(){
11
+ const manifest='a'.repeat(64);
12
+ return {
13
+ schema:'deadbyte.r39-parity.v1',status:'passed',execution_provider:'deadbyte_mcp',rdc_operation_count:0,
14
+ candidate:{release_id:`v0.11.3-${manifest.slice(0,16)}`,version:'0.11.3',manifest_sha256:manifest},
15
+ immutable_slot:{protected:true,release_root:'C:/immutable/r39',development_root:'D:/Projects/deadbyte-mcp-r36-dev'},
16
+ local_full:{status:'passed',tool_count:76,strict_output_schemas:true},
17
+ public_compact:{status:'passed',tool_count:41,capability_closure:true,gateway_count:5},
18
+ autonomous:{status:'passed',signed_release_verified:true,observed_failure_before_replan:true},
19
+ before_rollback_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false},
20
+ rollback:{state:'completed'},stage_restore:{status:'restored',manifest_sha256:manifest},restore:{state:'completed'},
21
+ predecessor:{release_id:R39_PREDECESSOR_RELEASE_ID,version:'0.11.2',manifest_sha256:R39_PREDECESSOR_MANIFEST},
22
+ predecessor_disarmed:{status:'passed',tool_count:41,capability_closure:true},
23
+ successor:{release_id:`v0.11.3-${manifest.slice(0,16)}`,version:'0.11.3',manifest_sha256:manifest},
24
+ successor_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false},
25
+ requirements:Object.fromEntries(['tree_read','precondition_mutation','search','owned_process','observation','coding_loop','autonomy','interrupted_recovery','evidence_verification','compact_closure','full_surface'].map(key=>[key,true]))
26
+ };
27
+ }
28
+
29
+ test('R39 parity validator requires full-76, compact closure, exact public 0.11.2 predecessor and immutable-slot separation',()=>{
30
+ const good=parityFixture();
31
+ assert.equal(validateParityEvidence(good),true);
32
+ assert.throws(()=>validateParityEvidence({...good,local_full:{...good.local_full,tool_count:75}}),/full 76/i);
33
+ assert.throws(()=>validateParityEvidence({...good,public_compact:{...good.public_compact,capability_closure:false}}),/compact closure/i);
34
+ assert.throws(()=>validateParityEvidence({...good,predecessor:{...good.predecessor,manifest_sha256:'b'.repeat(64)}}),/predecessor/i);
35
+ assert.throws(()=>validateParityEvidence({...good,immutable_slot:{...good.immutable_slot,development_root:good.immutable_slot.release_root}}),/immutable-slot/i);
36
+ assert.throws(()=>validateParityEvidence({...good,stage_restore:{status:'missing',manifest_sha256:good.candidate.manifest_sha256}}),/stage restore/i);
37
+ });
38
+
39
+ test('R39 parity captures R39 bridge, exact public 0.11.2 predecessor, stage reseed and successor restore',async()=>{
40
+ const parity=await text('scripts/release-parity-r39.mjs');
41
+ assert.match(parity,/R39_PREDECESSOR_RELEASE_ID='v0\.11\.2-058605dfccaa3035'/);
42
+ assert.match(parity,/058605dfccaa3035a57c6393d53f2421c14e5a92bd145c2334477ba24d7cab8b/);
43
+ assert.match(parity,/const stageRestore=await restoreFrozenStage/);
44
+ assert.match(parity,/publicR39Disarmed/);
45
+ assert.match(parity,/scheduleDeferred\('activate',candidateManifest,\{bridgeRoot:successorBridge\.root,bridgeScriptSha256:successorBridge\.sha256\}\)/);
46
+ });
47
+
48
+ test('R39 current final closure writer and independent verifier bind R39 domains and public 0.11.2 predecessor',async()=>{
49
+ const [writer,verifier]=await Promise.all([text('scripts/final-closure-r39.mjs'),text('scripts/final-closure-verify-r39.mjs')]);
50
+ assert.equal(typeof verifyFinalClosureObject,'function');
51
+ assert.match(writer,/DEADBYTE-R39-FINAL-CLOSURE-V1/);
52
+ assert.match(writer,/deadbyte\.r39-final-closure\.v1/);
53
+ assert.match(writer,/pointer\.version==='0\.11\.3'/);
54
+ assert.match(writer,/R39 FINAL MACHINE BASELINE/);
55
+ assert.match(writer,/deadbyte\.r39-parity\.v1/);
56
+ assert.match(writer,/deadbyte\.r39-windows-gate\.v1/);
57
+ assert.match(writer,/R39_PREDECESSOR_RELEASE_ID/);
58
+ assert.doesNotMatch(verifier,/from ['"]\.\.\/src\//);
59
+ assert.match(verifier,/DEADBYTE-R39-FINAL-CLOSURE-V1/);
60
+ assert.match(verifier,/deadbyte\.r39-final-closure\.v1/);
61
+ assert.match(verifier,/envelope\.body\.version==='0\.11\.3'/);
62
+ assert.match(verifier,/R39 FINAL MACHINE BASELINE/);
63
+ assert.match(verifier,/deadbyte\.r39-parity\.v1/);
64
+ assert.match(verifier,/deadbyte\.r39-windows-gate\.v1/);
65
+ assert.match(verifier,/058605dfccaa3035a57c6393d53f2421c14e5a92bd145c2334477ba24d7cab8b/);
66
+ });
67
+
68
+ test('R39 bounded public parity suite covers current release identity and agent fabric',async()=>{
69
+ const script=await text('scripts/release-parity-tests-r39.ps1');
70
+ assert.match(script,/r39-finalization\.test\.mjs/);
71
+ assert.match(script,/release-version\.test\.mjs/);
72
+ assert.match(script,/r37-agent-fabric\.test\.mjs/);
73
+ assert.match(script,/remote-live-log-r37\.test\.mjs/);
74
+ });
@@ -5,45 +5,48 @@ import { createHash } from 'node:crypto';
5
5
 
6
6
  const root=new URL('../',import.meta.url);
7
7
  const text=rel=>readFile(new URL(rel,root),'utf8');
8
- const R38_PREDECESSOR_RELEASE_ID='v0.11.1-220fac89dd82cdcd';
9
- const R38_PREDECESSOR_MANIFEST='220fac89dd82cdcdddb82cd7d0b71b768f84a5c87d57ebaca0f5383f33d97a76';
8
+ const R39_PREDECESSOR_RELEASE_ID='v0.11.2-058605dfccaa3035';
9
+ const R39_PREDECESSOR_MANIFEST='058605dfccaa3035a57c6393d53f2421c14e5a92bd145c2334477ba24d7cab8b';
10
10
 
11
- test('R38 hotfix authority agrees on V0.11.2 and preserves exact public 0.11.1 predecessor',async()=>{
11
+ test('R39 hotfix authority agrees on V0.11.3 and preserves exact public 0.11.2 predecessor',async()=>{
12
12
  const pkg=JSON.parse(await text('package.json'));
13
13
  const [version,controller,gate,readme,architecture,controllerReadme,deferred,parity,closure,closureVerify,windowsGate,semanticConfig]=await Promise.all([
14
- text('src/version.mjs'),text('controller/deadbyte-controller.ps1'),text('scripts/gate-windows-r38.ps1'),
14
+ text('src/version.mjs'),text('controller/deadbyte-controller.ps1'),text('scripts/gate-windows-r39.ps1'),
15
15
  text('README.txt'),text('docs/ARCHITECTURE.md'),text('controller/README.TXT'),
16
- text('scripts/deferred-slot-operation-r38.mjs'),text('scripts/release-parity-r38.mjs'),text('scripts/final-closure-r38.mjs'),
17
- text('scripts/final-closure-verify-r38.mjs'),text('scripts/windows-gate-evidence-r38.mjs'),
16
+ text('scripts/deferred-slot-operation-r39.mjs'),text('scripts/release-parity-r39.mjs'),text('scripts/final-closure-r39.mjs'),
17
+ text('scripts/final-closure-verify-r39.mjs'),text('scripts/windows-gate-evidence-r39.mjs'),
18
18
  text('controller/deadbyte-semantic-lsp-config.json')
19
19
  ]);
20
- assert.equal(pkg.version,'0.11.2');
21
- assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r38.ps1');
22
- assert.equal(pkg.scripts['self-update:deferred'],'node scripts/deferred-slot-operation-r38.mjs');
23
- assert.equal(pkg.scripts['release:parity'],'node scripts/release-parity-r38.mjs');
24
- assert.equal(pkg.scripts['release:final:write'],'node scripts/final-closure-r38.mjs');
25
- assert.equal(pkg.scripts['release:final:verify'],'node scripts/final-closure-verify-r38.mjs');
26
- assert.match(version,/DEADBYTE_VERSION = '0\.11\.2'/);
27
- assert.match(controller,/CONTROLLER V0\.11\.2 \/ R38/);
28
- assert.match(gate,/DEADBYTE V0\.11\.2 \/ R38 WINDOWS BATCH GATE: PASS/);
29
- assert.match(readme,/^DEADBYTE MCP V0\.11\.2 \/ R38 HOTFIX BASELINE$/m);
30
- assert.match(architecture,/^# DEADBYTE MCP V0\.11\.2 \/ R38 ARCHITECTURE$/m);
31
- assert.match(controllerReadme,/^DEADBYTE MCP V0\.11\.2 \/ R38 CONTROLLER$/m);
32
- assert.match(deferred,/--expected-version','0\.11\.2'/);
33
- assert.match(parity,/R38_PREDECESSOR_RELEASE_ID='v0\.11\.1-220fac89dd82cdcd'/);
34
- assert.match(parity,new RegExp(R38_PREDECESSOR_MANIFEST));
35
- assert.match(parity,/version==='0\.11\.2'|version:'0\.11\.2'/);
36
- assert.match(closure,/version:'0\.11\.2'/);
37
- assert.match(closureVerify,/DEADBYTE V0\.11\.2 \/ R38 WINDOWS BATCH GATE: PASS/);
38
- assert.match(windowsGate,/version:'0\.11\.2'/);
20
+ assert.equal(pkg.version,'0.11.3');
21
+ assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r39.ps1');
22
+ assert.equal(pkg.scripts['self-update:deferred'],'node scripts/deferred-slot-operation-r39.mjs');
23
+ assert.equal(pkg.scripts['release:parity'],'node scripts/release-parity-r39.mjs');
24
+ assert.equal(pkg.scripts['release:final:write'],'node scripts/final-closure-r39.mjs');
25
+ assert.equal(pkg.scripts['release:final:verify'],'node scripts/final-closure-verify-r39.mjs');
26
+ assert.match(version,/DEADBYTE_VERSION = '0\.11\.3'/);
27
+ assert.match(controller,/CONTROLLER V0\.11\.3 \/ R39/);
28
+ assert.match(gate,/DEADBYTE V0\.11\.3 \/ R39 WINDOWS BATCH GATE: PASS/);
29
+ assert.match(readme,/^DEADBYTE MCP V0\.11\.3 \/ R39 HOTFIX BASELINE$/m);
30
+ assert.match(architecture,/^# DEADBYTE MCP V0\.11\.3 \/ R39 ARCHITECTURE$/m);
31
+ assert.match(controllerReadme,/^DEADBYTE MCP V0\.11\.3 \/ R39 CONTROLLER$/m);
32
+ assert.match(deferred,/--expected-version','0\.11\.3'/);
33
+ assert.match(parity,/R39_PREDECESSOR_RELEASE_ID='v0\.11\.2-058605dfccaa3035'/);
34
+ assert.match(parity,new RegExp(R39_PREDECESSOR_MANIFEST));
35
+ assert.match(parity,/version==='0\.11\.3'|version:'0\.11\.3'/);
36
+ assert.match(closure,/version:'0\.11\.3'/);
37
+ assert.match(closureVerify,/DEADBYTE V0\.11\.3 \/ R39 WINDOWS BATCH GATE: PASS/);
38
+ assert.match(windowsGate,/version:'0\.11\.3'/);
39
39
  assert.equal(createHash('sha256').update(Buffer.from(semanticConfig,'utf8')).digest('hex'),'d274b099a298c1033fea8f1e8849751693bbc0448778d619400acb82d4f53a3b');
40
- assert.equal(R38_PREDECESSOR_RELEASE_ID,'v0.11.1-220fac89dd82cdcd');
40
+ assert.equal(R39_PREDECESSOR_RELEASE_ID,'v0.11.2-058605dfccaa3035');
41
41
  });
42
42
 
43
- test('R38 hotfix keeps ONLINE reuse and fixes PowerShell $Host recovery collision',async()=>{
43
+ test('R39 hotfix keeps ONLINE reuse and fixes PowerShell $Host recovery collision',async()=>{
44
44
  const [cli,controller]=await Promise.all([text('src/deadbyte-cli.mjs'),text('controller/deadbyte-controller.ps1')]);
45
45
  assert.match(cli,/controllerRuntimeReady/);
46
46
  assert.match(cli,/Runtime already ONLINE; reusing verified bridge\/cloud\/supervisor/);
47
+ assert.match(cli,/invokeController\(ctx,'start',\{discardOutput:true,timeoutMs:REMOTE_START_TIMEOUT_MS\}\)/);
48
+ assert.match(cli,/remote controller start returned without a verified ONLINE runtime/);
49
+ assert.match(cli,/discardOutput\?\['ignore','ignore','ignore'\]/);
47
50
  const start=controller.indexOf('function Recover-AutonomousSupervisor');
48
51
  const end=controller.indexOf('function Show-State',start);
49
52
  assert.ok(start>=0&&end>start,'supervisor recovery block missing');
@@ -7,7 +7,7 @@ test('R37 live timeline renders sanitized tool-call detail and correlates termin
7
7
  const tracker=createLiveTimelineTracker({clock:()=>now});
8
8
  const run=tracker.observe({event_type:'tool.request',tool:'coding_file_read',request_id:'abcdef1234567890',
9
9
  args:{root_id:'projects',path:'src/a.mjs',content:'SECRET',token:'SECRET'}});
10
- assert.match(run,/^1970-01-01T00:00:01\.000Z \| coding_file_read\s+\| Arguments: \{/);
10
+ assert.match(run,/^1970-01-01T07:00:01\.000\+07:00 \| coding_file_read\s+\| Arguments: \{/);
11
11
  assert.match(run,/\"path\":\"src\/a\.mjs\"/);
12
12
  assert.match(run,/\"reason\":\"payload\"/);
13
13
  assert.match(run,/\"reason\":\"secret\"/);
@@ -16,11 +16,15 @@ async function fixture({failCommand='',statusOnline=false}={}){
16
16
  const state=path.join(dir,'state');
17
17
  const bin=path.join(state,'bin');
18
18
  const trace=path.join(dir,'trace.txt');
19
+ const startedMarker=path.join(dir,'started.txt');
20
+ const spawnedStdout=path.join(dir,'spawned.stdout.log');
21
+ const spawnedStderr=path.join(dir,'spawned.stderr.log');
22
+ const spawnedPid=path.join(dir,'spawned.pid');
19
23
  await mkdir(bin,{recursive:true});
20
24
  const launcher=path.join(bin,'DEADBYTE-MCP.ps1');
21
- const ps1=`param([string]$Command)\n$ErrorActionPreference='Stop'\nfor($i=0;$i -lt 20;$i++){ try { [IO.File]::AppendAllText($env:DEADBYTE_REMOTE_TEST_TRACE,(\"$Command\" + [Environment]::NewLine),[Text.Encoding]::UTF8); break } catch { if($i -eq 19){ throw }; Start-Sleep -Milliseconds 10 } }\nif ($env:DEADBYTE_REMOTE_TEST_FAIL -and $Command -eq $env:DEADBYTE_REMOTE_TEST_FAIL) { Write-Error \"forced $Command failure\"; exit 9 }\nswitch ($Command) {\n 'start' { Write-Host 'DEADBYTE MCP = ONLINE' }\n 'status' { if ($env:DEADBYTE_REMOTE_TEST_STATUS_ONLINE -eq '1') { Write-Host 'DEADBYTE MCP = ONLINE'; Write-Host 'Bridge PID : 1001 [verified]'; Write-Host 'Cloud PID : 1002 [verified]'; Write-Host 'Local ready : True'; Write-Host 'Loop supervisor: RUNNING [verified]' } else { Write-Host 'DEADBYTE MCP = OFFLINE' } }\n 'processstatus' { Write-Host 'Process plane : ARMED [standing-grant]' }\n 'codingstatus' { Write-Host 'Coding plane : ARMED [standing-grant]' }\n 'autonomousstatus' { Write-Host 'Autonomous : ARMED [standing-grant]' }\n 'hoststatus' { Write-Host 'Host plane : DISARMED [disarmed]' }\n 'park' { Write-Host 'DEADBYTE MCP = PARKED' }\n default { Write-Host \"$Command OK\" }\n}\nexit 0\n`;
25
+ const ps1=`param([string]$Command)\n$ErrorActionPreference='Stop'\nfor($i=0;$i -lt 20;$i++){ try { [IO.File]::AppendAllText($env:DEADBYTE_REMOTE_TEST_TRACE,(\"$Command\" + [Environment]::NewLine),[Text.Encoding]::UTF8); break } catch { if($i -eq 19){ throw }; Start-Sleep -Milliseconds 10 } }\nif ($env:DEADBYTE_REMOTE_TEST_FAIL -and $Command -eq $env:DEADBYTE_REMOTE_TEST_FAIL) { Write-Error \"forced $Command failure\"; exit 9 }\nswitch ($Command) {\n 'start' { if ($env:DEADBYTE_REMOTE_TEST_SPAWN_CHILD -eq '1') { $node=(Get-Command node.exe).Source; $spawned=Start-Process -FilePath $node -ArgumentList @('-e','setTimeout(()=>process.exit(0),10000)') -PassThru -WindowStyle Hidden -RedirectStandardOutput $env:DEADBYTE_REMOTE_TEST_SPAWN_STDOUT -RedirectStandardError $env:DEADBYTE_REMOTE_TEST_SPAWN_STDERR; if ($env:DEADBYTE_REMOTE_TEST_SPAWN_PID) { [IO.File]::WriteAllText($env:DEADBYTE_REMOTE_TEST_SPAWN_PID,[string]$spawned.Id,[Text.Encoding]::UTF8) } }; if ($env:DEADBYTE_REMOTE_TEST_STARTED) { [IO.File]::WriteAllText($env:DEADBYTE_REMOTE_TEST_STARTED,'1',[Text.Encoding]::UTF8) }; Write-Host 'DEADBYTE MCP = ONLINE' }\n 'status' { if ($env:DEADBYTE_REMOTE_TEST_STATUS_ONLINE -eq '1' -or ($env:DEADBYTE_REMOTE_TEST_STARTED -and (Test-Path -LiteralPath $env:DEADBYTE_REMOTE_TEST_STARTED))) { Write-Host 'DEADBYTE MCP = ONLINE'; Write-Host 'Bridge PID : 1001 [verified]'; Write-Host 'Cloud PID : 1002 [verified]'; Write-Host 'Local ready : True'; Write-Host 'Loop supervisor: RUNNING [verified]' } else { Write-Host 'DEADBYTE MCP = OFFLINE' } }\n 'processstatus' { Write-Host 'Process plane : ARMED [standing-grant]' }\n 'codingstatus' { Write-Host 'Coding plane : ARMED [standing-grant]' }\n 'autonomousstatus' { Write-Host 'Autonomous : ARMED [standing-grant]' }\n 'hoststatus' { Write-Host 'Host plane : DISARMED [disarmed]' }\n 'park' { if ($env:DEADBYTE_REMOTE_TEST_STARTED) { Remove-Item -LiteralPath $env:DEADBYTE_REMOTE_TEST_STARTED -Force -ErrorAction SilentlyContinue }; Write-Host 'DEADBYTE MCP = PARKED' }\n default { Write-Host \"$Command OK\" }\n}\nexit 0\n`;
22
26
  await writeFile(launcher,ps1,'utf8');
23
- return {dir,state,trace,env:{...process.env,DEADBYTE_STATE_ROOT:state,DEADBYTE_REMOTE_TEST_TRACE:trace,DEADBYTE_REMOTE_TEST_FAIL:failCommand,DEADBYTE_REMOTE_TEST_STATUS_ONLINE:statusOnline?'1':'0'}};
27
+ return {dir,state,trace,env:{...process.env,DEADBYTE_STATE_ROOT:state,DEADBYTE_REMOTE_TEST_TRACE:trace,DEADBYTE_REMOTE_TEST_FAIL:failCommand,DEADBYTE_REMOTE_TEST_STATUS_ONLINE:statusOnline?'1':'0',DEADBYTE_REMOTE_TEST_STARTED:startedMarker,DEADBYTE_REMOTE_TEST_SPAWN_STDOUT:spawnedStdout,DEADBYTE_REMOTE_TEST_SPAWN_STDERR:spawnedStderr,DEADBYTE_REMOTE_TEST_SPAWN_PID:spawnedPid},spawnedPid};
24
28
  }
25
29
 
26
30
  async function traceCommands(file,{read=readFile,retryDelayMs=10,maxAttempts=20}={}){
@@ -90,15 +94,45 @@ winTest('bare remote reuses a fully verified ONLINE runtime without invoking blo
90
94
  }
91
95
  });
92
96
 
97
+ winTest('bare remote PARKED startup does not wait for a long-lived child holding inherited pipe handles',async()=>{
98
+ const fx=await fixture();
99
+ fx.env.DEADBYTE_REMOTE_TEST_SPAWN_CHILD='1';
100
+ let child=null;
101
+ try{
102
+ const startedAt=Date.now();
103
+ child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
104
+ const output=await collect(child);
105
+ const ready=await waitFor(fx.trace,commands=>commands.includes('hoststatus'),{timeoutMs:8000});
106
+ const elapsed=Date.now()-startedAt;
107
+ assert.deepEqual(ready.slice(0,10),[
108
+ 'status','start','status','armprocess','armcoding','armautonomous',
109
+ 'processstatus','codingstatus','autonomousstatus','hoststatus'
110
+ ]);
111
+ assert.ok(elapsed<7000,`PARKED startup waited on inherited child pipe handles: ${elapsed}ms`);
112
+ assert.equal(child.exitCode,null,'remote session must remain foreground after PARKED startup');
113
+ assert.match(output.stdout,/\[BOOT\] Starting bridge\/runtime\.\.\./);
114
+ assert.match(output.stdout,/\[OK\] ONLINE/);
115
+ child.stdin.end();
116
+ const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
117
+ assert.equal(ended.timeout,undefined,'remote session did not exit after PARKED startup proof');
118
+ assert.equal(ended.code,0,output.stderr);
119
+ }finally{
120
+ if(child?.exitCode===null) child.kill('SIGKILL');
121
+ try{const pid=Number((await readFile(fx.spawnedPid,'utf8')).trim());if(Number.isInteger(pid)&&pid>0) process.kill(pid,'SIGKILL');}catch{}
122
+ await sleep(100);
123
+ await rm(fx.dir,{recursive:true,force:true});
124
+ }
125
+ });
126
+
93
127
  winTest('bare remote uses one unified live timeline, keeps authority semantics, then disarms and parks when the foreground session ends',async()=>{
94
128
  const fx=await fixture();
95
129
  let child=null;
96
130
  try{
97
131
  child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
98
132
  const output=await collect(child);
99
- const ready=await waitFor(fx.trace,commands=>commands.slice(0,9).join(',')==='status,start,armprocess,armcoding,armautonomous,processstatus,codingstatus,autonomousstatus,hoststatus');
100
- assert.deepEqual(ready.slice(0,9),[
101
- 'status','start','armprocess','armcoding','armautonomous',
133
+ const ready=await waitFor(fx.trace,commands=>commands.slice(0,10).join(',')==='status,start,status,armprocess,armcoding,armautonomous,processstatus,codingstatus,autonomousstatus,hoststatus');
134
+ assert.deepEqual(ready.slice(0,10),[
135
+ 'status','start','status','armprocess','armcoding','armautonomous',
102
136
  'processstatus','codingstatus','autonomousstatus','hoststatus'
103
137
  ]);
104
138
  assert.equal(child.exitCode,null,'remote session must remain foreground after becoming ready');
@@ -136,9 +170,9 @@ winTest('bare remote uses one unified live timeline, keeps authority semantics,
136
170
  ].join('\n')+'\n','utf8');
137
171
  const logDeadline=Date.now()+3000;
138
172
  while(Date.now()<logDeadline&&!/✗ \[fedcba98\] ERR coding_file_read 1\.73s/.test(output.stdout)) await sleep(50);
139
- assert.match(output.stdout,/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z \| coding_tree\s+\| Arguments: .*\"path\":\"src\".*\"root_id\":\"projects\".*\[cursor r1:[0-9a-f]{24}:1\]$/m);
173
+ assert.match(output.stdout,/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\+07:00 \| coding_tree\s+\| Arguments: .*\"path\":\"src\".*\"root_id\":\"projects\".*\[cursor r1:[0-9a-f]{24}:1\]$/m);
140
174
  assert.match(output.stdout,/✓ \[abcdef12\] OK coding_tree 42ms \[cursor r1:[0-9a-f]{24}:2\]/);
141
- assert.match(output.stdout,/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}Z \| coding_file_read\s+\| Arguments: \{\"path\":\"src\/deadbyte-cli\.mjs\",\"root_id\":\"projects\"\} \[cursor r1:[0-9a-f]{24}:3\]$/m);
175
+ assert.match(output.stdout,/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\.[0-9]{3}\+07:00 \| coding_file_read\s+\| Arguments: \{\"path\":\"src\/deadbyte-cli\.mjs\",\"root_id\":\"projects\"\} \[cursor r1:[0-9a-f]{24}:3\]$/m);
142
176
  assert.match(output.stdout,/✗ \[fedcba98\] ERR coding_file_read 1\.73s \[cursor r1:[0-9a-f]{24}:4\]/);
143
177
  assert.equal((output.stdout.match(/✓ \[abcdef12\] OK coding_tree 42ms/g)||[]).length,1,'duplicate terminal result must print once');
144
178
  const resultJournal=JSON.parse(await readFile(path.join(fx.state,'runtime','remote-results',`${marker.result_session_id}.json`),'utf8'));
@@ -209,7 +243,7 @@ winTest('remote --resume replays sanitized tool-call and terminal result events
209
243
  while(Date.now()<deadline&&(!/coding_file_read\s+\| Arguments: .*REPLAY cursor r1:[0-9a-f]{24}:3/.test(secondOutput.stdout)||
210
244
  !/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:4\]/.test(secondOutput.stdout)||
211
245
  !/\[LOG\] Unified live timeline/.test(secondOutput.stdout))) await sleep(50);
212
- assert.match(secondOutput.stdout,/^2026-09-18T16:30:01\.000Z \| coding_file_read\s+\| Arguments: .*\"path\":\"src\/deadbyte-cli\.mjs\".*REPLAY cursor r1:[0-9a-f]{24}:3$/m);
246
+ assert.match(secondOutput.stdout,/^2026-09-18T23:30:01\.000\+07:00 \| coding_file_read\s+\| Arguments: .*\"path\":\"src\/deadbyte-cli\.mjs\".*REPLAY cursor r1:[0-9a-f]{24}:3$/m);
213
247
  assert.match(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:4\]/);
214
248
  assert.match(secondOutput.stdout,/♻️ \[SESSION\] Previous result stream replayed/);
215
249
  assert.doesNotMatch(secondOutput.stdout,/DO_NOT_REPLAY_SECRET/);
@@ -249,9 +283,9 @@ winTest('detached guardian revokes authority, parks, and removes the session mar
249
283
  try{
250
284
  child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
251
285
  const output=await collect(child);
252
- const ready=await waitFor(fx.trace,commands=>commands.slice(0,8).join(',')==='start,armprocess,armcoding,armautonomous,processstatus,codingstatus,autonomousstatus,hoststatus');
253
- assert.deepEqual(ready.slice(0,9),[
254
- 'status','start','armprocess','armcoding','armautonomous',
286
+ const ready=await waitFor(fx.trace,commands=>commands.slice(0,10).join(',')==='status,start,status,armprocess,armcoding,armautonomous,processstatus,codingstatus,autonomousstatus,hoststatus');
287
+ assert.deepEqual(ready.slice(0,10),[
288
+ 'status','start','status','armprocess','armcoding','armautonomous',
255
289
  'processstatus','codingstatus','autonomousstatus','hoststatus'
256
290
  ]);
257
291
  const markerPath=path.join(fx.state,'runtime','remote-session.json');
@@ -294,7 +328,7 @@ winTest('bare remote rolls back authority and parks if one plane fails to arm',a
294
328
  assert.equal(ended.timeout,undefined,'failed startup did not terminate');
295
329
  assert.notEqual(ended.code,0);
296
330
  const commands=await traceCommands(fx.trace);
297
- assert.deepEqual(commands.slice(0,4),['status','start','armprocess','armcoding']);
331
+ assert.deepEqual(commands.slice(0,5),['status','start','status','armprocess','armcoding']);
298
332
  assert.deepEqual(commands.slice(-5),['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park']);
299
333
  assert.doesNotMatch(output.stdout,/Live logs/i);
300
334
  }finally{await rm(fx.dir,{recursive:true,force:true});}