deadbyte-mcp 0.15.36 → 0.15.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/MANIFEST.SHA256 +55 -27
  2. package/PROVENANCE.json +114 -87
  3. package/README.txt +12 -12
  4. package/RELEASE.json +214 -187
  5. package/SBOM.cdx.json +10 -25
  6. package/TEST-MATRIX.json +297 -258
  7. package/bridge/package.json +1 -1
  8. package/bridge/src/bridge-health-r59.mjs +4 -3
  9. package/bridge/src/bridge.mjs +71 -14
  10. package/bridge/src/canonical-json-r60.mjs +13 -0
  11. package/bridge/src/reconnect-delay-r60.mjs +31 -0
  12. package/bridge/src/remote-call-claims-r60.mjs +157 -0
  13. package/bridge/src/remote-dispatch-r60.mjs +75 -0
  14. package/controller/deadbyte-controller.ps1 +6 -1
  15. package/controller/deadbyte-process-policy.json +4 -4
  16. package/docs/R59-PROVENANCE.json +87 -0
  17. package/docs/R59-RELEASE.json +187 -0
  18. package/docs/R59-SBOM.cdx.json +68 -0
  19. package/docs/R59-TEST-MATRIX.json +258 -0
  20. package/docs/R59-bridge-package.json +13 -0
  21. package/docs/R59-package-lock.json +184 -0
  22. package/docs/R59-package.json +106 -0
  23. package/docs/R59-version.mjs +6 -0
  24. package/docs/R60-TASK-CONTRACT.md +22 -0
  25. package/package.json +5 -3
  26. package/scripts/full-regression-r60.mjs +32 -0
  27. package/scripts/gate-windows-r60-prepublish.ps1 +74 -0
  28. package/src/capability-snapshot.mjs +6 -2
  29. package/src/deadbyte-cli.mjs +80 -34
  30. package/src/remote-authority.mjs +56 -0
  31. package/src/remote-enforcement-probe-r60.mjs +17 -0
  32. package/src/remote-live-log.mjs +19 -2
  33. package/src/remote-log-decode-r60.mjs +32 -0
  34. package/src/remote-mcp-machine-smoke-client.mjs +19 -1
  35. package/src/remote-session-guardian.mjs +20 -3
  36. package/src/tool-audit.mjs +5 -0
  37. package/src/version.mjs +1 -1
  38. package/test/r48-release-contract.test.mjs +1 -1
  39. package/test/r51-runtime-coherence.test.mjs +2 -2
  40. package/test/r58-cleanup-retention.test.mjs +9 -3
  41. package/test/r58-concurrent-recovery.test.mjs +9 -3
  42. package/test/r58-controller-live-local.test.mjs +22 -3
  43. package/test/r58-stale-owner.test.mjs +2 -2
  44. package/test/r59-release-contract.test.mjs +6 -6
  45. package/test/r60-authority-coherence.test.mjs +36 -0
  46. package/test/r60-authority-enforcement.test.mjs +28 -0
  47. package/test/r60-bridge-dispatch.test.mjs +119 -0
  48. package/test/r60-clock-discipline.test.mjs +15 -0
  49. package/test/r60-live-timeline.test.mjs +29 -0
  50. package/test/r60-reconnect-errors.test.mjs +21 -0
  51. package/test/r60-reconnect-jitter.test.mjs +18 -0
  52. package/test/r60-release-contract.test.mjs +81 -0
  53. package/test/r60-remote-call-recovery.test.mjs +170 -0
  54. package/test/r60-windows-log-decode.test.mjs +25 -0
  55. package/test/remote-live-log-r37.test.mjs +1 -1
  56. package/test/remote-session-cli.test.mjs +200 -43
@@ -1,6 +1,6 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import {mkdir,cp,readFile,writeFile} from 'node:fs/promises';
3
+ import {mkdir,cp,readFile,readdir,writeFile} from 'node:fs/promises';
4
4
  import {spawnSync} from 'node:child_process';
5
5
  import {createServer} from 'node:net';
6
6
  import {createHash,randomBytes,generateKeyPairSync} from 'node:crypto';
@@ -8,6 +8,7 @@ import path from 'node:path';
8
8
  import {makeDoctorCliFixture} from './helpers/r58-doctor-fixture.mjs';
9
9
  import {prepareBridgeSpec,windowsPowerShellEnvironment} from '../src/runtime-update.mjs';
10
10
  import {queryForegroundIdentity as queryForegroundProcessIdentity,foregroundIdentityMatches as sameForegroundProcessIdentity} from '../src/foreground-process-identity.mjs';
11
+ import {Client,StreamableHTTPClientTransport} from '@modelcontextprotocol/client';
11
12
 
12
13
  const sha=b=>createHash('sha256').update(b).digest('hex');
13
14
  const quote=s=>"'"+s.replaceAll("'","''")+"'";
@@ -31,7 +32,7 @@ test('R58 actual isolated controller/bridge/core reaches ONLINE and stops withou
31
32
  const bridgeScript=path.join(bridgeRoot,'src','bridge.mjs'),nodeHash=sha(await readFile(process.execPath));
32
33
  const preparedBridge=await prepareBridgeSpec({Bridge:{FilePath:process.execPath,FileSha256:nodeHash,Arguments:'src\\bridge.mjs',WorkingDirectory:bridgeRoot},Cloud:{}},{root:bridgeRoot,scriptSha256:sha(await readFile(bridgeScript))});
33
34
  const dependencies=preparedBridge.Bridge.Dependencies.map(dependency=>`@{Name=${quote(dependency.Name)};Path=${quote(dependency.Path)};Sha256='${dependency.Sha256}'}`);
34
- assert.deepEqual(preparedBridge.Bridge.Dependencies.map(x=>x.Name),['bridge-health-r59.mjs','node-http-adapter.mjs','public-tool-definitions.mjs','r40-governor.mjs']);
35
+ assert.deepEqual(preparedBridge.Bridge.Dependencies.map(x=>x.Name),['bridge-health-r59.mjs','canonical-json-r60.mjs','node-http-adapter.mjs','public-tool-definitions.mjs','r40-governor.mjs','reconnect-delay-r60.mjs','remote-call-claims-r60.mjs','remote-dispatch-r60.mjs']);
35
36
  const config=path.join(f.root,'controller-config.psd1'),runtime=path.join(f.state,'runtime');
36
37
  await writeFile(config,`@{ Schema='deadbyte.controller.v1'; CoreRoot=${quote(f.pkg)}; WorkspaceRoot=${quote(workspace)}; Bridge=@{FilePath=${quote(process.execPath)};FileSha256='${nodeHash}';Arguments='src\\bridge.mjs';WorkingDirectory=${quote(bridgeRoot)};ScriptPath=${quote(bridgeScript)};ScriptSha256='${sha(await readFile(bridgeScript))}';Dependencies=@(${dependencies.join(';')})}; Cloud=@{FilePath=${quote(process.execPath)};FileSha256='${nodeHash}';Arguments=${quote('"'+cloud+'"')};WorkingDirectory=${quote(f.root)};Dependencies=@(@{Name='fixture-cloud';Path=${quote(cloud)};Sha256='${sha(await readFile(cloud))}'})}; MachineRuntimeEnabled=$false;AgentRuntimeEnabled=$false;ProcessRuntimeEnabled=$false;ProcessPolicyFile='';CodingRuntimeEnabled=$false;CodingPolicyFile='';MachineFsRuntimeEnabled=$false;ObservationRuntimeEnabled=$false;DesktopRuntimeEnabled=$false;DesktopPolicyFile='';AutonomousRuntimeEnabled=$false;AutonomousSupervisorEnabled=$false;AutonomousPolicyFile='';HostPolicyFile='';LocalReadyUri='http://127.0.0.1:${port}/healthz';UrlRegex='';McpUrlFile=${quote(url)};McpPathFile='';StartTimeoutSeconds=15;ProbeTimeoutSeconds=1 }`);
37
38
  // Controller's existing audit mode requires machine runtime. It is observation
@@ -61,7 +62,8 @@ test('R58 actual isolated controller/bridge/core reaches ONLINE and stops withou
61
62
  launcher_sha256:'0'.repeat(64),
62
63
  config_path:generationConfig
63
64
  },null,2)+'\n');
64
- const env=windowsPowerShellEnvironment({...f.env,DEADBYTE_CONTROLLER_CONFIG:config,DEADBYTE_CONTROLLER_RUNTIME_ROOT:runtime,DEADBYTE_BRIDGE_PORT:String(port),DEADBYTE_BRIDGE_PATH_TOKEN:randomBytes(32).toString('hex')});
65
+ const bridgeToken=randomBytes(32).toString('hex');
66
+ const env=windowsPowerShellEnvironment({...f.env,DEADBYTE_CONTROLLER_CONFIG:config,DEADBYTE_CONTROLLER_RUNTIME_ROOT:runtime,DEADBYTE_BRIDGE_PORT:String(port),DEADBYTE_BRIDGE_PATH_TOKEN:bridgeToken});
65
67
  const run=(command,json=false)=>spawnSync(path.join(process.env.SystemRoot,'System32/WindowsPowerShell/v1.0/powershell.exe'),['-NoProfile','-File',controller,command,...(json?['-Json']:[])],{env,encoding:'utf8',timeout:45000});
66
68
  let coreIdentity=null;
67
69
  try{
@@ -70,6 +72,17 @@ test('R58 actual isolated controller/bridge/core reaches ONLINE and stops withou
70
72
  const status=run('status',true);assert.equal(status.status,0,status.stderr);const observed=JSON.parse(status.stdout);
71
73
  assert.equal(observed.state,'ONLINE');assert.equal(observed.local_ready,true);assert.equal(observed.core.alive,true);assert.equal(observed.core.parent_pid,observed.bridge.pid);
72
74
  for(const plane of Object.values(observed.authority))assert.equal(plane.armed,false);
75
+ const publicClient=new Client({name:'r60-isolated-ingress',version:'0.15.37'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
76
+ try{
77
+ await publicClient.connect(new StreamableHTTPClientTransport(new URL(`http://127.0.0.1:${port}/mcp/${bridgeToken}`)));
78
+ const publicStatus=await publicClient.callTool({name:'machine_status',arguments:{}});
79
+ assert.equal(publicStatus.structuredContent?.status,'ok','actual Bridge ingress must execute through the guarded dispatch');
80
+ const claimRoot=path.join(f.state,'runtime','remote-call-claims');
81
+ const shards=await readdir(claimRoot);
82
+ assert.equal(shards.length,1,'public ingress must create a durable claim');
83
+ const records=await readdir(path.join(claimRoot,shards[0]));
84
+ assert.equal(records.filter(name=>name.endsWith('.terminal.json')).length,1,'Core result must publish a terminal record');
85
+ }finally{await publicClient.close().catch(()=>{});}
73
86
  const firstCore=await queryForegroundProcessIdentity(observed.core.pid);assert.ok(firstCore);
74
87
  process.kill(firstCore.pid);
75
88
  let recovered=null;
@@ -83,6 +96,12 @@ test('R58 actual isolated controller/bridge/core reaches ONLINE and stops withou
83
96
  }
84
97
  assert.ok(recovered,'bridge did not recover a fresh Core within bounded restart budget');
85
98
  assert.equal(recovered.core.parent_pid,recovered.bridge.pid);
99
+ const reattached=new Client({name:'r60-recovered-execution',version:'0.15.37'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
100
+ try{
101
+ await reattached.connect(new StreamableHTTPClientTransport(new URL(`http://127.0.0.1:${port}/mcp/${bridgeToken}`)));
102
+ const proof=await reattached.callTool({name:'machine_status',arguments:{}});
103
+ assert.equal(proof.structuredContent?.status,'ok','recovered Core must execute a bounded MCP call');
104
+ }finally{await reattached.close().catch(()=>{});}
86
105
  coreIdentity=await queryForegroundProcessIdentity(recovered.core.pid);assert.ok(coreIdentity);
87
106
  const stopped=run('stop');assert.equal(stopped.status,0,stopped.stderr);
88
107
  const terminal=run('status',true);assert.equal(terminal.status,0,terminal.stderr);const end=JSON.parse(terminal.stdout);
@@ -51,7 +51,7 @@ test('R58 bound stale birth identity reconciles on the first invocation without
51
51
  await mkdir(base,{recursive:true});const root=await mkdtemp(path.join(base,'stale-birth-'));
52
52
  await mkdir(path.join(root,'runtime'));await mkdir(path.join(root,'bin'));
53
53
  const trace=path.join(root,'trace.txt');
54
- await writeFile(path.join(root,'bin','DEADBYTE-MCP.ps1'),`param([string]$Command)\n[IO.File]::AppendAllText('${trace.replaceAll("'","''")}',$Command+[Environment]::NewLine)\nexit 0\n`);
54
+ await writeFile(path.join(root,'bin','DEADBYTE-MCP.ps1'),`param([string]$Command,[switch]$Json)\n[IO.File]::AppendAllText('${trace.replaceAll("'","''")}',$Command+[Environment]::NewLine)\nif ($Command -eq 'status' -and $Json) { $off=@{configured=$true;armed=$false;reason='disarmed'}; @{schema='deadbyte.controller-observation.v1';state='OFFLINE';authority=@{process=$off;coding=$off;autonomous=$off;desktop=$off;host=$off}} | ConvertTo-Json -Depth 5 -Compress }\nexit 0\n`);
55
55
  const current=queryForegroundIdentity(process.pid);
56
56
  const stale={...current,creation_utc:'2000-01-01T00:00:00.000Z'};
57
57
  const marker={schema:'deadbyte.remote-session.v2',owner_pid:process.pid,guardian_pid:process.pid,session_nonce:'b'.repeat(64),owner_identity:stale,guardian_identity:stale};
@@ -63,7 +63,7 @@ test('R58 bound stale birth identity reconciles on the first invocation without
63
63
  await writeFile(path.join(root,'observation.json'),JSON.stringify({code,stdout,stderr,simulation:'birth identity drift at a live unrelated numeric PID'}),{flag:'wx'});
64
64
  assert.match(stdout,/Stale remote session/);
65
65
  assert.doesNotMatch(stderr,/already active|ownership unverified/);
66
- assert.deepEqual((await readFile(trace,'utf8')).trim().split(/\r?\n/).slice(0,6),['disarmautonomous','disarmcoding','disarmprocess','disarmdesktop','disarmhost','park']);
66
+ assert.deepEqual((await readFile(trace,'utf8')).trim().split(/\r?\n/).slice(0,7),['disarmautonomous','disarmcoding','disarmprocess','disarmdesktop','disarmhost','status','park']);
67
67
  assert.match(stderr,/without a verified ONLINE runtime/,'fixture deliberately has no real runtime; recovery must already have converged');
68
68
  await assert.rejects(readFile(markerPath),{code:'ENOENT'});
69
69
  assert.equal(foregroundAlive(),true,'unrelated live process must not be killed');
@@ -3,7 +3,7 @@ import assert from 'node:assert/strict';
3
3
  import {readFile} from 'node:fs/promises';
4
4
 
5
5
  const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
6
- const json=rel=>read(rel).then(JSON.parse);
6
+ const json=rel=>read(rel).then(raw=>JSON.parse(raw.replace(/^\uFEFF/,'')));
7
7
 
8
8
  const PARENT={
9
9
  version:'0.15.35',
@@ -15,8 +15,8 @@ const PARENT={
15
15
 
16
16
  test('R59 identity is coherent and binds exact accepted 0.15.35 predecessor',async()=>{
17
17
  const [pkg,lock,release,prov,matrix,sbom,version,bridgePkg]=await Promise.all([
18
- json('package.json'),json('package-lock.json'),json('RELEASE.json'),json('PROVENANCE.json'),
19
- json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),json('bridge/package.json')
18
+ json('docs/R59-package.json'),json('docs/R59-package-lock.json'),json('docs/R59-RELEASE.json'),json('docs/R59-PROVENANCE.json'),
19
+ json('docs/R59-TEST-MATRIX.json'),json('docs/R59-SBOM.cdx.json'),read('docs/R59-version.mjs'),json('docs/R59-bridge-package.json')
20
20
  ]);
21
21
  assert.equal(pkg.version,'0.15.36');
22
22
  assert.equal(lock.version,pkg.version);
@@ -40,7 +40,7 @@ test('R59 identity is coherent and binds exact accepted 0.15.35 predecessor',asy
40
40
  });
41
41
 
42
42
  test('R59 release records runtime hardening without expanding public authority',async()=>{
43
- const [release,prov,matrix]=await Promise.all([json('RELEASE.json'),json('PROVENANCE.json'),json('TEST-MATRIX.json')]);
43
+ const [release,prov,matrix]=await Promise.all([json('docs/R59-RELEASE.json'),json('docs/R59-PROVENANCE.json'),json('docs/R59-TEST-MATRIX.json')]);
44
44
  assert.equal(release.r59_runtime_hardening.optional_plane_degradation,true);
45
45
  assert.equal(release.r59_runtime_hardening.capability_manifest_v3,true);
46
46
  assert.equal(release.r59_runtime_hardening.live_overlay_authority_ceiling,true);
@@ -53,8 +53,8 @@ test('R59 release records runtime hardening without expanding public authority',
53
53
  assert.equal(matrix.observed_pre_release_evidence.r59_contracts.tests,19);
54
54
  assert.equal(matrix.observed_pre_release_evidence.r59_public_surface.status,'PASS');
55
55
  assert.equal(matrix.observed_pre_release_evidence.r59_public_surface.tool_count,43);
56
- assert.equal(prov.operator_override.four_hour_soak,'NOT_COMPLETED');
57
- assert.equal(prov.operator_override.clean_machine,'NOT_COMPLETED');
56
+ assert.equal(prov.operator_override.four_hour_soak,'WAIVED_BY_OPERATOR');
57
+ assert.equal(prov.operator_override.clean_machine,'WAIVED_BY_OPERATOR');
58
58
  assert.equal(prov.operator_override.stable_final_claim,false);
59
59
  assert.equal(matrix.operator_override.stable_final_claim,false);
60
60
  assert.equal(release.stabilization.stable_final_claim,false);
@@ -0,0 +1,36 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { authorityVector, parseAuthorityObservation, assertAuthorityVector, assertRuntimeReadyObservation } from '../src/remote-authority.mjs';
4
+
5
+ const observed = (armed={}) => ({
6
+ schema:'deadbyte.controller-observation.v1',
7
+ authority:Object.fromEntries(['process','coding','autonomous','desktop','host'].map(name=>[
8
+ name,{configured:true,armed:Boolean(armed[name]),reason:armed[name]?'standing-grant':'disarmed'}
9
+ ]))
10
+ });
11
+
12
+ test('remote modes have exact non-widening authority vectors',()=>{
13
+ assert.deepEqual(authorityVector('default'),{process:true,coding:true,autonomous:true,desktop:false,host:false});
14
+ assert.deepEqual(authorityVector('desktop'),{process:true,coding:true,autonomous:true,desktop:true,host:false});
15
+ assert.deepEqual(authorityVector('host'),{process:true,coding:true,autonomous:true,desktop:false,host:true});
16
+ assert.deepEqual(authorityVector('full'),{process:true,coding:true,autonomous:true,desktop:true,host:true});
17
+ });
18
+
19
+ test('observed standing Host grant rejects bounded READY',()=>{
20
+ const snapshot=parseAuthorityObservation(JSON.stringify(observed({process:true,coding:true,autonomous:true,host:true})));
21
+ assert.throws(()=>assertAuthorityVector(snapshot,authorityVector('default')),/host.*expected DISARMED/);
22
+ });
23
+
24
+ test('malformed or incomplete controller observation fails closed',()=>{
25
+ assert.throws(()=>parseAuthorityObservation('{}'),/observation/);
26
+ assert.throws(()=>parseAuthorityObservation(JSON.stringify({schema:'deadbyte.controller-observation.v1',authority:{process:{armed:true}}})),/authority/);
27
+ });
28
+
29
+ test('readiness requires verified Bridge Core Cloud and local MCP, not just ONLINE text',()=>{
30
+ const value={...observed({process:true,coding:true,autonomous:true}),state:'ONLINE',local_ready:true,
31
+ bridge:{alive:true,reason:'verified'},core:{alive:true,reason:'verified'},cloud:{alive:true,reason:'verified'},
32
+ supervisor:{running:true},core_root:'D:\\exact-release'};
33
+ assertRuntimeReadyObservation(value,{coreRoot:'D:\\exact-release'});
34
+ assert.throws(()=>assertRuntimeReadyObservation({...value,core:{alive:false,reason:'wrong-core-generation'}}),/core/);
35
+ assert.throws(()=>assertRuntimeReadyObservation({...value,core_root:'D:\\wrong'} ,{coreRoot:'D:\\exact-release'}),/core root/);
36
+ });
@@ -0,0 +1,28 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { probeRemoteEnforcement } from '../src/remote-enforcement-probe-r60.mjs';
4
+
5
+ function client({hostArmed=false,desktopArmed=false}={}){
6
+ return {callTool:async ({name})=>name==='desktop_control'
7
+ ? {isError:false,structuredContent:{status:'ok',op:'status',result:{armed:desktopArmed}}}
8
+ : hostArmed
9
+ ? {isError:false,structuredContent:{status:'ok',content:'{}',sha256:'a'.repeat(64)}}
10
+ : {isError:true,structuredContent:{status:'denied'}}};
11
+ }
12
+
13
+ test('default remote verifies Host denial and Desktop disarm through actual MCP tools',async()=>{
14
+ await probeRemoteEnforcement({client:client(),mode:'default'});
15
+ await assert.rejects(probeRemoteEnforcement({client:client({hostArmed:true}),mode:'default'}),/Host.*enforcement/);
16
+ await assert.rejects(probeRemoteEnforcement({client:client({desktopArmed:true}),mode:'default'}),/Desktop.*enforcement/);
17
+ });
18
+
19
+ test('full remote requires both Host read and Desktop armed state',async()=>{
20
+ await probeRemoteEnforcement({client:client({hostArmed:true,desktopArmed:true}),mode:'full'});
21
+ await assert.rejects(probeRemoteEnforcement({client:client({hostArmed:false,desktopArmed:true}),mode:'full'}),/Host.*enforcement/);
22
+ });
23
+
24
+ test('post-session revoked probe independently rejects lingering Host and Desktop grants',async()=>{
25
+ await probeRemoteEnforcement({client:client(),mode:'revoked'});
26
+ await assert.rejects(probeRemoteEnforcement({client:client({hostArmed:true}),mode:'revoked'}),/Host.*enforcement/);
27
+ await assert.rejects(probeRemoteEnforcement({client:client({desktopArmed:true}),mode:'revoked'}),/Desktop.*enforcement/);
28
+ });
@@ -0,0 +1,119 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {mkdtemp,rm} from 'node:fs/promises';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import {openRemoteCallClaims} from '../bridge/src/remote-call-claims-r60.mjs';
7
+ import {dispatchBridgeCall,classifyRemoteOperation} from '../bridge/src/remote-dispatch-r60.mjs';
8
+ import {createCapabilitySnapshotTracker} from '../src/capability-snapshot.mjs';
9
+
10
+ const base={device_id:'device-1',session_id:'stateless',request_id:'call-1',tool:'coding_file_write',
11
+ arguments:{root_id:'fixture',path:'a.txt',content:'A'},expires_at_utc:'2030-01-01T00:00:00.000Z',
12
+ release_id:'v0.15.37-test',generation_manifest_sha256:'a'.repeat(64),machine_id:'d'.repeat(64),online_epoch:'c'.repeat(64),classification:'mutating'};
13
+
14
+ async function fixture(run){
15
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r60-bridge-dispatch-'));
16
+ try{await run(openRemoteCallClaims({root,clock:()=>Date.parse('2029-01-01T00:00:00.000Z')}));}
17
+ finally{await rm(root,{recursive:true,force:true});}
18
+ }
19
+
20
+ test('remote operation classifier marks only pinned read-only forms safe for recovery',()=>{
21
+ assert.equal(classifyRemoteOperation({name:'machine_status'},{}),'read_only');
22
+ assert.equal(classifyRemoteOperation({name:'machine_fs'},{op:'read',root_id:'fixture',path:'a.txt'}),'read_only');
23
+ assert.equal(classifyRemoteOperation({name:'machine_fs'},{op:'write',root_id:'fixture',path:'a.txt'}),'mutating');
24
+ assert.equal(classifyRemoteOperation({name:'coding_file_write'},{}),'mutating');
25
+ assert.equal(classifyRemoteOperation({name:'unknown_future_tool'},{}),'unknown');
26
+ });
27
+
28
+ test('capability snapshot describes the Bridge idempotency boundary without adding signed capabilities',()=>{
29
+ const snapshot=createCapabilitySnapshotTracker({clock:()=>1000}).snapshot({profile:'compact',
30
+ ledger:{ledger_sha256:'a'.repeat(64),entries:[]},toolCatalog:['capability_manifest'],catalogSha256:'b'.repeat(64),
31
+ resolution:{capabilities:[]},bindings:{},planes:{}});
32
+ assert.equal(snapshot.remote_dispatch_contract.scope,'bridge_ingress_only');
33
+ assert.equal(snapshot.remote_dispatch_contract.keyed_mutation,'same stable key and canonical payload: no duplicate dispatch; unknown post-dispatch outcome is not retried');
34
+ assert.equal(snapshot.remote_dispatch_contract.keyless_mutation,'cross-reconnect logical retry safety unavailable; ambiguous outcome is not auto-replayed');
35
+ assert.deepEqual(snapshot.capabilities,[]);
36
+ });
37
+
38
+ test('Bridge keyed mutation duplicate executes the downstream side effect once and replays result',async()=>fixture(async claims=>{
39
+ let effects=0;
40
+ const binding={...base,idempotency_key:'stable-write-1'};
41
+ const invoke=async()=>{effects++;return {structuredContent:{status:'ok',receipt_sha256:'b'.repeat(64)}};};
42
+ const first=await dispatchBridgeCall({claims,binding,classification:'mutating',invoke});
43
+ const duplicate=await dispatchBridgeCall({claims,binding:{...binding,session_id:'new-session',request_id:'call-99'},classification:'mutating',invoke});
44
+ assert.deepEqual(duplicate,first);
45
+ assert.equal(effects,1);
46
+ await assert.rejects(dispatchBridgeCall({claims,binding:{...binding,arguments:{...binding.arguments,content:'B'}},classification:'mutating',invoke}),/idempotency_key_conflict/);
47
+ assert.equal(effects,1);
48
+ }));
49
+
50
+ test('Bridge keyless exact duplicate does not replay and uncertain post-dispatch mutation stays unknown',async()=>fixture(async claims=>{
51
+ let effects=0;
52
+ const first=await dispatchBridgeCall({claims,binding:base,classification:'mutating',invoke:async()=>{effects++;throw new Error('transport lost');}}).catch(error=>error);
53
+ assert.match(first.message,/unknown/i);
54
+ const second=await dispatchBridgeCall({claims,binding:base,classification:'mutating',invoke:async()=>{effects++;}}).catch(error=>error);
55
+ assert.match(second.message,/unknown/i);
56
+ assert.equal(effects,1);
57
+ }));
58
+
59
+ test('keyless JSON-RPC ids do not become cross-delivery mutation identities',async()=>fixture(async claims=>{
60
+ let effects=0;
61
+ const invoke=async()=>({structuredContent:{status:'ok',effect_number:++effects}});
62
+ const first=await dispatchBridgeCall({claims,binding:{...base,session_id:'delivery-a'},classification:'mutating',invoke});
63
+ const second=await dispatchBridgeCall({claims,binding:{...base,session_id:'delivery-b'},classification:'mutating',invoke});
64
+ assert.equal(first.structuredContent.effect_number,1);
65
+ assert.equal(second.structuredContent.effect_number,2);
66
+ assert.equal(effects,2,'legacy calls do not acquire exactly-once semantics from a reused JSON-RPC id');
67
+ }));
68
+
69
+ test('concurrent Bridge deliveries race one durable dispatch marker and one side effect',async()=>fixture(async claims=>{
70
+ let effects=0;
71
+ const binding={...base,idempotency_key:'concurrent-write-1'};
72
+ const outcomes=await Promise.allSettled(Array.from({length:12},()=>dispatchBridgeCall({claims,binding,classification:'mutating',invoke:async()=>{
73
+ effects++;
74
+ return {structuredContent:{status:'ok',receipt_sha256:'b'.repeat(64)}};
75
+ }})));
76
+ assert.equal(effects,1);
77
+ assert.ok(outcomes.some(item=>item.status==='fulfilled'));
78
+ assert.ok(outcomes.every(item=>item.status==='fulfilled'||/in flight|unknown|no replay/i.test(item.reason.message)));
79
+ }));
80
+
81
+ test('two Bridge claim-store instances sharing one root still allow only one keyed side effect',async()=>{
82
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r60-two-bridges-'));
83
+ try{
84
+ const one=openRemoteCallClaims({root,clock:()=>Date.parse('2029-01-01T00:00:00.000Z')});
85
+ const two=openRemoteCallClaims({root,clock:()=>Date.parse('2029-01-01T00:00:00.000Z')});
86
+ const binding={...base,idempotency_key:'two-bridge-race'};
87
+ let effects=0;
88
+ const invoke=async()=>{effects++;return {structuredContent:{status:'ok'}};};
89
+ const outcomes=await Promise.allSettled([
90
+ dispatchBridgeCall({claims:one,binding,classification:'mutating',invoke}),
91
+ dispatchBridgeCall({claims:two,binding:{...binding,session_id:'second',request_id:'second'},classification:'mutating',invoke})
92
+ ]);
93
+ assert.equal(effects,1);
94
+ assert.ok(outcomes.some(item=>item.status==='fulfilled'));
95
+ assert.ok(outcomes.every(item=>item.status==='fulfilled'||/in flight|unknown|no replay/i.test(item.reason.message)));
96
+ }finally{await rm(root,{recursive:true,force:true});}
97
+ });
98
+
99
+ test('a keyed result is replayable after the reply is lost, without invoking Core again',async()=>fixture(async claims=>{
100
+ const binding={...base,idempotency_key:'lost-reply'};
101
+ let effects=0;
102
+ await dispatchBridgeCall({claims,binding,classification:'mutating',invoke:async()=>({structuredContent:{status:'ok',ordinal:++effects}})});
103
+ const replay=await dispatchBridgeCall({claims,binding:{...binding,session_id:'reattached',request_id:'new-rpc-id'},classification:'mutating',
104
+ invoke:async()=>{throw new Error('must not reach Core');}});
105
+ assert.equal(replay.structuredContent.ordinal,1);
106
+ assert.equal(effects,1);
107
+ }));
108
+
109
+ test('read-only post-crash claim can re-execute after recovery without mutating retry',async()=>fixture(async claims=>{
110
+ const binding={...base,tool:'machine_status',classification:'read_only',arguments:{},idempotency_key:'read-status-1'};
111
+ const first=await claims.claim(binding);
112
+ await claims.dispatch(first.claim_id);
113
+ await claims.recover({limit:100});
114
+ let calls=0;
115
+ const result=await dispatchBridgeCall({claims,binding,classification:'read_only',invoke:async()=>{calls++;return {structuredContent:{status:'ok'}};}});
116
+ assert.equal(result.structuredContent.status,'ok');
117
+ assert.equal(calls,1);
118
+ assert.equal((await claims.state(first.claim_id)).state,'TERMINAL');
119
+ }));
@@ -0,0 +1,15 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { createBridgeHealth } from '../bridge/src/bridge-health-r59.mjs';
4
+
5
+ test('backward wall-clock jump cannot extend capability freshness',()=>{
6
+ let wall=100000,elapsed=0;
7
+ const health=createBridgeHealth({clock:()=>wall,elapsedClock:()=>elapsed,maxCapabilityAgeMs:15000});
8
+ health.coreConnected({childIdentity:'core',protocolEra:'modern',catalogSha256:'a'.repeat(64)});
9
+ health.capabilityObserved({schema:'deadbyte.capability-manifest.v3',snapshot_id:'b'.repeat(64),state_epoch:1,
10
+ observed_at_utc:new Date(wall).toISOString(),valid_until_utc:new Date(wall+60000).toISOString(),planes:{}});
11
+ assert.equal(health.snapshot().state,'READY');
12
+ wall-=60000;
13
+ elapsed+=16000;
14
+ assert.equal(health.snapshot().state,'DEGRADED');
15
+ });
@@ -0,0 +1,29 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { createLiveTimelineTracker } from '../src/remote-live-log.mjs';
4
+
5
+ test('capability polling prints initial/changed identity and suppresses only unchanged observations',()=>{
6
+ let now=1000;
7
+ const tracker=createLiveTimelineTracker({clock:()=>now,heartbeatBurstLimit:3,heartbeatWindowMs:3000});
8
+ const lines=[];
9
+ for(let i=0;i<3;i++){
10
+ const request_id=`cap-${i}`;
11
+ lines.push(tracker.observe({event_type:'tool.request',tool:'capability_manifest',request_id,args:{}},{sequence:i*2+1}));
12
+ now+=10;
13
+ lines.push(tracker.observe({event_type:'tool.result',tool:'capability_manifest',request_id,outcome:{is_error:false,duration_ms:2,
14
+ snapshot_id:i===2?'b'.repeat(64):'a'.repeat(64),state_epoch:i===2?2:1}},{sequence:i*2+2}));
15
+ }
16
+ assert.match(lines[1],/capability_manifest.*epoch=1/);
17
+ assert.equal(lines[3],null);
18
+ assert.match(lines[5],/capability_manifest.*epoch=2/);
19
+ assert.match(tracker.reconcileInterrupted().join('\n'),/capability_manifest ×1 unchanged suppressed/);
20
+ assert.match(tracker.summary(),/3 calls \| 3 ok/);
21
+ });
22
+
23
+ test('machine status and ping remain visible in R60 human timeline',()=>{
24
+ const tracker=createLiveTimelineTracker({clock:()=>1000});
25
+ for(const tool of ['machine_status','machine_ping']){
26
+ tracker.observe({event_type:'tool.request',tool,request_id:tool,args:{}},{});
27
+ assert.match(tracker.observe({event_type:'tool.result',tool,request_id:tool,outcome:{is_error:false,duration_ms:1}},{}),new RegExp(tool));
28
+ }
29
+ });
@@ -0,0 +1,21 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { classifyReconnectFailure } from '../bridge/src/reconnect-delay-r60.mjs';
4
+
5
+ test('identity, catalog and protocol drift terminate reconnect budget immediately',()=>{
6
+ for(const message of ['core script identity drift','replacement core catalog drift','replacement core protocol is not modern'])
7
+ assert.equal(classifyReconnectFailure(new Error(message)),'TERMINAL');
8
+ assert.equal(classifyReconnectFailure(Object.assign(new Error('connection reset'),{code:'ECONNRESET'})),'TRANSIENT');
9
+ assert.equal(classifyReconnectFailure(Object.assign(new Error('permission denied'),{code:'EACCES'})),'TERMINAL');
10
+ });
11
+
12
+ test('typed terminal and transient failures are not inferred from incidental message text',()=>{
13
+ assert.equal(classifyReconnectFailure(Object.assign(new Error('connection reset'),{kind:'terminal',code:'DEADBYTE_GENERATION_MISMATCH'})),'TERMINAL');
14
+ assert.equal(classifyReconnectFailure(Object.assign(new Error('generation mismatch'),{kind:'transient',code:'ECONNRESET'})),'TRANSIENT');
15
+ for(const code of ['DEADBYTE_AUTHORITY_REVOKED','DEADBYTE_POLICY_DENIED','DEADBYTE_SCHEMA_INVALID',
16
+ 'DEADBYTE_RELEASE_MISMATCH','DEADBYTE_GENERATION_MISMATCH','DEADBYTE_IDEMPOTENCY_CONFLICT',
17
+ 'DEADBYTE_CLAIM_CORRUPT','DEADBYTE_CREDENTIAL_EXPIRED'])
18
+ assert.equal(classifyReconnectFailure(Object.assign(new Error('arbitrary'),{code})),'TERMINAL');
19
+ for(const code of ['ECONNRESET','ECONNREFUSED','EPIPE','ETIMEDOUT','EHOSTUNREACH'])
20
+ assert.equal(classifyReconnectFailure(Object.assign(new Error('arbitrary'),{code})),'TRANSIENT');
21
+ });
@@ -0,0 +1,18 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { reconnectDelayMs, waitForReconnect } from '../bridge/src/reconnect-delay-r60.mjs';
4
+
5
+ test('bounded reconnect delays jitter each attempt without exceeding the restart budget',()=>{
6
+ const low=[0,1,2,3,4].map(index=>reconnectDelayMs(index,()=>0));
7
+ const high=[0,1,2,3,4].map(index=>reconnectDelayMs(index,()=>1));
8
+ assert.deepEqual(low,[188,375,750,1500,3000]);
9
+ assert.deepEqual(high,[313,625,1250,2500,5000]);
10
+ assert.throws(()=>reconnectDelayMs(5),/attempt/);
11
+ });
12
+
13
+ test('shutdown aborts a scheduled reconnect before another child can start',async()=>{
14
+ const controller=new AbortController();
15
+ const pending=waitForReconnect(5000,controller.signal);
16
+ controller.abort();
17
+ assert.equal(await pending,false);
18
+ });
@@ -0,0 +1,81 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {readFile} from 'node:fs/promises';
4
+
5
+ const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
6
+ const json=rel=>read(rel).then(raw=>JSON.parse(raw.replace(/^\uFEFF/,'')));
7
+
8
+ const PARENT=Object.freeze({
9
+ version:'0.15.36',
10
+ release_id:'v0.15.36-090d9db3e0679c0d',
11
+ manifest_sha256:'090d9db3e0679c0d4943f3229ecab7b9fcccbe4f767348a568c9f3bb60d1b431',
12
+ generation_manifest_sha256:'6134f9f26b680e13ed545da4ab5f3020f411ea2569062fb9c154c8a7e036c9dc'
13
+ });
14
+
15
+ test('R60 identity is coherent and binds the exact production-accepted 0.15.36 predecessor',async()=>{
16
+ const [pkg,lock,release,prov,matrix,sbom,version,bridgePkg,contract]=await Promise.all([
17
+ json('package.json'),json('package-lock.json'),json('RELEASE.json'),json('PROVENANCE.json'),
18
+ json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),json('bridge/package.json'),
19
+ read('docs/R60-TASK-CONTRACT.md')
20
+ ]);
21
+ assert.equal(pkg.version,'0.15.37');
22
+ assert.equal(lock.version,pkg.version);
23
+ assert.equal(lock.packages[''].version,pkg.version);
24
+ assert.match(version,/DEADBYTE_VERSION = '0\.15\.37'/);
25
+ assert.equal(bridgePkg.version,pkg.version);
26
+ assert.equal(release.version,pkg.version);
27
+ assert.equal(release.train,'R60');
28
+ assert.equal(release.label,'REMOTE TRUTH + RESILIENCE HARDENING');
29
+ assert.equal(prov.version,pkg.version);
30
+ assert.equal(matrix.version,pkg.version);
31
+ assert.equal(matrix.train,'R60');
32
+ assert.equal(sbom.metadata.component.version,pkg.version);
33
+ assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r60:0.15.37');
34
+ assert.equal(release.parent.version,PARENT.version);
35
+ assert.equal(release.parent.release_id,PARENT.release_id);
36
+ assert.equal(release.parent.manifest_sha256,PARENT.manifest_sha256);
37
+ assert.equal(release.parent.generation_manifest_sha256,PARENT.generation_manifest_sha256);
38
+ assert.equal(release.runtime_predecessor.release_id,PARENT.release_id);
39
+ assert.equal(release.runtime_predecessor.manifest_sha256,PARENT.manifest_sha256);
40
+ assert.equal(release.runtime_predecessor.generation_manifest_sha256,PARENT.generation_manifest_sha256);
41
+ assert.equal(prov.runtime_predecessor.release_id,PARENT.release_id);
42
+ assert.equal(prov.runtime_predecessor.manifest_sha256,PARENT.manifest_sha256);
43
+ assert.equal(prov.runtime_predecessor.generation_manifest_sha256,PARENT.generation_manifest_sha256);
44
+ assert.match(contract,/TASK_ID: deadbyte-r60-remote-truth-resilience/);
45
+ assert.match(contract,/0\.15\.36/);
46
+ assert.match(contract,/0\.15\.37/);
47
+ });
48
+
49
+ test('R60 release contract exposes the proven remote truth semantics without widening dependencies',async()=>{
50
+ const [pkg,release,matrix]=await Promise.all([json('package.json'),json('RELEASE.json'),json('TEST-MATRIX.json')]);
51
+ assert.equal(Object.keys(pkg.dependencies??{}).length,4);
52
+ assert.equal(release.r60_remote_hardening.authority_truth_coherence,true);
53
+ assert.equal(release.r60_remote_hardening.execution_backed_readiness,true);
54
+ assert.equal(release.r60_remote_hardening.keyed_mutation_dedup,true);
55
+ assert.equal(release.r60_remote_hardening.keyless_ambiguous_mutation_fail_closed,true);
56
+ assert.equal(release.r60_remote_hardening.read_only_recovery,true);
57
+ assert.equal(release.r60_remote_hardening.bounded_reconnect_jitter,true);
58
+ assert.equal(release.r60_remote_hardening.terminal_transient_failure_taxonomy,true);
59
+ assert.equal(release.r60_remote_hardening.capability_manifest_human_suppression,true);
60
+ assert.equal(release.r60_remote_hardening.windows_log_bom_decode,true);
61
+ assert.equal(release.r60_remote_hardening.public_surface_tool_count,43);
62
+ assert.equal(release.r60_remote_hardening.stable_final_claim,false);
63
+ assert.equal(matrix.observed_pre_release_evidence.r60_behavioral_regression.status,'PASS');
64
+ assert.equal(matrix.observed_pre_release_evidence.r60_behavioral_regression.tests,1241);
65
+ assert.equal(matrix.observed_pre_release_evidence.r60_behavioral_regression.passed,1210);
66
+ assert.equal(matrix.observed_pre_release_evidence.r60_behavioral_regression.skipped,31);
67
+ assert.equal(matrix.observed_pre_release_evidence.r60_behavioral_regression.failed,0);
68
+ assert.equal(matrix.observed_pre_release_evidence.r60_windows_gate.status,'PASS_STAGED_WINDOWS_DOCTOR_WARN');
69
+ assert.equal(matrix.observed_pre_release_evidence.r60_package.status,'PASS_VERIFY_ONLY_PRE_FINAL_SEAL');
70
+ });
71
+
72
+ test('R60 package scripts bind the new focused, full-regression and Windows-gate entrypoints',async()=>{
73
+ const [pkg,gate]=await Promise.all([json('package.json'),read('scripts/gate-windows-r60-prepublish.ps1')]);
74
+ assert.match(pkg.scripts['r60:focused:test'],/r60-authority-coherence\.test\.mjs/);
75
+ assert.match(pkg.scripts['r60:focused:test'],/r60-remote-call-recovery\.test\.mjs/);
76
+ assert.equal(pkg.scripts['r60:full:test'],'node scripts/full-regression-r60.mjs');
77
+ assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r60-prepublish.ps1');
78
+ assert.match(gate,/ValidateSet\('all','preflight','focused','full-batch','manifest','doctor'\)/);
79
+ assert.match(gate,/R60 PREPUBLISH WINDOWS GATE STAGE: PASS/);
80
+ assert.match(gate,/--batch=\$Batch/);
81
+ });