deadbyte-mcp 0.15.0 → 0.15.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 (77) hide show
  1. package/MANIFEST.SHA256 +76 -41
  2. package/PROVENANCE.json +10 -0
  3. package/R45-PARENT.json +18 -0
  4. package/README.txt +14 -14
  5. package/RELEASE.json +37 -0
  6. package/SBOM.cdx.json +46 -0
  7. package/TEST-MATRIX.json +31 -0
  8. package/bin/deadbyte-hardware-observer-r45.exe +0 -0
  9. package/bin/deadbyte-hardware-observer-r45.obj +0 -0
  10. package/controller/README.TXT +2 -2
  11. package/controller/deadbyte-controller.ps1 +2 -2
  12. package/docs/ARCHITECTURE.md +1 -1
  13. package/native/deadbyte-hardware-observer.cpp +308 -0
  14. package/package.json +12 -7
  15. package/scripts/autonomous-tests.ps1 +2 -2
  16. package/scripts/build-hardware-r45.ps1 +71 -0
  17. package/scripts/deferred-slot-operation-r45.mjs +126 -0
  18. package/scripts/derive-r45-parent.mjs +24 -0
  19. package/scripts/derive-r45-release.mjs +72 -0
  20. package/scripts/derive-r45-tests.mjs +20 -0
  21. package/scripts/final-closure-r45.mjs +121 -0
  22. package/scripts/final-closure-verify-r45.mjs +220 -0
  23. package/scripts/finalize-r45.mjs +219 -0
  24. package/scripts/full-regression-r45.mjs +20 -0
  25. package/scripts/full-regression-summary-r45.mjs +14 -0
  26. package/scripts/gate-windows-r45.ps1 +44 -0
  27. package/scripts/init-host-policy.ps1 +39 -1
  28. package/scripts/inspect-active-release-r45.mjs +20 -0
  29. package/scripts/release-manifest.mjs +3 -1
  30. package/scripts/release-parity-r45.mjs +253 -0
  31. package/scripts/release-parity-tests-r45.ps1 +8 -0
  32. package/scripts/verify-r45-parent.mjs +142 -0
  33. package/scripts/windows-gate-evidence-r45.mjs +60 -0
  34. package/src/autonomous-runtime.mjs +12 -7
  35. package/src/capability-ledger.mjs +1 -0
  36. package/src/compact-gateway-mcp-tools.mjs +4 -2
  37. package/src/deadbyte-cli.mjs +17 -9
  38. package/src/doctor-r45.mjs +65 -0
  39. package/src/host-plane.mjs +133 -85
  40. package/src/mcp-server.mjs +64 -23
  41. package/src/native-diff-v2.mjs +9 -4
  42. package/src/native-diff.mjs +29 -7
  43. package/src/observation-mcp-tools.mjs +5 -1
  44. package/src/observation-output-contracts.mjs +8 -0
  45. package/src/observation-runtime.mjs +33 -2
  46. package/src/observation-smoke-client.mjs +6 -2
  47. package/src/output-contracts.mjs +27 -11
  48. package/src/r45-compact-disarmed-probe.mjs +74 -0
  49. package/src/r45-full-surface-probe.mjs +34 -0
  50. package/src/release-generation.mjs +1 -0
  51. package/src/remote-mcp-r45-parity-client.mjs +206 -0
  52. package/src/runtime-update.mjs +36 -8
  53. package/src/version.mjs +1 -1
  54. package/test/agent-runtime.test.mjs +1 -0
  55. package/test/autonomous-loop.test.mjs +24 -0
  56. package/test/autonomous-runtime.test.mjs +1 -0
  57. package/test/cli-entrypoint.test.mjs +4 -4
  58. package/test/coding-plane.test.mjs +1 -0
  59. package/test/compact-max-catalog-r45.test.mjs +99 -0
  60. package/test/contained.test.mjs +23 -11
  61. package/test/controller.test.mjs +5 -1
  62. package/test/core.test.mjs +1 -1
  63. package/test/full-max-catalog-r45.test.mjs +91 -0
  64. package/test/hardware-observation-r45.test.mjs +44 -0
  65. package/test/host-inline-r45.test.mjs +67 -0
  66. package/test/machine-mcp-integration.test.mjs +1 -0
  67. package/test/observation-mcp-tools.test.mjs +4 -3
  68. package/test/output-schema.test.mjs +1 -0
  69. package/test/package-boundary.test.mjs +1 -1
  70. package/test/production-docs.test.mjs +3 -3
  71. package/test/r33-closeout-regression.test.mjs +20 -19
  72. package/test/r33-finalization.test.mjs +3 -3
  73. package/test/r45-autonomous-quick-test.test.mjs +10 -0
  74. package/test/r45-finalization.test.mjs +84 -0
  75. package/test/release-generation.test.mjs +1 -0
  76. package/test/release-version.test.mjs +52 -41
  77. package/test/runtime-host-bootstrap-r45.test.mjs +46 -0
package/src/version.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export const DEADBYTE_VERSION = '0.15.0';
1
+ export const DEADBYTE_VERSION = '0.15.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';
@@ -54,6 +54,7 @@ async function connectAgent(f) {
54
54
  DEADBYTE_WORKSPACE_ROOT: f.root,
55
55
  DEADBYTE_SIGNING_KEY: f.keys.privateKeyPath,
56
56
  DEADBYTE_VERIFY_KEY: f.keys.publicKeyPath,
57
+ DEADBYTE_PRIVILEGED_POLICY: '',
57
58
  DEADBYTE_AGENT_RUNTIME: '1'
58
59
  },
59
60
  stderr: 'pipe'
@@ -147,6 +147,30 @@ test('R24 autonomous goal diagnoses a failing test, replans with native diff, be
147
147
  }
148
148
  });
149
149
 
150
+ test('historical autonomous release verification survives source drift and disarmed mutation authority', async () => {
151
+ const f = await fixture();
152
+ try {
153
+ const submitted = await f.runtime.submit({ submissionId:'historical-release-verify', rootId:'project',
154
+ title:'repair program', goal:'make exported value equal fixed', acceptance:'release evidence must remain verifiable',
155
+ maxIterations:10 });
156
+ const result = await f.runtime.run({ goalId:submitted.goal_id, maxCycles:16 });
157
+ assert.equal(result.status,'completed');
158
+ assert.equal((await f.runtime.verify({ goalId:submitted.goal_id })).ok,true);
159
+
160
+ await writeFile(f.program,"export const value = 'rolled-back';\n");
161
+ await rm(f.codingRuntime.policy.lease_file);
162
+ await rm(f.policy.lease_file);
163
+
164
+ const verified = await f.runtime.verify({ goalId:submitted.goal_id });
165
+ assert.equal(verified.ok,true);
166
+ assert.equal(verified.native_diffs_verified,2);
167
+ assert.equal(verified.required_profiles_verified,3);
168
+ } finally {
169
+ await new Promise(resolve => f.planner.server.close(resolve));
170
+ await rm(f.root,{recursive:true,force:true});
171
+ }
172
+ });
173
+
150
174
  test('autonomous profile execution is capped by the absolute autonomous lease without changing coding request identity', async () => {
151
175
  const calls=[];
152
176
  const f=await fixture([],{
@@ -68,6 +68,7 @@ async function fixture() {
68
68
  command:process.execPath, args:[serverPath], cwd:repoRoot,
69
69
  env:{ ...getDefaultEnvironment(), DEADBYTE_WORKSPACE_ROOT:workspaceRoot,
70
70
  DEADBYTE_SIGNING_KEY:keys.privateKeyPath, DEADBYTE_VERIFY_KEY:keys.publicKeyPath,
71
+ DEADBYTE_PRIVILEGED_POLICY:'',
71
72
  DEADBYTE_AGENT_RUNTIME:'1', DEADBYTE_CODING_RUNTIME:'1',
72
73
  DEADBYTE_CODING_POLICY:codingPolicyPath, DEADBYTE_AUTONOMOUS_RUNTIME:'1',
73
74
  DEADBYTE_AUTONOMOUS_POLICY:autonomousPolicyPath }, stderr:'pipe'
@@ -21,7 +21,7 @@ test('npx CLI reports the canonical package version through --version, -v and ve
21
21
  for(const arg of ['--version','-v','version']){
22
22
  const result=spawnSync(process.execPath,[cliPath,arg],{cwd:root,encoding:'utf8',windowsHide:true});
23
23
  assert.equal(result.status,0,result.stderr);
24
- assert.equal(result.stdout.trim(),'0.15.0');
24
+ assert.equal(result.stdout.trim(),'0.15.1');
25
25
  }
26
26
  });
27
27
 
@@ -45,11 +45,11 @@ test('npx CLI exposes local supervisor lifecycle without any supervisor arm comm
45
45
  assert.match(source,/supervisorrecover/);
46
46
  const mapping=source.match(/const SUPERVISOR_COMMANDS=.*?;\n/s)?.[0]??'';
47
47
  assert.doesNotMatch(mapping,/arm(?:coding|autonomous|process|host)/i);
48
- assert.match(source,/npx deadbyte-mcp@latest supervisor status/);
48
+ assert.match(source,/npx -y \$\{exact\} supervisor status/);
49
49
  });
50
50
 
51
51
  test('README makes npx the primary operator UX',async()=>{
52
52
  const readme=await readFile(path.join(root,'README.txt'),'utf8');
53
- assert.match(readme,/npx deadbyte-mcp@latest remote/);
54
- assert.match(readme,/npx deadbyte-mcp@latest audit verify/);
53
+ assert.match(readme,/npx -y deadbyte-mcp@0\.15\.1 remote/);
54
+ assert.match(readme,/npx -y deadbyte-mcp@0\.15\.1 audit verify/);
55
55
  });
@@ -60,6 +60,7 @@ async function fixture() {
60
60
  DEADBYTE_WORKSPACE_ROOT: workspaceRoot,
61
61
  DEADBYTE_SIGNING_KEY: keys.privateKeyPath,
62
62
  DEADBYTE_VERIFY_KEY: keys.publicKeyPath,
63
+ DEADBYTE_PRIVILEGED_POLICY: '',
63
64
  DEADBYTE_AGENT_RUNTIME: '1',
64
65
  DEADBYTE_CODING_RUNTIME: '1',
65
66
  DEADBYTE_CODING_POLICY: policyPath
@@ -0,0 +1,99 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { createHash } from 'node:crypto';
4
+ import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { Client } from '@modelcontextprotocol/client';
8
+ import { StdioClientTransport, getDefaultEnvironment } from '@modelcontextprotocol/client/stdio';
9
+ import { createR34Fixture } from './helpers/autonomous-r34-fixture.mjs';
10
+
11
+ const here=path.dirname(fileURLToPath(import.meta.url));
12
+ const repoRoot=path.resolve(here,'..');
13
+ const serverPath=path.join(repoRoot,'src','mcp-server.mjs');
14
+ const desktopPolicyPath=path.join(repoRoot,'controller','deadbyte-desktop-policy.json');
15
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
16
+ const absent=async p=>{try{await access(p);return false;}catch(e){if(e?.code==='ENOENT')return true;throw e;}};
17
+
18
+ test('R45 real max-runtime compact stdio catalog is exactly 43 with verified skill_catalog while all authority remains disarmed',async()=>{
19
+ const f=await createR34Fixture({authority:'disarmed'});
20
+ const processPolicyPath=path.join(f.root,'process-policy.json');
21
+ const processGrant=path.join(f.root,'process-grant.json');
22
+ const processState=path.join(f.root,'process-state');
23
+ const hostPolicyPath=path.join(f.root,'host-policy.json');
24
+ const hostArm=path.join(f.root,'host-arm.json');
25
+ const nodeSha=sha(await readFile(process.execPath));
26
+ await mkdir(processState,{recursive:true});
27
+ await writeFile(processPolicyPath,JSON.stringify({
28
+ schema:'deadbyte.process-policy.v1',enabled:true,grant_file:processGrant,state_dir:processState,
29
+ native_host:{path:process.execPath,sha256:nodeSha},
30
+ roots:{core:{path:f.project,deny_paths:[]}},
31
+ profiles:{node:{executable:process.execPath,executable_sha256:nodeSha,root_ids:['core'],
32
+ prefix_args:[],transport:'pipe',max_args:8,max_arg_bytes:1024,max_sessions:2,
33
+ max_input_bytes:65536,max_retained_output_bytes:262144,env_allow:['PATH','TEMP','TMP'],
34
+ input_actions:{ping:'PING\r\n'}}}
35
+ },null,2));
36
+ await writeFile(hostPolicyPath,JSON.stringify({
37
+ schema:'deadbyte.host-policy.v1',enabled:true,arm_file:hostArm,max_read_bytes:262144,max_write_bytes:1048576,
38
+ roots:{core:{path:f.project,read:true,write:true,exec:true}},
39
+ commands:{node_script:{kind:'script',executable:process.execPath,executable_sha256:nodeSha,
40
+ root_ids:['core'],prefix_args:[],extensions:['.mjs'],timeout_ms:5000,max_output_bytes:65536}}
41
+ },null,2));
42
+
43
+ const desktopRaw=JSON.parse(await readFile(desktopPolicyPath,'utf8'));
44
+ const desktopGrant=desktopRaw.grant_file;
45
+ const codingLease=f.codingPolicy.lease_file;
46
+ const autonomousLease=f.policy.lease_file;
47
+ for(const q of [processGrant,hostArm,desktopGrant,codingLease,autonomousLease]) assert.equal(await absent(q),true,'authority unexpectedly armed before start: '+q);
48
+
49
+ const client=new Client({name:'deadbyte-r40-max-catalog',version:'0.12.0'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
50
+ const env={
51
+ ...getDefaultEnvironment(),
52
+ DEADBYTE_CAPABILITY_PROFILE:'compact',
53
+ DEADBYTE_AUDIT_RUNTIME:'0',
54
+ DEADBYTE_STATE_ROOT:path.join(f.root,'state'),
55
+ DEADBYTE_WORKSPACE_ROOT:f.root,
56
+ DEADBYTE_SIGNING_KEY:f.keys.privateKeyPath,
57
+ DEADBYTE_VERIFY_KEY:f.keys.publicKeyPath,
58
+ DEADBYTE_PRIVILEGED_POLICY:hostPolicyPath,
59
+ DEADBYTE_MACHINE_RUNTIME:'1',
60
+ DEADBYTE_AGENT_RUNTIME:'0',
61
+ DEADBYTE_PROCESS_RUNTIME:'1',
62
+ DEADBYTE_PROCESS_POLICY:processPolicyPath,
63
+ DEADBYTE_CODING_RUNTIME:'1',
64
+ DEADBYTE_CODING_POLICY:path.join(f.root,'coding-policy.json'),
65
+ DEADBYTE_MACHINE_FS_RUNTIME:'1',
66
+ DEADBYTE_OBSERVATION_RUNTIME:'1',
67
+ DEADBYTE_DESKTOP_RUNTIME:'1',
68
+ DEADBYTE_DESKTOP_POLICY:desktopPolicyPath,
69
+ DEADBYTE_AUTONOMOUS_RUNTIME:'1',
70
+ DEADBYTE_AUTONOMOUS_POLICY:path.join(f.root,'autonomous-policy.json'),
71
+ DEADBYTE_AUTONOMOUS_SUPERVISOR_MODE:'external'
72
+ };
73
+ const transport=new StdioClientTransport({command:process.execPath,args:[serverPath],cwd:repoRoot,env,stderr:'pipe'});
74
+ try{
75
+ await client.connect(transport);
76
+ const listed=await client.listTools();
77
+ const names=listed.tools.map(t=>t.name).sort();
78
+ assert.equal(names.length,43,'expected exact compact max catalog 43, got '+names.length+': '+names.join(','));
79
+ for(const name of ['capability_manifest','desktop_control','coding_inspect','machine_fs','machine_observe','process_session',
80
+ 'host_file_read','host_file_write','host_exec','skill_catalog']) assert.ok(names.includes(name),'missing '+name);
81
+ const manifest=await client.callTool({name:'capability_manifest',arguments:{}});
82
+ assert.equal(manifest.isError,false);
83
+ const m=manifest.structuredContent.result;
84
+ assert.equal(m.schema,'deadbyte.capability-manifest.v2');
85
+ assert.equal(m.profile,'compact');
86
+ assert.equal(m.tool_count,43);
87
+ assert.deepEqual(m.tool_catalog,names);
88
+ assert.match(m.catalog_sha256,/^[0-9a-f]{64}$/);
89
+ const hardware=m.capabilities.find(item=>item.id==='observation.hardware_query');
90
+ assert.ok(hardware);assert.equal(hardware.authority,'none');assert.equal(hardware.compact_tool,'machine_observe');assert.equal(hardware.compact_op,'hardware_query');
91
+ const skill=m.capabilities.find(item=>item.id==='skill.catalog');
92
+ assert.ok(skill);assert.equal(skill.authority,'none');assert.equal(skill.mutating,false);
93
+ console.log(JSON.stringify({tool_count:m.tool_count,catalog_sha256:m.catalog_sha256,ledger_sha256:m.ledger_sha256,desktop:true,hardware_query:true,skill:true,authority:'DISARMED'}));
94
+ } finally {
95
+ await client.close().catch(()=>{});
96
+ for(const q of [processGrant,hostArm,desktopGrant,codingLease,autonomousLease]) assert.equal(await absent(q),true,'authority file appeared during catalog probe: '+q);
97
+ await f.cleanup();
98
+ }
99
+ });
@@ -352,6 +352,10 @@ test('contained execution source has a compile-time worker registry and no user
352
352
  const executor = await readFile(fileURLToPath(new URL('../src/contained-executor.mjs', import.meta.url)), 'utf8');
353
353
  const registry = await readFile(fileURLToPath(new URL('../src/worker-registry.mjs', import.meta.url)), 'utf8');
354
354
  const server = await readFile(fileURLToPath(new URL('../src/mcp-server.mjs', import.meta.url)), 'utf8');
355
+ const containedStart = server.indexOf("toolServer.registerTool(\n 'contained_transform'");
356
+ const containedEnd = server.indexOf('toolServer.registerTool(', containedStart + 1);
357
+ const contained = server.slice(containedStart, containedEnd);
358
+ assert.ok(containedStart >= 0 && containedEnd > containedStart);
355
359
  assert.match(registry, /contained-transform-worker\.exe/);
356
360
  assert.match(registry, /contained-reverse-worker\.exe/);
357
361
  assert.match(registry, /CONTAINED_EXECUTION_REGISTRY/);
@@ -360,9 +364,9 @@ test('contained execution source has a compile-time worker registry and no user
360
364
  assert.match(registry, /lowercase_ascii/);
361
365
  assert.match(registry, /reverse_bytes/);
362
366
  assert.match(executor, /loadVerifiedWorkerRegistry/);
363
- assert.match(server, /'contained_transform'/);
364
- assert.match(server, /z\.enum\(CONTAINED_TRANSFORM_OPERATIONS\)/);
365
- assert.doesNotMatch(server, /executable:\s*z\./);
367
+ assert.match(contained, /'contained_transform'/);
368
+ assert.match(contained, /z\.enum\(CONTAINED_TRANSFORM_OPERATIONS\)/);
369
+ assert.doesNotMatch(contained, /executable:\s*z\./);
366
370
  assert.doesNotMatch(executor, /--worker/);
367
371
  assert.doesNotMatch(server, /registerTool\(\s*['"](?:command_run|shell_execute|powershell_run)['"]/);
368
372
  });
@@ -706,12 +710,16 @@ test('contained execution validator rejects missing or altered worker manifest e
706
710
 
707
711
  test('MCP contained_transform schema is a compile-time operation enum with no executable or invocation-control surface', async () => {
708
712
  const server = await readFile(fileURLToPath(new URL('../src/mcp-server.mjs', import.meta.url)), 'utf8');
709
- assert.match(server, /z\.enum\(CONTAINED_TRANSFORM_OPERATIONS\)/);
710
- assert.equal((server.match(/inputSchema: z\.strictObject\(\{/g) ?? []).length, 8);
713
+ const containedStart = server.indexOf("toolServer.registerTool(\n 'contained_transform'");
714
+ const containedEnd = server.indexOf('toolServer.registerTool(', containedStart + 1);
715
+ const contained = server.slice(containedStart, containedEnd);
716
+ assert.ok(containedStart >= 0 && containedEnd > containedStart);
717
+ assert.match(contained, /z\.enum\(CONTAINED_TRANSFORM_OPERATIONS\)/);
718
+ assert.match(contained, /inputSchema: z\.strictObject\(\{/);
711
719
  assert.match(server, /if \(hostPolicy\)/);
712
720
  for (const name of ['host_file_read', 'host_file_write', 'host_exec']) assert.match(server, new RegExp(`'${name}'`));
713
- assert.doesNotMatch(server, /inputSchema: z\.object\(\{/);
714
- assert.doesNotMatch(server, /executable:\s*z\.|argv:\s*z\.|environment:\s*z\.|challenge:\s*z\.|request_digest:\s*z\.|worker_id:\s*z\./);
721
+ assert.doesNotMatch(contained, /inputSchema: z\.object\(\{/);
722
+ assert.doesNotMatch(contained, /executable:\s*z\.|argv:\s*z\.|environment:\s*z\.|challenge:\s*z\.|request_digest:\s*z\.|worker_id:\s*z\./);
715
723
  });
716
724
 
717
725
  test('R27 Windows batch gate builds native payload before freezing and verifying the candidate', async () => {
@@ -914,13 +922,17 @@ test('contained execution validator fails closed on active network evidence', ()
914
922
 
915
923
  test('execution authority is strict at MCP and native argv boundaries', async () => {
916
924
  const server = await readFile(fileURLToPath(new URL('../src/mcp-server.mjs', import.meta.url)), 'utf8');
925
+ const containedStart = server.indexOf("toolServer.registerTool(\n 'contained_transform'");
926
+ const containedEnd = server.indexOf('toolServer.registerTool(', containedStart + 1);
927
+ const contained = server.slice(containedStart, containedEnd);
917
928
  const launcher = await readFile(fileURLToPath(new URL('../native/deadbyte-exec.cpp', import.meta.url)), 'utf8');
918
929
  const helper = await readFile(fileURLToPath(new URL('../native/contained-network-proof.h', import.meta.url)), 'utf8');
919
930
  const authority = await readFile(fileURLToPath(new URL('../src/authority-smoke.mjs', import.meta.url)), 'utf8');
920
- assert.match(server, /inputSchema: z\.strictObject\(/);
921
- assert.doesNotMatch(server, /worker_id:\s*z\./);
922
- assert.doesNotMatch(server, /executable:\s*z\./);
923
- assert.doesNotMatch(server, /argv:\s*z\./);
931
+ assert.ok(containedStart >= 0 && containedEnd > containedStart);
932
+ assert.match(contained, /inputSchema: z\.strictObject\(/);
933
+ assert.doesNotMatch(contained, /worker_id:\s*z\./);
934
+ assert.doesNotMatch(contained, /executable:\s*z\./);
935
+ assert.doesNotMatch(contained, /argv:\s*z\./);
924
936
  assert.match(launcher, /argc != 7/);
925
937
  assert.match(launcher, /invalid fixed argument contract/);
926
938
  assert.match(helper, /HasExactContainedWorkerArguments/);
@@ -82,11 +82,15 @@ test('controller keeps privileged policy optional and propagates it only to the
82
82
 
83
83
  test('Windows host policy bootstrap pins executables and creates only explicit local roots', async () => {
84
84
  const init = await readFile(fileURLToPath(new URL('../scripts/init-host-policy.ps1', import.meta.url)), 'utf8');
85
- assert.match(init, /deadbyte\.host-policy\.v1/);
85
+ assert.match(init, /deadbyte\.host-policy\.v2/);
86
86
  assert.match(init, /Get-FileHash/);
87
87
  assert.match(init, /powershell_script/);
88
88
  assert.match(init, /cmd_script/);
89
89
  assert.match(init, /node_script/);
90
+ assert.match(init, /powershell_inline/);
91
+ assert.match(init, /cmd_inline/);
92
+ assert.match(init, /node_inline/);
93
+ assert.match(init, /native_exec/);
90
94
  assert.match(init, /D:\\Projects/);
91
95
  assert.match(init, /State\s+: DISARMED/);
92
96
  });
@@ -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.15.0');
108
+ assert.equal(result.receipt.runtime.package_version, '0.15.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}$/);
@@ -0,0 +1,91 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { createHash } from 'node:crypto';
4
+ import { access, mkdir, readFile, writeFile } from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { Client } from '@modelcontextprotocol/client';
8
+ import { StdioClientTransport, getDefaultEnvironment } from '@modelcontextprotocol/client/stdio';
9
+ import { createR34Fixture } from './helpers/autonomous-r34-fixture.mjs';
10
+
11
+ const here=path.dirname(fileURLToPath(import.meta.url));
12
+ const repoRoot=path.resolve(here,'..');
13
+ const serverPath=path.join(repoRoot,'src','mcp-server.mjs');
14
+ const desktopPolicyPath=path.join(repoRoot,'controller','deadbyte-desktop-policy.json');
15
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
16
+ const absent=async p=>{try{await access(p);return false;}catch(e){if(e?.code==='ENOENT')return true;throw e;}};
17
+
18
+ test('R45 real max-runtime full stdio catalog is exactly 82 with skill and four Desktop primitives while authority remains disarmed',async()=>{
19
+ const f=await createR34Fixture({authority:'disarmed'});
20
+ const processPolicyPath=path.join(f.root,'process-policy.json');
21
+ const processGrant=path.join(f.root,'process-grant.json');
22
+ const processState=path.join(f.root,'process-state');
23
+ const hostPolicyPath=path.join(f.root,'host-policy.json');
24
+ const hostArm=path.join(f.root,'host-arm.json');
25
+ const nodeSha=sha(await readFile(process.execPath));
26
+ await mkdir(processState,{recursive:true});
27
+ await writeFile(processPolicyPath,JSON.stringify({
28
+ schema:'deadbyte.process-policy.v1',enabled:true,grant_file:processGrant,state_dir:processState,
29
+ native_host:{path:process.execPath,sha256:nodeSha},
30
+ roots:{core:{path:f.project,deny_paths:[]}},
31
+ profiles:{node:{executable:process.execPath,executable_sha256:nodeSha,root_ids:['core'],
32
+ prefix_args:[],transport:'pipe',max_args:8,max_arg_bytes:1024,max_sessions:2,
33
+ max_input_bytes:65536,max_retained_output_bytes:262144,env_allow:['PATH','TEMP','TMP'],
34
+ input_actions:{ping:'PING\r\n'}}}
35
+ },null,2));
36
+ await writeFile(hostPolicyPath,JSON.stringify({
37
+ schema:'deadbyte.host-policy.v1',enabled:true,arm_file:hostArm,max_read_bytes:262144,max_write_bytes:1048576,
38
+ roots:{core:{path:f.project,read:true,write:true,exec:true}},
39
+ commands:{node_script:{kind:'script',executable:process.execPath,executable_sha256:nodeSha,
40
+ root_ids:['core'],prefix_args:[],extensions:['.mjs'],timeout_ms:5000,max_output_bytes:65536}}
41
+ },null,2));
42
+
43
+ const desktopRaw=JSON.parse(await readFile(desktopPolicyPath,'utf8'));
44
+ const desktopGrant=desktopRaw.grant_file;
45
+ const codingLease=f.codingPolicy.lease_file;
46
+ const autonomousLease=f.policy.lease_file;
47
+ for(const q of [processGrant,hostArm,desktopGrant,codingLease,autonomousLease]) assert.equal(await absent(q),true,'authority unexpectedly armed before start: '+q);
48
+
49
+ const client=new Client({name:'deadbyte-r45-full-catalog',version:'0.15.1'},{versionNegotiation:{mode:{pin:'2026-07-28'}}});
50
+ const env={
51
+ ...getDefaultEnvironment(),
52
+ DEADBYTE_CAPABILITY_PROFILE:'full',
53
+ DEADBYTE_AUDIT_RUNTIME:'0',
54
+ DEADBYTE_STATE_ROOT:path.join(f.root,'state'),
55
+ DEADBYTE_WORKSPACE_ROOT:f.root,
56
+ DEADBYTE_SIGNING_KEY:f.keys.privateKeyPath,
57
+ DEADBYTE_VERIFY_KEY:f.keys.publicKeyPath,
58
+ DEADBYTE_PRIVILEGED_POLICY:hostPolicyPath,
59
+ DEADBYTE_MACHINE_RUNTIME:'1',
60
+ DEADBYTE_AGENT_RUNTIME:'1',
61
+ DEADBYTE_PROCESS_RUNTIME:'1',
62
+ DEADBYTE_PROCESS_POLICY:processPolicyPath,
63
+ DEADBYTE_CODING_RUNTIME:'1',
64
+ DEADBYTE_CODING_POLICY:path.join(f.root,'coding-policy.json'),
65
+ DEADBYTE_MACHINE_FS_RUNTIME:'1',
66
+ DEADBYTE_OBSERVATION_RUNTIME:'1',
67
+ DEADBYTE_DESKTOP_RUNTIME:'1',
68
+ DEADBYTE_DESKTOP_POLICY:desktopPolicyPath,
69
+ DEADBYTE_AUTONOMOUS_RUNTIME:'1',
70
+ DEADBYTE_AUTONOMOUS_POLICY:path.join(f.root,'autonomous-policy.json'),
71
+ DEADBYTE_AUTONOMOUS_SUPERVISOR_MODE:'external'
72
+ };
73
+ const transport=new StdioClientTransport({command:process.execPath,args:[serverPath],cwd:repoRoot,env,stderr:'pipe'});
74
+ try{
75
+ await client.connect(transport);
76
+ const listed=await client.listTools();
77
+ const names=listed.tools.map(t=>t.name).sort();
78
+ const {R45_EXPECTED_TOOLS}=await import('../src/remote-mcp-r45-parity-client.mjs');
79
+ assert.equal(names.length,82,'expected exact full R45 catalog 82, got '+names.length+': '+names.join(','));
80
+ assert.deepEqual(names,R45_EXPECTED_TOOLS);
81
+ for(const name of ['machine_hardware_query','desktop_status','desktop_observe','desktop_target','desktop_action',
82
+ 'host_file_read','host_file_write','host_exec','skill_catalog']) assert.ok(names.includes(name),'missing '+name);
83
+ for(const tool of listed.tools) assert.equal(tool.outputSchema?.additionalProperties,false,'non-strict output '+tool.name);
84
+ const catalog_sha256=sha(Buffer.from(JSON.stringify(names),'utf8'));
85
+ console.log(JSON.stringify({tool_count:names.length,catalog_sha256,desktop_tools:4,skill:true,authority:'DISARMED'}));
86
+ } finally {
87
+ await client.close().catch(()=>{});
88
+ for(const q of [processGrant,hostArm,desktopGrant,codingLease,autonomousLease]) assert.equal(await absent(q),true,'authority file appeared during catalog probe: '+q);
89
+ await f.cleanup();
90
+ }
91
+ });
@@ -0,0 +1,44 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { mkdtemp, mkdir, writeFile } from 'node:fs/promises';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { generateTrustKeypair } from '../src/trust.mjs';
7
+ import { loadCodingPolicy } from '../src/coding-plane.mjs';
8
+ import { createObservationRuntime, verifyObservationReceiptFile } from '../src/observation-runtime.mjs';
9
+
10
+ async function fixture(){
11
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-hardware-query-r45-'));
12
+ const project=path.join(root,'project');await mkdir(project);
13
+ const policyPath=path.join(root,'coding-policy.json');
14
+ await writeFile(policyPath,JSON.stringify({schema:'deadbyte.coding-policy.v1',enabled:true,
15
+ lease_file:path.join(root,'coding-grant.json'),evidence_dir:path.join(root,'evidence'),
16
+ roots:{project:{path:project,read:true,write:false,exec:false,deny_paths:[]}},commands:{},
17
+ max_read_bytes:65536,max_write_bytes:65536}));
18
+ const policy=await loadCodingPolicy(policyPath);
19
+ const keys=await generateTrustKeypair({privateKeyPath:path.join(root,'private.pem'),publicKeyPath:path.join(root,'public.pem')});
20
+ const calls=[];
21
+ const hardwareSnapshotProvider=async query=>{calls.push(query);return {schema:'deadbyte.hardware-query.v1',query,
22
+ data:query==='cpu'?{brand:'TEST CPU',logical_processors:16}:{fixture:true}};};
23
+ const runtime=createObservationRuntime({policy,signingKeyPath:keys.privateKeyPath,verifyKeyPath:keys.publicKeyPath,
24
+ stateRoot:root,processSnapshotProvider:async()=>[],systemSnapshotProvider:async()=>({hostname:'x',platform:'win32',architecture:'x64',
25
+ uptime_seconds:1,total_memory_bytes:1,free_memory_bytes:1,cpu_count:1,load_average:[0,0,0]}),
26
+ ownedRuntimePidProvider:async()=>new Set(),hardwareSnapshotProvider});
27
+ return {root,policy,keys,runtime,calls};
28
+ }
29
+
30
+ test('R45 hardware query is typed read-only observation with signed evidence and no host authority',async()=>{
31
+ const f=await fixture();
32
+ const out=await f.runtime.hardwareQuery({query:'cpu'});
33
+ assert.equal(out.query,'cpu');assert.equal(out.data.brand,'TEST CPU');assert.deepEqual(f.calls,['cpu']);
34
+ assert.match(out.request_sha256,/^[0-9a-f]{64}$/);assert.match(out.result_head_sha256,/^[0-9a-f]{64}$/);
35
+ assert.match(out.receipt_id,/^[0-9a-f]{24}$/);assert.match(out.receipt_sha256,/^[0-9a-f]{64}$/);
36
+ const verified=await verifyObservationReceiptFile({policy:f.policy,verifyKeyPath:f.keys.publicKeyPath,receiptId:out.receipt_id});
37
+ assert.equal(verified.ok,true);assert.equal(verified.signature_valid,true);assert.equal(verified.kind,'machine_hardware_query');
38
+ });
39
+
40
+ test('R45 hardware query rejects untyped arbitrary query names before provider dispatch',async()=>{
41
+ const f=await fixture();
42
+ await assert.rejects(()=>f.runtime.hardwareQuery({query:'run_powershell'}),/hardware query/i);
43
+ assert.deepEqual(f.calls,[]);
44
+ });
@@ -0,0 +1,67 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { createHash, randomBytes } from 'node:crypto';
4
+ import { mkdtemp, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import {
8
+ HOST_GRANT_SCHEMA, HOST_POLICY_SCHEMA_V2, hostExecInline, hostExecNative, loadHostPolicy
9
+ } from '../src/host-plane.mjs';
10
+
11
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
12
+
13
+ async function fixture(){
14
+ const dir=await mkdtemp(path.join(os.tmpdir(),'deadbyte-host-inline-r45-'));
15
+ const root=path.join(dir,'root');await mkdir(root);
16
+ const arm=path.join(dir,'arm.json'), policyPath=path.join(dir,'policy.json');
17
+ const exeSha=sha(await readFile(process.execPath));
18
+ const raw={
19
+ schema:HOST_POLICY_SCHEMA_V2,enabled:true,arm_file:arm,
20
+ roots:{core:{path:root,read:true,write:true,exec:true}},
21
+ commands:{
22
+ node_inline:{kind:'inline',executable:process.execPath,executable_sha256:exeSha,root_ids:['core'],
23
+ prefix_args:['-e'],timeout_ms:5000,max_output_bytes:65536,max_command_chars:32768}
24
+ },
25
+ native_exec:{enabled:true,root_ids:['core'],timeout_ms:5000,max_output_bytes:65536,max_args:64,max_arg_chars:8192},
26
+ max_read_bytes:262144,max_write_bytes:1048576
27
+ };
28
+ await writeFile(policyPath,JSON.stringify(raw,null,2));
29
+ const policy=await loadHostPolicy(policyPath);
30
+ await writeFile(arm,JSON.stringify({schema:HOST_GRANT_SCHEMA,policy_sha256:policy.policy_sha256,
31
+ instance_nonce:randomBytes(32).toString('hex'),armed_at_utc:new Date().toISOString()},null,2));
32
+ return {dir,root,arm,policy,exeSha};
33
+ }
34
+
35
+ test('R45 host inline executes in argv memory with zero staging artifact and hashes command/output',async t=>{
36
+ const f=await fixture();t.after(()=>rm(f.dir,{recursive:true,force:true}));
37
+ const before=(await readdir(f.root)).sort();
38
+ const command='process.stdout.write("INLINE_OK")';
39
+ const out=await hostExecInline(f.policy,{commandId:'node_inline',rootId:'core',command,cwd:'.',timeoutMs:2000});
40
+ const after=(await readdir(f.root)).sort();
41
+ assert.deepEqual(after,before,'inline execution must not stage a script file');
42
+ assert.equal(out.exit_code,0);assert.equal(out.stdout,'INLINE_OK');assert.equal(out.stderr,'');
43
+ assert.equal(out.command_sha256,sha(Buffer.from(command,'utf8')));
44
+ assert.equal(out.stdout_sha256,sha(Buffer.from('INLINE_OK','utf8')));
45
+ assert.equal(out.stderr_sha256,sha(Buffer.alloc(0)));
46
+ assert.match(out.argv_sha256,/^[0-9a-f]{64}$/);assert.equal(out.executable_sha256,f.exeSha);
47
+ });
48
+
49
+ test('R45 native argv execution accepts arbitrary absolute hash-pinned executable only while Host is armed',async t=>{
50
+ const f=await fixture();t.after(()=>rm(f.dir,{recursive:true,force:true}));
51
+ const before=(await readdir(f.root)).sort();
52
+ const out=await hostExecNative(f.policy,{rootId:'core',executable:process.execPath,executableSha256:f.exeSha,
53
+ args:['-e','process.stdout.write("NATIVE_OK")'],cwd:'.',timeoutMs:2000});
54
+ assert.equal(out.exit_code,0);assert.equal(out.stdout,'NATIVE_OK');
55
+ assert.deepEqual((await readdir(f.root)).sort(),before,'native argv execution must not create staging files');
56
+ await assert.rejects(()=>hostExecNative(f.policy,{rootId:'core',executable:process.execPath,executableSha256:'f'.repeat(64),
57
+ args:['--version'],cwd:'.'}),/executable hash mismatch/i);
58
+ });
59
+
60
+ test('R45 inline execution observes authority revocation during a live child and fails closed',async t=>{
61
+ const f=await fixture();t.after(()=>rm(f.dir,{recursive:true,force:true}));
62
+ const running=hostExecInline(f.policy,{commandId:'node_inline',rootId:'core',
63
+ command:'setTimeout(()=>process.stdout.write("SHOULD_NOT_COMPLETE"),1500)',cwd:'.',timeoutMs:4000,authorityPollMs:50});
64
+ await new Promise(r=>setTimeout(r,150));
65
+ await rm(f.arm,{force:true});
66
+ await assert.rejects(()=>running,/host authority changed during operation/i);
67
+ });
@@ -51,6 +51,7 @@ async function fixture() {
51
51
  env: {
52
52
  ...getDefaultEnvironment(), DEADBYTE_STATE_ROOT: root, DEADBYTE_MACHINE_RUNTIME: '1',
53
53
  DEADBYTE_SIGNING_KEY: keys.privateKeyPath, DEADBYTE_VERIFY_KEY: keys.publicKeyPath,
54
+ DEADBYTE_PRIVILEGED_POLICY: '',
54
55
  DEADBYTE_AGENT_RUNTIME: '0', DEADBYTE_CODING_RUNTIME: '0', DEADBYTE_AUTONOMOUS_RUNTIME: '0'
55
56
  }, stderr: 'pipe'
56
57
  });
@@ -15,14 +15,15 @@ function runtime(){
15
15
  searchStatus:async()=>({status:'ok',search_id:hex('a'),state:'completed',result_count:0,files_scanned:0,bytes_scanned:0,truncated:false,request_sha256:hex('b'),result_head_sha256:hex('c'),receipt_id:receipt,receipt_sha256:hex('d'),error:null}),
16
16
  searchCancel:async()=>({status:'ok',search_id:hex('a'),state:'cancelled',cancel_requested:true}),
17
17
  processList:async()=>({status:'ok',snapshot_id:hex('e'),observed_at_utc:new Date(0).toISOString(),processes:[],next_cursor:null,request_sha256:hex('b'),result_head_sha256:hex('c'),receipt_id:receipt,receipt_sha256:hex('d')}),
18
- systemStatus:async()=>({status:'ok',observed_at_utc:new Date(0).toISOString(),hostname:'x',platform:'win32',architecture:'x64',uptime_seconds:1,total_memory_bytes:2,free_memory_bytes:1,cpu_count:1,load_average:[0,0,0],request_sha256:hex('b'),result_head_sha256:hex('c'),receipt_id:receipt,receipt_sha256:hex('d')})
18
+ systemStatus:async()=>({status:'ok',observed_at_utc:new Date(0).toISOString(),hostname:'x',platform:'win32',architecture:'x64',uptime_seconds:1,total_memory_bytes:2,free_memory_bytes:1,cpu_count:1,load_average:[0,0,0],request_sha256:hex('b'),result_head_sha256:hex('c'),receipt_id:receipt,receipt_sha256:hex('d')}),
19
+ hardwareQuery:async({query})=>({status:'ok',query,observed_at_utc:new Date(0).toISOString(),observer_sha256:hex('e'),data:{vendor:'x'},request_sha256:hex('b'),result_head_sha256:hex('c'),receipt_id:receipt,receipt_sha256:hex('d')})
19
20
  };
20
21
  }
21
22
 
22
- test('R32 registers exactly six bounded observation tools',()=>{
23
+ test('R45 registers exactly seven bounded observation tools including typed native hardware',()=>{
23
24
  const server=new FakeServer(); registerObservationTools(server,{runtime:runtime()});
24
25
  assert.deepEqual([...server.tools.keys()].sort(),[
25
- 'machine_process_list','machine_search_cancel','machine_search_page','machine_search_start','machine_search_status','machine_system_status'
26
+ 'machine_hardware_query','machine_process_list','machine_search_cancel','machine_search_page','machine_search_start','machine_search_status','machine_system_status'
26
27
  ]);
27
28
  for(const [name,tool] of server.tools){ assert.ok(tool.spec.inputSchema,`${name} input`); assert.ok(tool.spec.outputSchema,`${name} output`); }
28
29
  });
@@ -40,6 +40,7 @@ async function fixture() {
40
40
  DEADBYTE_WORKSPACE_ROOT: workspaceRoot,
41
41
  DEADBYTE_SIGNING_KEY: keys.privateKeyPath,
42
42
  DEADBYTE_VERIFY_KEY: keys.publicKeyPath,
43
+ DEADBYTE_PRIVILEGED_POLICY: '',
43
44
  DEADBYTE_AGENT_RUNTIME: '1'
44
45
  },
45
46
  stderr: 'pipe'
@@ -39,6 +39,6 @@ test('R28 package boundary contains only immutable workspace seed files', () =>
39
39
 
40
40
  test('publish boundary excludes live state, private keys, grants and non-example controller secrets',()=>{
41
41
  const files=packFiles();
42
- const forbidden=files.filter(rel=>/(^|\/)(active-release\.json|runtime\/|audit\/|evidence\/)|\.pem$|(^|\/)deadbyte-controller\.config\.psd1$|(^|\/)deadbyte-host-policy\.json$|(^|\/)[^/]*(?:grant|arm)\.json$/i.test(rel));
42
+ const forbidden=files.filter(rel=>rel.startsWith('tmp/')||rel.startsWith('.deadbyte-machine-fs-recovery/')||/(^|\/)(active-release\.json|runtime\/|audit\/|evidence\/)|\.pem$|(^|\/)deadbyte-controller\.config\.psd1$|(^|\/)deadbyte-host-policy\.json$|(^|\/)[^/]*(?:grant|arm)\.json$/i.test(rel));
43
43
  assert.deepEqual(forbidden,[]);
44
44
  });
@@ -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\.3 mcp/);
12
+ assert.match(text,/npx -y deadbyte-mcp@0\.15\.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\.3"[\s\S]*?"mcp"/);
14
+ assert.match(text,/"mcpServers"[\s\S]*?"command"\s*:\s*"npx"[\s\S]*?"-y"[\s\S]*?"deadbyte-mcp@0\.15\.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\.3",\s*"mcp"\]/);
23
+ assert.match(text,/args\s*=\s*\["-y",\s*"deadbyte-mcp@0\.15\.1",\s*"mcp"\]/);
24
24
  });
25
25
 
26
26
  test('production README records tracer bullet, semantic scope, remote UX, safety and document extension',async()=>{
@@ -86,23 +86,24 @@ 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 current R44 gate emits signed-R43-parent feature evidence outside the candidate tree', async()=>{
90
- const stateRoot=await temp('deadbyte-r44-windows-evidence-');
91
- try{
92
- const gate=await readFile(path.join(root,'scripts','gate-windows-r44.ps1'),'utf8');
93
- assert.match(gate,/windows-gate-evidence-r44\.mjs/);assert.match(gate,/r44-parent-verify/);
94
- const manifestSha=sha256(await readFile(path.join(root,'MANIFEST.SHA256')));
95
- const {writeWindowsGateEvidence}=await import('../scripts/windows-gate-evidence-r44.mjs');
96
- const summary=await writeWindowsGateEvidence({candidateRoot:root,stateRoot,clock:()=>new Date('2026-09-21T00:01:00.000Z')});
97
- const evidence=JSON.parse(await readFile(summary.path,'utf8'));
98
- assert.equal(evidence.schema,'deadbyte.r44-windows-gate.v1');assert.equal(evidence.version,'0.15.0');
99
- assert.equal(evidence.manifest_sha256,manifestSha);
100
- assert.equal(evidence.marker,'DEADBYTE V0.15.0 / R44 REMOTE AGENT SKILL WINDOWS BATCH GATE: PASS');
101
- assert.equal(evidence.parent.release_id,'v0.14.1-0a5a833892593283');
102
- assert.equal(evidence.parent.final_closure_sha256,'2f29e94dd726638c23b2e520a608dcf2a6919e43348855be3940599d557f920b');
103
- for(const key of ['skill_integrity','agent_backend_persistence','codex_protocol_contract','remote_device_identity','durable_job_supervisor','real_external_supervisor_smoke','full_regression_required']) assert.equal(evidence.features[key],true,key);
104
- assert.ok(summary.path.startsWith(path.join(stateRoot,'evidence','release')));
105
- const historical=await readFile(path.join(root,'scripts','windows-gate-evidence-r43.mjs'),'utf8');
106
- assert.match(historical,/version:'0\.14\.1'/);assert.match(historical,/deadbyte\.r43-windows-gate\.v1/);
107
- }finally{await rm(stateRoot,{recursive:true,force:true});}
89
+ test('Windows current R45 gate binds exact sealed R44 parent and machine-freedom evidence contract', async()=>{
90
+ const gate=await readFile(path.join(root,'scripts','gate-windows-r45.ps1'),'utf8');
91
+ const evidenceSource=await readFile(path.join(root,'scripts','windows-gate-evidence-r45.mjs'),'utf8');
92
+ const parent=JSON.parse(await readFile(path.join(root,'R45-PARENT.json'),'utf8'));
93
+ assert.match(gate,/windows-gate-evidence-r45\.mjs/);
94
+ assert.match(gate,/r45-parent-verify/);
95
+ assert.match(gate,/host-policy-refresh/);
96
+ assert.match(gate,/hardware-build/);
97
+ assert.match(gate,/doctor/);
98
+ assert.match(evidenceSource,/deadbyte\.r45-windows-gate\.v1/);
99
+ assert.match(evidenceSource,/version:'0\.15\.1'/);
100
+ assert.match(evidenceSource,/DEADBYTE V0\.15\.1 \/ R45 MACHINE FREEDOM WINDOWS BATCH GATE: PASS/);
101
+ for(const key of ['host_inline_native','native_hardware_observation','doctor_release_truth']) assert.match(evidenceSource,new RegExp(key+':true'));
102
+ assert.equal(parent.parent_release_id,'v0.15.0-c15fa41719be61b3');
103
+ assert.equal(parent.parent_manifest_sha256,'c15fa41719be61b3186e49b2367a5f4c057365cfb465102dbefb7d7355f45483');
104
+ assert.equal(parent.parent_generation_manifest_sha256,'6d7429c050b7fe893492e102f00282019116e0c9e54e4f25a5791defa1661d30');
105
+ assert.equal(parent.parent_final_closure_sha256,'533b7e0ff9ded04086dd90ed34e3b87bc427acc3c55c25bb9f4ec66cb448e667');
106
+ const historical=await readFile(path.join(root,'scripts','windows-gate-evidence-r44.mjs'),'utf8');
107
+ assert.match(historical,/version:'0\.15\.0'/);
108
+ assert.match(historical,/deadbyte\.r44-windows-gate\.v1/);
108
109
  });