deadbyte-mcp 0.11.0 → 0.11.1

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 (65) hide show
  1. package/MANIFEST.SHA256 +64 -56
  2. package/README.txt +7 -7
  3. package/bin/WORKER-REGISTRY.txt +3 -3
  4. package/bin/appcontainer-stage.exe +0 -0
  5. package/bin/appcontainer-stage.obj +0 -0
  6. package/bin/bootstrap-advapi32.exe +0 -0
  7. package/bin/bootstrap-advapi32.obj +0 -0
  8. package/bin/bootstrap-exitcode.exe +0 -0
  9. package/bin/bootstrap-exitcode.obj +0 -0
  10. package/bin/bootstrap-kernel32.exe +0 -0
  11. package/bin/bootstrap-kernel32.obj +0 -0
  12. package/bin/child-control-probe.exe +0 -0
  13. package/bin/child-control-probe.obj +0 -0
  14. package/bin/child-control-stage.exe +0 -0
  15. package/bin/child-control-stage.obj +0 -0
  16. package/bin/contained-reverse-worker.exe +0 -0
  17. package/bin/contained-reverse-worker.obj +0 -0
  18. package/bin/contained-transform-worker.exe +0 -0
  19. package/bin/contained-transform-worker.obj +0 -0
  20. package/bin/containment-probe.exe +0 -0
  21. package/bin/containment-probe.obj +0 -0
  22. package/bin/deadbyte-contain.exe +0 -0
  23. package/bin/deadbyte-contain.obj +0 -0
  24. package/bin/deadbyte-exec.exe +0 -0
  25. package/bin/deadbyte-exec.obj +0 -0
  26. package/bin/deadbyte-process-host.exe +0 -0
  27. package/bin/deadbyte-process-host.obj +0 -0
  28. package/bin/deadbyte-tunnel-host.exe +0 -0
  29. package/bin/deadbyte-tunnel-host.obj +0 -0
  30. package/controller/README.TXT +1 -1
  31. package/controller/deadbyte-controller.ps1 +1 -1
  32. package/controller/deadbyte-process-policy.json +1 -1
  33. package/docs/ARCHITECTURE.md +1 -1
  34. package/package.json +1 -1
  35. package/scripts/build-containment.ps1 +15 -15
  36. package/scripts/deferred-slot-operation-r37-0110.mjs +124 -0
  37. package/scripts/deferred-slot-operation.mjs +1 -1
  38. package/scripts/final-closure-r37-0110.mjs +113 -0
  39. package/scripts/final-closure-verify-r37-0110.mjs +208 -0
  40. package/scripts/final-closure-verify.mjs +16 -16
  41. package/scripts/final-closure.mjs +8 -8
  42. package/scripts/gate-windows-r37-0110.ps1 +42 -0
  43. package/scripts/gate-windows.ps1 +3 -3
  44. package/scripts/release-parity-r37-0110.mjs +200 -0
  45. package/scripts/release-parity-tests.ps1 +1 -1
  46. package/scripts/release-parity.mjs +14 -14
  47. package/scripts/windows-gate-evidence-r37-0110.mjs +52 -0
  48. package/scripts/windows-gate-evidence.mjs +4 -4
  49. package/src/deadbyte-cli.mjs +58 -23
  50. package/src/remote-live-log.mjs +23 -1
  51. package/src/remote-result-journal.mjs +23 -4
  52. package/src/version.mjs +1 -1
  53. package/test/cli-entrypoint.test.mjs +9 -0
  54. package/test/containment.test.mjs +18 -0
  55. package/test/core.test.mjs +1 -1
  56. package/test/production-docs.test.mjs +3 -3
  57. package/test/r33-closeout-regression.test.mjs +2 -2
  58. package/test/r33-finalization.test.mjs +3 -3
  59. package/test/r36-release-identity.test.mjs +4 -4
  60. package/test/r37-0110-history.test.mjs +20 -0
  61. package/test/r37-finalization.test.mjs +14 -14
  62. package/test/r37-remote-tool-call-timeline.test.mjs +94 -0
  63. package/test/release-version.test.mjs +22 -29
  64. package/test/remote-live-log-r37.test.mjs +5 -2
  65. package/test/remote-session-cli.test.mjs +66 -25
package/src/version.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export const DEADBYTE_VERSION = '0.11.0';
1
+ export const DEADBYTE_VERSION = '0.11.1';
2
2
  export const MCP_PROTOCOL_VERSION = '2026-07-28';
3
3
  export const RECEIPT_SCHEMA_V1 = 'deadbyte.receipt.v1';
4
4
  export const RECEIPT_SCHEMA_V2 = 'deadbyte.receipt.v2';
@@ -1,6 +1,7 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import { readFile } from 'node:fs/promises';
4
+ import { spawnSync } from 'node:child_process';
4
5
  import path from 'node:path';
5
6
  import { fileURLToPath } from 'node:url';
6
7
 
@@ -16,6 +17,14 @@ test('package exposes npx-first deadbyte-mcp bin and is registry-publishable',as
16
17
  assert.equal(pkg.publishConfig?.access,'public');
17
18
  });
18
19
 
20
+ test('npx CLI reports the canonical package version through --version, -v and version',()=>{
21
+ for(const arg of ['--version','-v','version']){
22
+ const result=spawnSync(process.execPath,[cliPath,arg],{cwd:root,encoding:'utf8',windowsHide:true});
23
+ assert.equal(result.status,0,result.stderr);
24
+ assert.equal(result.stdout.trim(),'0.11.1');
25
+ }
26
+ });
27
+
19
28
  test('npx CLI remote path invokes stable PS1 directly and never routes through CMD',async()=>{
20
29
  const source=await readFile(cliPath,'utf8');
21
30
  assert.match(source,/^#!\/usr\/bin\/env node/m);
@@ -230,6 +230,24 @@ test('native build script targets Windows 10 and preserves MSVC diagnostics', as
230
230
  assert.doesNotMatch(source, /\$VsWhere = Join-Path \$\{env:ProgramFiles\(x86\)\}/);
231
231
  });
232
232
 
233
+ test('native build is reproducible at both MSVC object and linker boundaries', async () => {
234
+ const buildScript = fileURLToPath(new URL('../scripts/build-containment.ps1', import.meta.url));
235
+ const source = await readFile(buildScript, 'utf8');
236
+ const lines = source.split(/\r?\n/);
237
+ const commonLine = lines.find(line => line.startsWith('$Common ='));
238
+ const bootstrapLine = lines.find(line => line.startsWith('$BootstrapCommon ='));
239
+ assert.ok(commonLine?.includes('/Brepro'), 'common compiler flags must include /Brepro');
240
+ assert.ok(bootstrapLine?.includes('/Brepro'), 'bootstrap compiler flags must include /Brepro');
241
+ for (const name of [
242
+ 'Launcher','Probe','BootstrapKernel','BootstrapAdvapi','StageLauncher','BootstrapExit',
243
+ 'ChildControlStage','ChildControlProbe','ContainedLauncher','ContainedWorker',
244
+ 'ContainedReverseWorker','TunnelHost','ProcessHost'
245
+ ]) {
246
+ const line = lines.find(candidate => candidate.startsWith(`$${name}Command =`));
247
+ assert.ok(line?.includes('/link /Brepro /INCREMENTAL:NO'), `${name} linker flags must be reproducible and non-incremental`);
248
+ }
249
+ });
250
+
233
251
 
234
252
 
235
253
  test('native build command composition is Windows PowerShell 5.1 parser-safe', async () => {
@@ -105,7 +105,7 @@ test('proof execution creates deterministic output and signed verifiable receipt
105
105
  assert.equal(result.receipt.request.schema, 'deadbyte.request.v1');
106
106
  assert.match(result.receipt.request.nonce, /^[0-9a-f]{64}$/);
107
107
  assert.match(result.receipt.request.sha256, /^[0-9a-f]{64}$/);
108
- assert.equal(result.receipt.runtime.package_version, '0.11.0');
108
+ assert.equal(result.receipt.runtime.package_version, '0.11.1');
109
109
  assert.match(result.receipt.runtime.mcp_ingress_adapter, /^(?:none|tunnel-stdio-probe-compat-v1)$/);
110
110
  assert.match(result.receipt.runtime.mcp_ingress_adapter_sha256, /^[0-9a-f]{64}$/);
111
111
  assert.match(result.receipt.runtime.mcp_ingress_mode_source_sha256, /^[0-9a-f]{64}$/);
@@ -9,9 +9,9 @@ const readme=()=>readFile(path.join(root,'README.txt'),'utf8');
9
9
 
10
10
  test('production README documents one-command stdio configs for major MCP clients',async()=>{
11
11
  const text=await readme();
12
- assert.match(text,/npx -y deadbyte-mcp@0\.11\.0 mcp/);
12
+ assert.match(text,/npx -y deadbyte-mcp@0\.11\.1 mcp/);
13
13
  assert.match(text,/CLAUDE DESKTOP/);
14
- assert.match(text,/"mcpServers"[\s\S]*?"command"\s*:\s*"npx"[\s\S]*?"-y"[\s\S]*?"deadbyte-mcp@0\.11\.0"[\s\S]*?"mcp"/);
14
+ assert.match(text,/"mcpServers"[\s\S]*?"command"\s*:\s*"npx"[\s\S]*?"-y"[\s\S]*?"deadbyte-mcp@0\.11\.1"[\s\S]*?"mcp"/);
15
15
  assert.match(text,/CURSOR/);
16
16
  assert.match(text,/\.cursor\/mcp\.json/);
17
17
  assert.match(text,/VS CODE/);
@@ -20,7 +20,7 @@ test('production README documents one-command stdio configs for major MCP client
20
20
  assert.match(text,/CODEX/);
21
21
  assert.match(text,/\[mcp_servers\.deadbyte\]/);
22
22
  assert.match(text,/command\s*=\s*"npx"/);
23
- assert.match(text,/args\s*=\s*\["-y",\s*"deadbyte-mcp@0\.11\.0",\s*"mcp"\]/);
23
+ assert.match(text,/args\s*=\s*\["-y",\s*"deadbyte-mcp@0\.11\.1",\s*"mcp"\]/);
24
24
  });
25
25
 
26
26
  test('production README records tracer bullet, semantic scope, remote UX, safety and document extension',async()=>{
@@ -102,9 +102,9 @@ test('Windows R37 gate emits manifest-bound machine-readable evidence outside th
102
102
  assert.equal(evidence.schema,'deadbyte.r37-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.0');
105
+ assert.equal(evidence.version,'0.11.1');
106
106
  assert.equal(evidence.manifest_sha256,manifestSha);
107
- assert.equal(evidence.marker,'DEADBYTE V0.11.0 / R37 WINDOWS BATCH GATE: PASS');
107
+ assert.equal(evidence.marker,'DEADBYTE V0.11.1 / R37 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
  });
@@ -33,10 +33,10 @@ test('R37 final closure verifier is implementation-independent from production h
33
33
  assert.match(verifier, /DEADBYTE-R27-SLOT-UPDATE-V1/);
34
34
  assert.match(verifier, /DEADBYTE-MACHINE-PING-V1/);
35
35
  assert.match(verifier, /DEADBYTE-R37-FINAL-CLOSURE-V1/);
36
- assert.match(writer, /pointer\.version==='0\.11\.0'/);
37
- assert.match(verifier, /envelope\.body\.version==='0\.11\.0'/);
36
+ assert.match(writer, /pointer\.version==='0\.11\.1'/);
37
+ assert.match(verifier, /envelope\.body\.version==='0\.11\.1'/);
38
38
  assert.match(verifier, /release_label==='R37 FINAL MACHINE BASELINE'/);
39
- assert.match(verifier, /8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8/);
39
+ assert.match(verifier, /08c2a0008b1f84c90f7ce7faa1e3decbd03f33612bc0fdc7d1ba591b548798e8/);
40
40
  });
41
41
 
42
42
  test('final closure verifier canonicalizes traversal order before exact-tree comparison', async () => {
@@ -10,10 +10,10 @@ const R36_RELEASE_ID='v0.10.0-8d1e5f09745e7647';
10
10
  const R36_MANIFEST='8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8';
11
11
 
12
12
  test('sealed R36 historical proof scripts preserve 0.10.0 / R36 and exact R35 predecessor',async()=>{
13
- const [gate,parity,closure,closureVerify,windowsGate,currentParity]=await Promise.all([
13
+ const [gate,parity,closure,closureVerify,windowsGate,r37_0110Parity]=await Promise.all([
14
14
  text('scripts/gate-windows-r36.ps1'),text('scripts/release-parity-r36.mjs'),
15
15
  text('scripts/final-closure-r36.mjs'),text('scripts/final-closure-verify-r36.mjs'),
16
- text('scripts/windows-gate-evidence-r36.mjs'),text('scripts/release-parity.mjs')
16
+ text('scripts/windows-gate-evidence-r36.mjs'),text('scripts/release-parity-r37-0110.mjs')
17
17
  ]);
18
18
  assert.match(gate,/DEADBYTE V0\.10\.0 \/ R36 WINDOWS BATCH GATE: PASS/);
19
19
  assert.match(parity,/deadbyte\.r36-parity\.v1/);
@@ -23,8 +23,8 @@ test('sealed R36 historical proof scripts preserve 0.10.0 / R36 and exact R35 pr
23
23
  assert.match(closure,/version:'0\.10\.0'/);
24
24
  assert.match(closureVerify,/DEADBYTE-R36-FINAL-CLOSURE-V1/);
25
25
  assert.match(windowsGate,/deadbyte\.r36-windows-gate\.v1/);
26
- assert.match(currentParity,new RegExp(R36_RELEASE_ID.replaceAll('.','\\.')));
27
- assert.match(currentParity,new RegExp(R36_MANIFEST));
26
+ assert.match(r37_0110Parity,new RegExp(R36_RELEASE_ID.replaceAll('.','\\.')));
27
+ assert.match(r37_0110Parity,new RegExp(R36_MANIFEST));
28
28
  });
29
29
 
30
30
  test('current R37 controller still binds production remote to compact profile and restores parent environment',async()=>{
@@ -0,0 +1,20 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { readFile } from 'node:fs/promises';
4
+ const root=new URL('../',import.meta.url);
5
+ const text=rel=>readFile(new URL(rel,root),'utf8');
6
+
7
+ test('sealed public 0.11.0 release scripts remain preserved as historical R37 authority',async()=>{
8
+ const [gate,evidence,parity,closure,verify,deferred]=await Promise.all([
9
+ text('scripts/gate-windows-r37-0110.ps1'),text('scripts/windows-gate-evidence-r37-0110.mjs'),
10
+ text('scripts/release-parity-r37-0110.mjs'),text('scripts/final-closure-r37-0110.mjs'),
11
+ text('scripts/final-closure-verify-r37-0110.mjs'),text('scripts/deferred-slot-operation-r37-0110.mjs')
12
+ ]);
13
+ assert.match(gate,/V0\.11\.0 \/ R37/);
14
+ assert.match(evidence,/version:'0\.11\.0'/);
15
+ assert.match(parity,/v0\.10\.0-8d1e5f09745e7647/);
16
+ assert.match(parity,/candidate\?\.version==='0\.11\.0'/);
17
+ assert.match(closure,/version:'0\.11\.0'/);
18
+ assert.match(verify,/value\?\.version==='0\.11\.0'/);
19
+ assert.match(deferred,/--expected-version','0\.11\.0'/);
20
+ });
@@ -1,7 +1,7 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import { readFile } from 'node:fs/promises';
4
- import { validateParityEvidence, R36_PREDECESSOR_RELEASE_ID, R36_PREDECESSOR_MANIFEST } from '../scripts/release-parity.mjs';
4
+ import { validateParityEvidence, R37_PREDECESSOR_RELEASE_ID, R37_PREDECESSOR_MANIFEST } from '../scripts/release-parity.mjs';
5
5
  import { verifyFinalClosureObject } from '../scripts/final-closure-verify.mjs';
6
6
 
7
7
  const root=new URL('../',import.meta.url);
@@ -11,22 +11,22 @@ function parityFixture(){
11
11
  const manifest='a'.repeat(64);
12
12
  return {
13
13
  schema:'deadbyte.r37-parity.v1',status:'passed',execution_provider:'deadbyte_mcp',rdc_operation_count:0,
14
- candidate:{release_id:`v0.11.0-${manifest.slice(0,16)}`,version:'0.11.0',manifest_sha256:manifest},
14
+ candidate:{release_id:`v0.11.1-${manifest.slice(0,16)}`,version:'0.11.1',manifest_sha256:manifest},
15
15
  immutable_slot:{protected:true,release_root:'C:/immutable/r37',development_root:'D:/Projects/deadbyte-mcp-r36-dev'},
16
16
  local_full:{status:'passed',tool_count:76,strict_output_schemas:true},
17
17
  public_compact:{status:'passed',tool_count:41,capability_closure:true,gateway_count:5},
18
18
  autonomous:{status:'passed',signed_release_verified:true,observed_failure_before_replan:true},
19
19
  before_rollback_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false},
20
20
  rollback:{state:'completed'},stage_restore:{status:'restored',manifest_sha256:manifest},restore:{state:'completed'},
21
- predecessor:{release_id:R36_PREDECESSOR_RELEASE_ID,version:'0.10.0',manifest_sha256:R36_PREDECESSOR_MANIFEST},
21
+ predecessor:{release_id:R37_PREDECESSOR_RELEASE_ID,version:'0.11.0',manifest_sha256:R37_PREDECESSOR_MANIFEST},
22
22
  predecessor_disarmed:{status:'passed',tool_count:41,capability_closure:true},
23
- successor:{release_id:`v0.11.0-${manifest.slice(0,16)}`,version:'0.11.0',manifest_sha256:manifest},
23
+ successor:{release_id:`v0.11.1-${manifest.slice(0,16)}`,version:'0.11.1',manifest_sha256:manifest},
24
24
  successor_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false},
25
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
26
  };
27
27
  }
28
28
 
29
- test('R37 parity validator requires full-76, compact closure, exact R36 predecessor and immutable-slot separation',()=>{
29
+ test('R37 parity validator requires full-76, compact closure, exact public 0.11.0 predecessor and immutable-slot separation',()=>{
30
30
  const good=parityFixture();
31
31
  assert.equal(validateParityEvidence(good),true);
32
32
  assert.throws(()=>validateParityEvidence({...good,local_full:{...good.local_full,tool_count:75}}),/full 76/i);
@@ -36,33 +36,33 @@ test('R37 parity validator requires full-76, compact closure, exact R36 predeces
36
36
  assert.throws(()=>validateParityEvidence({...good,stage_restore:{status:'missing',manifest_sha256:good.candidate.manifest_sha256}}),/stage restore/i);
37
37
  });
38
38
 
39
- test('R37 parity captures R37 bridge, exact R36 predecessor, stage reseed and successor restore',async()=>{
39
+ test('R37 parity captures R37 bridge, exact public 0.11.0 predecessor, stage reseed and successor restore',async()=>{
40
40
  const parity=await text('scripts/release-parity.mjs');
41
- assert.match(parity,/R36_PREDECESSOR_RELEASE_ID='v0\.10\.0-8d1e5f09745e7647'/);
42
- assert.match(parity,/8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8/);
41
+ assert.match(parity,/R37_PREDECESSOR_RELEASE_ID='v0\.11\.0-08c2a0008b1f84c9'/);
42
+ assert.match(parity,/08c2a0008b1f84c90f7ce7faa1e3decbd03f33612bc0fdc7d1ba591b548798e8/);
43
43
  assert.match(parity,/const stageRestore=await restoreFrozenStage/);
44
- assert.match(parity,/publicR36Disarmed/);
44
+ assert.match(parity,/publicR37Disarmed/);
45
45
  assert.match(parity,/scheduleDeferred\('activate',candidateManifest,\{bridgeRoot:successorBridge\.root,bridgeScriptSha256:successorBridge\.sha256\}\)/);
46
46
  });
47
47
 
48
- test('R37 current final closure writer and independent verifier bind R37 domains and R36 predecessor',async()=>{
48
+ test('R37 current final closure writer and independent verifier bind R37 domains and public 0.11.0 predecessor',async()=>{
49
49
  const [writer,verifier]=await Promise.all([text('scripts/final-closure.mjs'),text('scripts/final-closure-verify.mjs')]);
50
50
  assert.equal(typeof verifyFinalClosureObject,'function');
51
51
  assert.match(writer,/DEADBYTE-R37-FINAL-CLOSURE-V1/);
52
52
  assert.match(writer,/deadbyte\.r37-final-closure\.v1/);
53
- assert.match(writer,/pointer\.version==='0\.11\.0'/);
53
+ assert.match(writer,/pointer\.version==='0\.11\.1'/);
54
54
  assert.match(writer,/R37 FINAL MACHINE BASELINE/);
55
55
  assert.match(writer,/deadbyte\.r37-parity\.v1/);
56
56
  assert.match(writer,/deadbyte\.r37-windows-gate\.v1/);
57
- assert.match(writer,/R36_PREDECESSOR_RELEASE_ID/);
57
+ assert.match(writer,/R37_PREDECESSOR_RELEASE_ID/);
58
58
  assert.doesNotMatch(verifier,/from ['"]\.\.\/src\//);
59
59
  assert.match(verifier,/DEADBYTE-R37-FINAL-CLOSURE-V1/);
60
60
  assert.match(verifier,/deadbyte\.r37-final-closure\.v1/);
61
- assert.match(verifier,/envelope\.body\.version==='0\.11\.0'/);
61
+ assert.match(verifier,/envelope\.body\.version==='0\.11\.1'/);
62
62
  assert.match(verifier,/R37 FINAL MACHINE BASELINE/);
63
63
  assert.match(verifier,/deadbyte\.r37-parity\.v1/);
64
64
  assert.match(verifier,/deadbyte\.r37-windows-gate\.v1/);
65
- assert.match(verifier,/8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8/);
65
+ assert.match(verifier,/08c2a0008b1f84c90f7ce7faa1e3decbd03f33612bc0fdc7d1ba591b548798e8/);
66
66
  });
67
67
 
68
68
  test('R37 bounded public parity suite covers current release identity and agent fabric',async()=>{
@@ -0,0 +1,94 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { mkdtemp, readFile, rm } from 'node:fs/promises';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { createLiveTimelineTracker, formatRemoteToolCall } from '../src/remote-live-log.mjs';
7
+ import { openRemoteResultJournal } from '../src/remote-result-journal.mjs';
8
+
9
+ const H=c=>c.repeat(64);
10
+ const session='c'.repeat(24);
11
+
12
+ test('R37 unified timeline renders one sanitized tool-call line with ISO timestamp, padded tool name, and JSON arguments',()=>{
13
+ const event={
14
+ event_type:'tool.request',
15
+ request_id:'abcdef1234567890',
16
+ tool:'coding_file_write',
17
+ created_at_utc:'2026-09-18T16:24:30.125Z',
18
+ args:{
19
+ root_id:'projects',
20
+ path:'src/example.mjs',
21
+ content:'TOP_SECRET_PAYLOAD',
22
+ token:'TOP_SECRET_TOKEN',
23
+ nested:{authorization:'Bearer abc.def.ghi',safe:true}
24
+ }
25
+ };
26
+ const line=formatRemoteToolCall(event);
27
+ assert.match(line,/^2026-09-18T16:24:30\.125Z \| coding_file_write\s+\| Arguments: \{/);
28
+ assert.match(line,/"root_id":"projects"/);
29
+ assert.match(line,/"path":"src\/example\.mjs"/);
30
+ assert.match(line,/"reason":"payload"/);
31
+ assert.match(line,/"reason":"secret"/);
32
+ assert.doesNotMatch(line,/TOP_SECRET_PAYLOAD|TOP_SECRET_TOKEN|Bearer abc\.def\.ghi/);
33
+ });
34
+
35
+ test('R37 live tracker uses the tool-call line for request and keeps correlated terminal result',()=>{
36
+ let now=Date.parse('2026-09-18T16:24:30.125Z');
37
+ const tracker=createLiveTimelineTracker({clock:()=>now});
38
+ const call=tracker.observe({event_type:'tool.request',request_id:'abcdef1234567890',tool:'coding_tree',
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"\}$/);
41
+ now+=250;
42
+ assert.equal(tracker.observe({event_type:'tool.result',request_id:'abcdef1234567890',tool:'coding_tree',
43
+ outcome:{is_error:false,duration_ms:250}}),'✓ [abcdef12] OK coding_tree 250ms');
44
+ });
45
+
46
+ test('R37 remote result journal persists sanitized tool-call and result in one monotonic cursor stream',async()=>{
47
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r37-toolcall-journal-'));
48
+ const file=path.join(root,'journal.json');
49
+ try{
50
+ const journal=await openRemoteResultJournal({filePath:file,sessionId:session,maxEntries:16});
51
+ const call=await journal.recordCall({
52
+ request_id:'req-1',tool:'coding_file_write',observed_at_utc:'2026-09-18T16:24:30.125Z',
53
+ arguments:{root_id:'projects',path:'x.txt',content:'DO_NOT_STORE_PAYLOAD',token:'DO_NOT_STORE_TOKEN'},
54
+ payload_sha256:H('1')
55
+ });
56
+ const duplicate=await journal.recordCall({
57
+ request_id:'req-1',tool:'coding_file_write',observed_at_utc:'2026-09-18T16:24:30.125Z',
58
+ arguments:{root_id:'projects',path:'x.txt',content:'DO_NOT_STORE_PAYLOAD',token:'DO_NOT_STORE_TOKEN'},
59
+ payload_sha256:H('1')
60
+ });
61
+ const result=await journal.recordTerminal({
62
+ request_id:'req-1',tool:'coding_file_write',status:'ok',observed_at_utc:'2026-09-18T16:24:30.500Z',
63
+ payload_sha256:H('2')
64
+ });
65
+ assert.equal(call.event.seq,1);
66
+ assert.equal(call.event.event_type,'tool.call');
67
+ assert.equal(duplicate.duplicate,true);
68
+ assert.equal(result.event.seq,2);
69
+ assert.equal(result.event.event_type,'tool.result');
70
+ assert.equal(journal.cursor(),'r1:'+session+':2');
71
+ const replay=await journal.replayAfter('r1:'+session+':0',{limit:8});
72
+ assert.deepEqual(replay.events.map(e=>[e.seq,e.event_type]),[[1,'tool.call'],[2,'tool.result']]);
73
+ const disk=await readFile(file,'utf8');
74
+ assert.doesNotMatch(disk,/DO_NOT_STORE_PAYLOAD|DO_NOT_STORE_TOKEN/);
75
+ assert.match(disk,/"reason":"payload"/);
76
+ assert.match(disk,/"reason":"secret"/);
77
+ }finally{await rm(root,{recursive:true,force:true});}
78
+ });
79
+
80
+ test('R37 journal remains backward-compatible with pre-tool-call result-only events',async()=>{
81
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r37-old-result-journal-'));
82
+ const file=path.join(root,'journal.json');
83
+ try{
84
+ await import('node:fs/promises').then(({writeFile})=>writeFile(file,JSON.stringify({
85
+ schema:'deadbyte.remote-result-journal.v1',session_id:session,next_seq:2,
86
+ events:[{session_id:session,seq:1,request_id:'old-1',tool:'coding_tree',status:'ok',
87
+ observed_at_utc:'2026-09-17T00:00:00.000Z',payload_sha256:H('3')}]
88
+ })+'\n','utf8'));
89
+ const journal=await openRemoteResultJournal({filePath:file,sessionId:session,maxEntries:16});
90
+ const replay=await journal.replayAfter('r1:'+session+':0',{limit:8});
91
+ assert.equal(replay.events[0].event_type,'tool.result');
92
+ assert.equal(replay.events[0].status,'ok');
93
+ }finally{await rm(root,{recursive:true,force:true});}
94
+ });
@@ -5,10 +5,10 @@ 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 R36_RELEASE_ID='v0.10.0-8d1e5f09745e7647';
9
- const R36_MANIFEST='8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8';
8
+ const R37_PREDECESSOR_RELEASE_ID='v0.11.0-08c2a0008b1f84c9';
9
+ const R37_PREDECESSOR_MANIFEST='08c2a0008b1f84c90f7ce7faa1e3decbd03f33612bc0fdc7d1ba591b548798e8';
10
10
 
11
- test('R37 successor release authority agrees on V0.11.0 / R37 and preserves exact public R36 predecessor',async()=>{
11
+ test('R37 patch release authority agrees on V0.11.1 and preserves exact public 0.11.0 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
14
  text('src/version.mjs'),text('controller/deadbyte-controller.ps1'),text('scripts/gate-windows.ps1'),
@@ -17,35 +17,28 @@ test('R37 successor release authority agrees on V0.11.0 / R37 and preserves exac
17
17
  text('scripts/final-closure-verify.mjs'),text('scripts/windows-gate-evidence.mjs'),
18
18
  text('controller/deadbyte-semantic-lsp-config.json')
19
19
  ]);
20
- assert.equal(pkg.version,'0.11.0');
21
- assert.match(version,/DEADBYTE_VERSION = '0\.11\.0'/);
22
- assert.match(controller,/CONTROLLER V0\.11\.0 \/ R37/);
23
- assert.match(gate,/DEADBYTE V0\.11\.0 \/ R37 WINDOWS BATCH GATE: PASS/);
24
- assert.match(readme,/^DEADBYTE MCP V0\.11\.0 \/ R37 PRODUCTION BASELINE$/m);
25
- assert.match(architecture,/^# DEADBYTE MCP V0\.11\.0 \/ R37 ARCHITECTURE$/m);
26
- assert.match(controllerReadme,/^DEADBYTE MCP V0\.11\.0 \/ R37 CONTROLLER$/m);
27
- assert.match(controllerReadme,/full 76-tool (?:profile|catalog)/);
28
- assert.match(controllerReadme,/compact capability profile[^\n]*<=42 tools/);
29
- assert.match(deferred,/--expected-version','0\.11\.0'/);
30
- assert.match(parity,/deadbyte\.r37-parity\.v1/);
31
- assert.match(parity,/version==='0\.11\.0'|version:'0\.11\.0'/);
32
- assert.match(parity,new RegExp(R36_RELEASE_ID.replaceAll('.','\\.')));
33
- assert.match(parity,new RegExp(R36_MANIFEST));
34
- assert.match(closure,/DEADBYTE-R37-FINAL-CLOSURE-V1/);
35
- assert.match(closure,/version:'0\.11\.0'/);
36
- assert.match(closureVerify,/DEADBYTE V0\.11\.0 \/ R37 WINDOWS BATCH GATE: PASS/);
37
- assert.match(windowsGate,/schema:'deadbyte\.r37-windows-gate\.v1'/);
20
+ assert.equal(pkg.version,'0.11.1');
21
+ assert.match(version,/DEADBYTE_VERSION = '0\.11\.1'/);
22
+ assert.match(controller,/CONTROLLER V0\.11\.1 \/ R37/);
23
+ assert.match(gate,/DEADBYTE V0\.11\.1 \/ R37 WINDOWS BATCH GATE: PASS/);
24
+ assert.match(readme,/^DEADBYTE MCP V0\.11\.1 \/ R37 PRODUCTION BASELINE$/m);
25
+ assert.match(architecture,/^# DEADBYTE MCP V0\.11\.1 \/ R37 ARCHITECTURE$/m);
26
+ assert.match(controllerReadme,/^DEADBYTE MCP V0\.11\.1 \/ R37 CONTROLLER$/m);
27
+ assert.match(deferred,/--expected-version','0\.11\.1'/);
28
+ assert.match(parity,/R37_PREDECESSOR_RELEASE_ID='v0\.11\.0-08c2a0008b1f84c9'/);
29
+ assert.match(parity,new RegExp(R37_PREDECESSOR_MANIFEST));
30
+ assert.match(parity,/version==='0\.11\.1'|version:'0\.11\.1'/);
31
+ assert.match(closure,/version:'0\.11\.1'/);
32
+ assert.match(closureVerify,/DEADBYTE V0\.11\.1 \/ R37 WINDOWS BATCH GATE: PASS/);
33
+ assert.match(windowsGate,/version:'0\.11\.1'/);
38
34
  assert.equal(createHash('sha256').update(Buffer.from(semanticConfig,'utf8')).digest('hex'),'d274b099a298c1033fea8f1e8849751693bbc0448778d619400acb82d4f53a3b');
39
35
  });
40
36
 
41
- test('R37 keeps the R36 capability surface contract while adding internal agent fabric',async()=>{
42
- const [parity,fabric,live]=await Promise.all([
43
- text('src/remote-mcp-r36-parity-client.mjs'),
44
- text('src/autonomous-runtime.mjs'),
45
- text('src/remote-live-log.mjs')
46
- ]);
37
+ test('R37 patch keeps capability surface and fixes ONLINE remote startup without restoring verbose mode',async()=>{
38
+ const [parity,cli]=await Promise.all([text('src/remote-mcp-r36-parity-client.mjs'),text('src/deadbyte-cli.mjs')]);
47
39
  assert.match(parity,/R36_EXPECTED_TOOLS\.length !== 76/);
48
40
  assert.match(parity,/R36_COMPACT_TOOL_LIMIT=42/);
49
- for(const name of ['deriveAgentMemory','effectIdentity','createWorkerScheduler','issueObservationLease']) assert.match(fabric,new RegExp(name));
50
- assert.match(live,/createLiveTimelineTracker/);
41
+ assert.match(cli,/controllerRuntimeReady/);
42
+ assert.match(cli,/Runtime already ONLINE; reusing verified bridge\/cloud\/supervisor/);
43
+ assert.doesNotMatch(cli,/remote --verbose/);
51
44
  });
@@ -2,12 +2,15 @@ import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import { createLiveTimelineTracker } from '../src/remote-live-log.mjs';
4
4
 
5
- test('R37 live timeline correlates RUN and result with stable short span id',()=>{
5
+ test('R37 live timeline renders sanitized tool-call detail and correlates terminal result with stable short span id',()=>{
6
6
  let now=1000;
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.equal(run,'▶ [abcdef12] RUN coding_file_read root=projects path=src/a.mjs');
10
+ assert.match(run,/^1970-01-01T00:00:01\.000Z \| coding_file_read\s+\| Arguments: \{/);
11
+ assert.match(run,/\"path\":\"src\/a\.mjs\"/);
12
+ assert.match(run,/\"reason\":\"payload\"/);
13
+ assert.match(run,/\"reason\":\"secret\"/);
11
14
  now=1250;
12
15
  const done=tracker.observe({event_type:'tool.result',tool:'coding_file_read',request_id:'abcdef1234567890',
13
16
  outcome:{is_error:false,duration_ms:250}});
@@ -11,16 +11,16 @@ const cliPath=path.join(root,'src','deadbyte-cli.mjs');
11
11
  const isWindows=process.platform==='win32';
12
12
  const sleep=ms=>new Promise(resolve=>setTimeout(resolve,ms));
13
13
 
14
- async function fixture({failCommand=''}={}){
14
+ async function fixture({failCommand='',statusOnline=false}={}){
15
15
  const dir=await mkdtemp(path.join(os.tmpdir(),'deadbyte-remote-session-'));
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
19
  await mkdir(bin,{recursive:true});
20
20
  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 '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`;
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`;
22
22
  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}};
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'}};
24
24
  }
25
25
 
26
26
  async function traceCommands(file,{read=readFile,retryDelayMs=10,maxAttempts=20}={}){
@@ -65,15 +65,40 @@ async function collect(child){
65
65
 
66
66
  const winTest=isWindows?test:test.skip;
67
67
 
68
+ winTest('bare remote reuses a fully verified ONLINE runtime without invoking blocking start',async()=>{
69
+ const fx=await fixture({failCommand:'start',statusOnline:true});
70
+ let child=null;
71
+ try{
72
+ child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
73
+ const output=await collect(child);
74
+ const ready=await waitFor(fx.trace,commands=>commands.includes('hoststatus'),{timeoutMs:8000});
75
+ assert.deepEqual(ready.slice(0,8),[
76
+ 'status','armprocess','armcoding','armautonomous',
77
+ 'processstatus','codingstatus','autonomousstatus','hoststatus'
78
+ ]);
79
+ assert.doesNotMatch(ready.join(','),/(^|,)start(,|$)/);
80
+ assert.equal(child.exitCode,null,'remote session must remain foreground after reusing ONLINE runtime');
81
+ assert.match(output.stdout,/Runtime already ONLINE; reusing verified bridge\/cloud\/supervisor/);
82
+ const authDeadline=Date.now()+3000;
83
+ while(Date.now()<authDeadline&&!/🔐 \[AUTH\] ARMED: process, coding, autonomous \| host DISARMED/.test(output.stdout)) await sleep(50);
84
+ assert.match(output.stdout,/🔐 \[AUTH\] ARMED: process, coding, autonomous \| host DISARMED/);
85
+ child.kill('SIGINT');
86
+ await output.closed;
87
+ }finally{
88
+ if(child&&child.exitCode===null) child.kill('SIGKILL');
89
+ await rm(fx.dir,{recursive:true,force:true});
90
+ }
91
+ });
92
+
68
93
  winTest('bare remote uses one unified live timeline, keeps authority semantics, then disarms and parks when the foreground session ends',async()=>{
69
94
  const fx=await fixture();
70
95
  let child=null;
71
96
  try{
72
97
  child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
73
98
  const output=await collect(child);
74
- const ready=await waitFor(fx.trace,commands=>commands.slice(0,8).join(',')==='start,armprocess,armcoding,armautonomous,processstatus,codingstatus,autonomousstatus,hoststatus');
75
- assert.deepEqual(ready.slice(0,8),[
76
- 'start','armprocess','armcoding','armautonomous',
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',
77
102
  'processstatus','codingstatus','autonomousstatus','hoststatus'
78
103
  ]);
79
104
  assert.equal(child.exitCode,null,'remote session must remain foreground after becoming ready');
@@ -111,13 +136,14 @@ winTest('bare remote uses one unified live timeline, keeps authority semantics,
111
136
  ].join('\n')+'\n','utf8');
112
137
  const logDeadline=Date.now()+3000;
113
138
  while(Date.now()<logDeadline&&!/✗ \[fedcba98\] ERR coding_file_read 1\.73s/.test(output.stdout)) await sleep(50);
114
- assert.match(output.stdout,/▶ \[abcdef12\] RUN coding_tree root=projects path=src/);
115
- assert.match(output.stdout,/✓ \[abcdef12\] OK coding_tree 42ms \[cursor r1:[0-9a-f]{24}:1\]/);
116
- assert.match(output.stdout,/▶ \[fedcba98\] RUN coding_file_read root=projects path=src\/deadbyte-cli\.mjs/);
117
- assert.match(output.stdout,/✗ \[fedcba98\] ERR coding_file_read 1\.73s \[cursor r1:[0-9a-f]{24}:2\]/);
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);
140
+ 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);
142
+ assert.match(output.stdout,/✗ \[fedcba98\] ERR coding_file_read 1\.73s \[cursor r1:[0-9a-f]{24}:4\]/);
118
143
  assert.equal((output.stdout.match(/✓ \[abcdef12\] OK coding_tree 42ms/g)||[]).length,1,'duplicate terminal result must print once');
119
144
  const resultJournal=JSON.parse(await readFile(path.join(fx.state,'runtime','remote-results',`${marker.result_session_id}.json`),'utf8'));
120
- assert.deepEqual(resultJournal.events.map(event=>event.seq),[1,2]);
145
+ assert.deepEqual(resultJournal.events.map(event=>event.seq),[1,2,3,4]);
146
+ assert.deepEqual(resultJournal.events.map(event=>event.event_type),['tool.call','tool.result','tool.call','tool.result']);
121
147
  assert.equal(resultJournal.events[0].request_id,'abcdef1234567890');
122
148
  assert.ok(resultJournal.events.every(event=>/^[0-9a-f]{64}$/.test(event.payload_sha256)));
123
149
  assert.doesNotMatch(JSON.stringify(resultJournal),/TOOL IN|TOOL OUT|stdout_excerpt|stderr_excerpt/);
@@ -146,7 +172,7 @@ winTest('bare remote uses one unified live timeline, keeps authority semantics,
146
172
  }
147
173
  });
148
174
 
149
- winTest('remote --resume replays only terminal results after the cursor before starting a new live session',async()=>{
175
+ winTest('remote --resume replays sanitized tool-call and terminal result events after the cursor without duplicates or loss',async()=>{
150
176
  const fx=await fixture();
151
177
  let first=null,second=null;
152
178
  try{
@@ -157,14 +183,22 @@ winTest('remote --resume replays only terminal results after the cursor before s
157
183
  while(Date.now()<liveDeadline&&!/\[LOG\] Unified live timeline/.test(firstOutput.stdout)) await sleep(50);
158
184
  const auditDir=path.join(fx.state,'audit');await mkdir(auditDir,{recursive:true});
159
185
  const auditFile=path.join(auditDir,'segment-00000001.jsonl');
160
- await writeFile(auditFile,JSON.stringify({seq:1,event_type:'tool.result',tool:'coding_tree',request_id:'resume-request-1',outcome:{is_error:false}})+'\n','utf8');
186
+ const firstBatch=[
187
+ {seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'resume-request-1',created_at_utc:'2026-09-18T16:30:00.000Z',args:{root_id:'projects',path:'src'}},
188
+ {seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'resume-request-1',created_at_utc:'2026-09-18T16:30:00.100Z',outcome:{is_error:false}}
189
+ ];
190
+ await writeFile(auditFile,firstBatch.map(JSON.stringify).join('\n')+'\n','utf8');
161
191
  let deadline=Date.now()+3000;
162
- while(Date.now()<deadline&&!/coding_tree .*\[cursor r1:[0-9a-f]{24}:1\]/.test(firstOutput.stdout)) await sleep(50);
163
- const cursor1=firstOutput.stdout.match(/coding_tree .*\[cursor (r1:[0-9a-f]{24}:1)\]/)?.[1];
192
+ while(Date.now()<deadline&&!/coding_tree .*\[cursor r1:[0-9a-f]{24}:2\]/.test(firstOutput.stdout)) await sleep(50);
193
+ const cursor1=firstOutput.stdout.match(/coding_tree .*\[cursor (r1:[0-9a-f]{24}:2)\]/)?.[1];
164
194
  assert.ok(cursor1,'first result cursor missing');
165
- await writeFile(auditFile,JSON.stringify({seq:2,event_type:'tool.result',tool:'coding_file_read',request_id:'resume-request-2',outcome:{is_error:false}})+'\n',{encoding:'utf8',flag:'a'});
195
+ const secondBatch=[
196
+ {seq:3,event_type:'tool.request',tool:'coding_file_read',request_id:'resume-request-2',created_at_utc:'2026-09-18T16:30:01.000Z',args:{root_id:'projects',path:'src/deadbyte-cli.mjs',token:'DO_NOT_REPLAY_SECRET'}},
197
+ {seq:4,event_type:'tool.result',tool:'coding_file_read',request_id:'resume-request-2',created_at_utc:'2026-09-18T16:30:01.100Z',outcome:{is_error:false}}
198
+ ];
199
+ await writeFile(auditFile,secondBatch.map(JSON.stringify).join('\n')+'\n',{encoding:'utf8',flag:'a'});
166
200
  deadline=Date.now()+3000;
167
- while(Date.now()<deadline&&!/coding_file_read .*\[cursor r1:[0-9a-f]{24}:2\]/.test(firstOutput.stdout)) await sleep(50);
201
+ while(Date.now()<deadline&&!/coding_file_read .*\[cursor r1:[0-9a-f]{24}:4\]/.test(firstOutput.stdout)) await sleep(50);
168
202
  first.stdin.end();
169
203
  const firstEnded=await Promise.race([firstOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
170
204
  assert.equal(firstEnded.timeout,undefined);
@@ -172,14 +206,20 @@ winTest('remote --resume replays only terminal results after the cursor before s
172
206
  second=spawn(process.execPath,[cliPath,'remote','--resume',cursor1],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
173
207
  const secondOutput=await collect(second);
174
208
  deadline=Date.now()+5000;
175
- while(Date.now()<deadline&&(!/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/.test(secondOutput.stdout)||
209
+ while(Date.now()<deadline&&(!/coding_file_read\s+\| Arguments: .*REPLAY cursor r1:[0-9a-f]{24}:3/.test(secondOutput.stdout)||
210
+ !/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:4\]/.test(secondOutput.stdout)||
176
211
  !/\[LOG\] Unified live timeline/.test(secondOutput.stdout))) await sleep(50);
177
- assert.match(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/);
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);
213
+ assert.match(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:4\]/);
178
214
  assert.match(secondOutput.stdout,/♻️ \[SESSION\] Previous result stream replayed/);
215
+ assert.doesNotMatch(secondOutput.stdout,/DO_NOT_REPLAY_SECRET/);
179
216
  assert.doesNotMatch(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_tree/);
180
- const replayIndex=secondOutput.stdout.indexOf('[REPLAY]');
217
+ assert.equal((secondOutput.stdout.match(/\| coding_file_read\s+\| Arguments:/g)||[]).length,1,'tool-call replay duplicated');
218
+ assert.equal((secondOutput.stdout.match(/\[REPLAY\] \[OK\] coding_file_read/g)||[]).length,1,'terminal replay duplicated');
219
+ const callReplayIndex=secondOutput.stdout.indexOf('| coding_file_read');
220
+ const resultReplayIndex=secondOutput.stdout.indexOf('[REPLAY] [OK] coding_file_read');
181
221
  const liveIndex=secondOutput.stdout.indexOf('[LOG] Unified live timeline');
182
- assert.ok(replayIndex>=0&&liveIndex>replayIndex,'resume replay must happen before new live tail');
222
+ assert.ok(callReplayIndex>=0&&resultReplayIndex>callReplayIndex&&liveIndex>resultReplayIndex,'resume ordering must be call -> result -> live tail');
183
223
  second.stdin.end();
184
224
  const secondEnded=await Promise.race([secondOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
185
225
  assert.equal(secondEnded.timeout,undefined);
@@ -210,8 +250,8 @@ winTest('detached guardian revokes authority, parks, and removes the session mar
210
250
  child=spawn(process.execPath,[cliPath,'remote'],{env:fx.env,stdio:['pipe','pipe','pipe'],windowsHide:true});
211
251
  const output=await collect(child);
212
252
  const ready=await waitFor(fx.trace,commands=>commands.slice(0,8).join(',')==='start,armprocess,armcoding,armautonomous,processstatus,codingstatus,autonomousstatus,hoststatus');
213
- assert.deepEqual(ready.slice(0,8),[
214
- 'start','armprocess','armcoding','armautonomous',
253
+ assert.deepEqual(ready.slice(0,9),[
254
+ 'status','start','armprocess','armcoding','armautonomous',
215
255
  'processstatus','codingstatus','autonomousstatus','hoststatus'
216
256
  ]);
217
257
  const markerPath=path.join(fx.state,'runtime','remote-session.json');
@@ -254,7 +294,7 @@ winTest('bare remote rolls back authority and parks if one plane fails to arm',a
254
294
  assert.equal(ended.timeout,undefined,'failed startup did not terminate');
255
295
  assert.notEqual(ended.code,0);
256
296
  const commands=await traceCommands(fx.trace);
257
- assert.deepEqual(commands.slice(0,3),['start','armprocess','armcoding']);
297
+ assert.deepEqual(commands.slice(0,4),['status','start','armprocess','armcoding']);
258
298
  assert.deepEqual(commands.slice(-5),['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park']);
259
299
  assert.doesNotMatch(output.stdout,/Live logs/i);
260
300
  }finally{await rm(fx.dir,{recursive:true,force:true});}
@@ -271,7 +311,8 @@ winTest('bare remote recovers a stale crashed session before arming a new one',a
271
311
  const output=await collect(child);
272
312
  const ready=await waitFor(fx.trace,commands=>commands.includes('hoststatus'));
273
313
  assert.deepEqual(ready.slice(0,5),['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park']);
274
- assert.equal(ready[5],'start');
314
+ assert.equal(ready[5],'status');
315
+ assert.equal(ready[6],'start');
275
316
  assert.match(output.stdout,/♻️ \[RECOVERY\] Stale remote session pid=2147483000; revoking authority before restart\./);
276
317
  child.stdin.end();
277
318
  const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);