deadbyte-mcp 0.9.0 → 0.11.0

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 (136) hide show
  1. package/MANIFEST.SHA256 +134 -92
  2. package/README.txt +19 -15
  3. package/bench/fixtures/corpus.json +32 -13
  4. package/bench/fixtures/r36/case-map.json +8 -0
  5. package/bin/WORKER-REGISTRY.txt +3 -3
  6. package/bin/appcontainer-stage.exe +0 -0
  7. package/bin/appcontainer-stage.obj +0 -0
  8. package/bin/bootstrap-advapi32.exe +0 -0
  9. package/bin/bootstrap-advapi32.obj +0 -0
  10. package/bin/bootstrap-exitcode.exe +0 -0
  11. package/bin/bootstrap-exitcode.obj +0 -0
  12. package/bin/bootstrap-kernel32.exe +0 -0
  13. package/bin/bootstrap-kernel32.obj +0 -0
  14. package/bin/child-control-probe.exe +0 -0
  15. package/bin/child-control-probe.obj +0 -0
  16. package/bin/child-control-stage.exe +0 -0
  17. package/bin/child-control-stage.obj +0 -0
  18. package/bin/contained-reverse-worker.exe +0 -0
  19. package/bin/contained-reverse-worker.obj +0 -0
  20. package/bin/contained-transform-worker.exe +0 -0
  21. package/bin/contained-transform-worker.obj +0 -0
  22. package/bin/containment-probe.exe +0 -0
  23. package/bin/containment-probe.obj +0 -0
  24. package/bin/deadbyte-contain.exe +0 -0
  25. package/bin/deadbyte-contain.obj +0 -0
  26. package/bin/deadbyte-exec.exe +0 -0
  27. package/bin/deadbyte-exec.obj +0 -0
  28. package/bin/deadbyte-process-host.exe +0 -0
  29. package/bin/deadbyte-process-host.obj +0 -0
  30. package/bin/deadbyte-tunnel-host.exe +0 -0
  31. package/bin/deadbyte-tunnel-host.obj +0 -0
  32. package/controller/README.TXT +8 -6
  33. package/controller/deadbyte-controller.ps1 +48 -2
  34. package/controller/deadbyte-process-policy.json +5 -5
  35. package/docs/ARCHITECTURE.md +1 -1
  36. package/docs/R36-CAPABILITY-EVIDENCE.md +43 -0
  37. package/docs/superpowers/plans/2026-09-18-r36-zero-loss-autonomy.md +739 -0
  38. package/docs/superpowers/specs/2026-09-18-r36-zero-loss-autonomy-design.md +640 -0
  39. package/package.json +1 -1
  40. package/proof/CONTAINMENT-BUILD.txt +6 -6
  41. package/scripts/deferred-slot-operation.mjs +53 -15
  42. package/scripts/final-closure-r36.mjs +113 -0
  43. package/scripts/final-closure-verify-r36.mjs +208 -0
  44. package/scripts/final-closure-verify.mjs +88 -39
  45. package/scripts/final-closure.mjs +63 -56
  46. package/scripts/gate-windows-r36.ps1 +42 -0
  47. package/scripts/gate-windows.ps1 +3 -3
  48. package/scripts/release-parity-r36.mjs +200 -0
  49. package/scripts/release-parity-tests.ps1 +9 -0
  50. package/scripts/release-parity.mjs +149 -139
  51. package/scripts/windows-gate-evidence-r36.mjs +52 -0
  52. package/scripts/windows-gate-evidence.mjs +5 -5
  53. package/src/agent-memory-plane.mjs +98 -0
  54. package/src/autonomous-context-engine.mjs +2 -1
  55. package/src/autonomous-mcp-tools.mjs +5 -1
  56. package/src/autonomous-output-contracts.mjs +9 -6
  57. package/src/autonomous-planner-contracts.mjs +36 -1
  58. package/src/autonomous-planner.mjs +25 -3
  59. package/src/autonomous-runtime.mjs +337 -43
  60. package/src/autonomous-timeout-recovery.mjs +27 -0
  61. package/src/capability-benchmark-runner.mjs +86 -1
  62. package/src/capability-benchmark.mjs +45 -0
  63. package/src/capability-ledger.mjs +158 -0
  64. package/src/coding-mcp-tools.mjs +31 -17
  65. package/src/coding-output-contracts.mjs +48 -10
  66. package/src/coding-plane.mjs +45 -9
  67. package/src/coding-search.mjs +130 -47
  68. package/src/compact-gateway-mcp-tools.mjs +128 -0
  69. package/src/compact-gateway-output-contracts.mjs +16 -0
  70. package/src/deadbyte-cli.mjs +62 -78
  71. package/src/effect-ledger.mjs +47 -0
  72. package/src/machine-fs-smoke-client.mjs +1 -1
  73. package/src/machine-fs.mjs +51 -8
  74. package/src/mcp-server.mjs +32 -9
  75. package/src/native-diff-v2.mjs +337 -0
  76. package/src/native-diff.mjs +50 -2
  77. package/src/observation-lease.mjs +32 -0
  78. package/src/observation-smoke-client.mjs +1 -1
  79. package/src/operator-surface.mjs +7 -1
  80. package/src/process-runtime.mjs +98 -11
  81. package/src/process-smoke-client.mjs +11 -3
  82. package/src/r36-compact-disarmed-probe.mjs +50 -0
  83. package/src/r36-full-surface-probe.mjs +56 -0
  84. package/src/remote-live-log.mjs +135 -0
  85. package/src/remote-mcp-autonomous-smoke-client.mjs +22 -12
  86. package/src/remote-mcp-coding-smoke-client.mjs +1 -1
  87. package/src/remote-mcp-r36-parity-client.mjs +175 -0
  88. package/src/remote-mcp-smoke-client.mjs +112 -56
  89. package/src/runtime-update.mjs +51 -1
  90. package/src/search-cursor.mjs +45 -0
  91. package/src/semantic-code.mjs +72 -5
  92. package/src/semantic-lsp-backend.mjs +39 -3
  93. package/src/version.mjs +1 -1
  94. package/src/worker-scheduler.mjs +53 -0
  95. package/test/autonomous-capability-r36.test.mjs +151 -0
  96. package/test/autonomous-output-contract.test.mjs +1 -1
  97. package/test/autonomous-runtime.test.mjs +2 -2
  98. package/test/capability-benchmark-r36.test.mjs +107 -0
  99. package/test/capability-benchmark-semantic-r36.test.mjs +52 -0
  100. package/test/capability-claims-r36.test.mjs +23 -0
  101. package/test/capability-ledger-r36.test.mjs +102 -0
  102. package/test/coding-catalog-consistency.test.mjs +2 -2
  103. package/test/coding-plane.test.mjs +2 -2
  104. package/test/coding-runtime.test.mjs +16 -0
  105. package/test/coding-search-r36.test.mjs +90 -0
  106. package/test/compact-catalog-r36.test.mjs +37 -0
  107. package/test/compact-gateway-r36.test.mjs +66 -0
  108. package/test/contained.test.mjs +1 -1
  109. package/test/core.test.mjs +1 -1
  110. package/test/deferred-slot-operation.test.mjs +9 -0
  111. package/test/fixtures/lsp-framed-server.mjs +2 -0
  112. package/test/helpers/autonomous-r34-fixture.mjs +5 -3
  113. package/test/multi-file-read.test.mjs +3 -0
  114. package/test/native-diff-topology-r36.test.mjs +105 -0
  115. package/test/package-boundary.test.mjs +6 -0
  116. package/test/process-longrun-r36.test.mjs +82 -0
  117. package/test/process-release-gate.test.mjs +9 -0
  118. package/test/production-docs.test.mjs +5 -5
  119. package/test/prompts-resources.test.mjs +7 -1
  120. package/test/r33-closeout-regression.test.mjs +4 -3
  121. package/test/r33-finalization.test.mjs +14 -9
  122. package/test/r36-finalization.test.mjs +104 -0
  123. package/test/r36-release-identity.test.mjs +45 -0
  124. package/test/r37-agent-fabric.test.mjs +92 -0
  125. package/test/r37-autonomous-timeout-recovery.test.mjs +60 -0
  126. package/test/r37-finalization.test.mjs +74 -0
  127. package/test/release-version.test.mjs +42 -33
  128. package/test/remote-live-log-r36.test.mjs +37 -0
  129. package/test/remote-live-log-r37.test.mjs +47 -0
  130. package/test/remote-live-log-recovery-r36.test.mjs +41 -0
  131. package/test/remote-r24-catalog.test.mjs +13 -0
  132. package/test/remote-session-cli.test.mjs +53 -66
  133. package/test/runtime-self-update.test.mjs +58 -1
  134. package/test/semantic-lsp-backend.test.mjs +9 -0
  135. package/test/semantic-r36-rename.test.mjs +82 -0
  136. package/deadbyte-mcp-0.8.9.tgz +0 -0
@@ -0,0 +1,82 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { createHash } from 'node:crypto';
4
+ import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { PROCESS_GRANT_SCHEMA, PROCESS_POLICY_SCHEMA, loadProcessPolicy } from '../src/process-policy.mjs';
9
+ import { createProcessRuntime } from '../src/process-runtime.mjs';
10
+ import { generateTrustKeypair } from '../src/trust.mjs';
11
+
12
+ const repo=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
13
+ const host=path.join(repo,'bin','deadbyte-process-host.exe');
14
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
15
+ const sleep=ms=>new Promise(resolve=>setTimeout(resolve,ms));
16
+
17
+ async function fixture(){
18
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r36-longrun-'));
19
+ const project=path.join(root,'project'); const trust=path.join(root,'trust');
20
+ await mkdir(project); await mkdir(trust);
21
+ const script=path.join(project,'longrun.mjs');
22
+ await writeFile(script,`process.stdout.write('chunk-1\\n');\nsetTimeout(()=>process.stdout.write('chunk-2\\n'),180);\nsetTimeout(()=>process.stdout.write('chunk-3\\n'),360);\nsetTimeout(()=>process.exit(0),540);\n`);
23
+ const grantFile=path.join(root,'process-grant.json'); const stateDir=path.join(root,'state'); const policyPath=path.join(root,'process-policy.json');
24
+ const raw={schema:PROCESS_POLICY_SCHEMA,enabled:true,grant_file:grantFile,state_dir:stateDir,native_host:{path:host,sha256:sha(await readFile(host))},roots:{core:{path:project,deny_paths:[]}},profiles:{longrun:{executable:process.execPath,executable_sha256:sha(await readFile(process.execPath)),root_ids:['core'],transport:'pipe',prefix_args:[script],max_args:0,max_arg_bytes:256,max_sessions:1,max_input_bytes:4096,max_retained_output_bytes:65536,env_allow:['PATH','TEMP','TMP'],input_actions:{}}}};
25
+ await writeFile(policyPath,JSON.stringify(raw));
26
+ const policy=await loadProcessPolicy(policyPath);
27
+ await writeFile(grantFile,JSON.stringify({schema:PROCESS_GRANT_SCHEMA,policy_sha256:policy.policy_sha256,instance_nonce:'6'.repeat(64),profile_ids:['longrun'],root_ids:['core'],granted_at_utc:new Date().toISOString()}));
28
+ const keys=await generateTrustKeypair({privateKeyPath:path.join(trust,'private.pem'),publicKeyPath:path.join(trust,'public.pem')});
29
+ const make=()=>createProcessRuntime({policy,signingKeyPath:keys.privateKeyPath,verifyKeyPath:keys.publicKeyPath});
30
+ return {root,project,stateDir,policy,keys,make,runtime:make()};
31
+ }
32
+
33
+ async function waitState(runtime,id,state,timeout=5000){const end=Date.now()+timeout;while(Date.now()<end){const s=await runtime.status({sessionId:id});if(s.state===state)return s;await sleep(30);}throw new Error(`timeout waiting ${state}`);}
34
+
35
+ test('R36 process runtime publishes terminal state only after durable terminal journal commit', async()=>{
36
+ const source=await readFile(path.join(repo,'src','process-runtime.mjs'),'utf8');
37
+ assert.match(source,/const terminalState = session\.terminate_requested \? 'terminated' : 'exited'/);
38
+ const commit=source.indexOf("await appendEvent(runtime, session, terminalState");
39
+ const publish=source.indexOf('session.state = terminalState;',commit);
40
+ assert.ok(commit>=0&&publish>commit,'terminal state must publish after terminal event commit');
41
+ });
42
+
43
+ test('R36 long process returns before exit and exposes monotonic cursor chunks', {skip:process.platform!=='win32'}, async()=>{
44
+ const f=await fixture(); try{
45
+ const startedAt=Date.now();
46
+ const started=await f.runtime.start({profileId:'longrun',rootId:'core',cwd:'.',args:[]});
47
+ assert.equal(started.state,'running');
48
+ assert.ok(Date.now()-startedAt<500,'start waited for child exit');
49
+ let offset=0; let text=''; let sawPartial=false;
50
+ const end=Date.now()+5000;
51
+ while(Date.now()<end){
52
+ const page=await f.runtime.read({sessionId:started.session_id,offset,maxBytes:8});
53
+ assert.ok(page.next_offset>=offset); assert.ok(page.next_offset<=page.stream_head);
54
+ if(page.next_offset<page.stream_head||page.state==='running') sawPartial=true;
55
+ text+=Buffer.from(page.data_base64,'base64').toString('utf8'); offset=page.next_offset;
56
+ if(page.state==='exited'&&offset===page.stream_head) break;
57
+ await sleep(35);
58
+ }
59
+ assert.equal(sawPartial,true); assert.match(text,/chunk-1/); assert.match(text,/chunk-2/); assert.match(text,/chunk-3/);
60
+ const terminal=await waitState(f.runtime,started.session_id,'exited'); assert.equal(terminal.exit_code,0);
61
+ await assert.rejects(()=>f.runtime.status({sessionId:'f'.repeat(64)}),/unknown process session/i);
62
+ } finally {await rm(f.root,{recursive:true,force:true});}
63
+ });
64
+
65
+ test('R36 terminal process session is recovered from signed journal after wrapper restart', {skip:process.platform!=='win32'}, async()=>{
66
+ const f=await fixture(); try{
67
+ const started=await f.runtime.start({profileId:'longrun',rootId:'core',cwd:'.',args:[]});
68
+ await waitState(f.runtime,started.session_id,'exited');
69
+ const original=await f.runtime.status({sessionId:started.session_id});
70
+ const checked=await f.runtime.verifyEventJournal({sessionId:started.session_id}); assert.equal(checked.ok,true);
71
+ const restarted=f.make();
72
+ const recovered=await restarted.status({sessionId:started.session_id});
73
+ assert.equal(recovered.state,'exited'); assert.equal(recovered.exit_code,0); assert.equal(recovered.session_id,started.session_id);
74
+ assert.equal(recovered.journal_head_sha256,original.journal_head_sha256);
75
+ const listed=await restarted.list(); assert.ok(listed.sessions.some(s=>s.session_id===started.session_id));
76
+ const page=await restarted.read({sessionId:started.session_id,offset:0,maxBytes:65536});
77
+ const text=Buffer.from(page.data_base64,'base64').toString('utf8');
78
+ assert.match(text,/chunk-1/); assert.match(text,/chunk-3/); assert.equal(page.state,'exited');
79
+ const verified=await restarted.verifyEventJournal({sessionId:started.session_id}); assert.equal(verified.ok,true); assert.equal(verified.head_sha256,recovered.journal_head_sha256);
80
+ await assert.rejects(()=>restarted.status({sessionId:'e'.repeat(64)}),/unknown process session/i);
81
+ } finally {await rm(f.root,{recursive:true,force:true});}
82
+ });
@@ -5,12 +5,21 @@ import { fileURLToPath } from 'node:url';
5
5
 
6
6
  const packagePath = fileURLToPath(new URL('../package.json', import.meta.url));
7
7
  const gatePath = fileURLToPath(new URL('../scripts/gate-windows.ps1', import.meta.url));
8
+ const processSmokePath = fileURLToPath(new URL('../src/process-smoke-client.mjs', import.meta.url));
8
9
 
9
10
  test('R31 package exposes the bounded process smoke command', async () => {
10
11
  const pkg = JSON.parse(await readFile(packagePath, 'utf8'));
11
12
  assert.equal(pkg.scripts['mcp:process:smoke'], 'node src/process-smoke-client.mjs');
12
13
  });
13
14
 
15
+ test('R36 process smoke isolates grant and recovery state outside the release source tree', async () => {
16
+ const source = await readFile(processSmokePath, 'utf8');
17
+ assert.match(source, /smoke-policy\.json/);
18
+ assert.match(source, /grant_file:\s*path\.join\(smokeTrust,\s*'process-grant\.json'\)/);
19
+ assert.match(source, /state_dir:\s*path\.join\(smokeTrust,\s*'process-state'\)/);
20
+ assert.match(source, /DEADBYTE_PROCESS_POLICY:\s*smokePolicyPath/);
21
+ });
22
+
14
23
  test('R31 Windows gate refreshes the native-host policy pin before manifest freeze', async () => {
15
24
  const pkg = JSON.parse(await readFile(packagePath, 'utf8'));
16
25
  const source = await readFile(gatePath, 'utf8');
@@ -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\.9\.0 mcp/);
12
+ assert.match(text,/npx -y deadbyte-mcp@0\.11\.0 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\.9\.0"[\s\S]*?"mcp"/);
14
+ assert.match(text,/"mcpServers"[\s\S]*?"command"\s*:\s*"npx"[\s\S]*?"-y"[\s\S]*?"deadbyte-mcp@0\.11\.0"[\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\.9\.0",\s*"mcp"\]/);
23
+ assert.match(text,/args\s*=\s*\["-y",\s*"deadbyte-mcp@0\.11\.0",\s*"mcp"\]/);
24
24
  });
25
25
 
26
26
  test('production README records tracer bullet, semantic scope, remote UX, safety and document extension',async()=>{
@@ -29,8 +29,8 @@ test('production README records tracer bullet, semantic scope, remote UX, safety
29
29
  for(const token of ['coding_files_read','coding_symbol_outline','coding_symbol_definition','coding_symbol_references','coding_symbol_replace']) assert.match(text,new RegExp(token));
30
30
  assert.match(text,/JavaScript\/TypeScript|JS\/TS/);
31
31
  assert.match(text,/does not claim|not claim|limited to/i);
32
- assert.match(text,/remote --verbose/);
33
- assert.match(text,/compact/i);
32
+ assert.doesNotMatch(text,/remote --verbose/);
33
+ assert.match(text,/unified live timeline/i);
34
34
  assert.match(text,/workspace allowlist|coding-policy root/i);
35
35
  assert.match(text,/destructive|standing grant|authority plane/i);
36
36
  assert.match(text,/document adapter/i);
@@ -24,7 +24,13 @@ test('MCP exposes compact workflow prompts and source-of-truth context resources
24
24
 
25
25
  const resources=await client.listResources();
26
26
  const uris=resources.resources.map(r=>r.uri).sort();
27
- assert.deepEqual(uris,['deadbyte://architecture','deadbyte://context']);
27
+ assert.deepEqual(uris,['deadbyte://architecture','deadbyte://context','deadbyte://surface-profile']);
28
+ const surface=await client.readResource({uri:'deadbyte://surface-profile'});
29
+ const surfaceText=surface.contents.map(c=>'text' in c?c.text:'').join('\n');
30
+ const surfaceState=JSON.parse(surfaceText);
31
+ assert.equal(surfaceState.schema,'deadbyte.surface-profile.v1');
32
+ assert.equal(surfaceState.profile,'full');
33
+ assert.equal(surfaceState.compact_tool_limit,42);
28
34
  const context=await client.readResource({uri:'deadbyte://context'});
29
35
  const contextText=context.contents.map(c=>'text' in c?c.text:'').join('\n');
30
36
  assert.match(contextText,/Machine truth/i); assert.match(contextText,/Authority plane/i); assert.match(contextText,/Loop Supervisor/i);
@@ -86,7 +86,7 @@ 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 R35 gate emits manifest-bound machine-readable evidence outside the candidate tree', async()=>{
89
+ test('Windows R37 gate emits manifest-bound machine-readable evidence outside the candidate tree', async()=>{
90
90
  const stateRoot=await temp('deadbyte-r33-windows-evidence-');
91
91
  try{
92
92
  const gate=await readFile(path.join(root,'scripts','gate-windows.ps1'),'utf8');
@@ -99,11 +99,12 @@ test('Windows R35 gate emits manifest-bound machine-readable evidence outside th
99
99
  assert.equal(summary.status,'written');
100
100
  const evidence=JSON.parse(await readFile(summary.path,'utf8'));
101
101
  const manifestSha=sha256(await readFile(path.join(root,'MANIFEST.SHA256')));
102
- assert.equal(evidence.schema,'deadbyte.r35-windows-gate.v1');
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
106
  assert.equal(evidence.manifest_sha256,manifestSha);
106
- assert.equal(evidence.marker,'DEADBYTE V0.9.0 / R35 WINDOWS BATCH GATE: PASS');
107
+ assert.equal(evidence.marker,'DEADBYTE V0.11.0 / R37 WINDOWS BATCH GATE: PASS');
107
108
  assert.ok(summary.path.startsWith(path.join(stateRoot,'evidence','release')));
108
109
  }finally{await rm(stateRoot,{recursive:true,force:true});}
109
110
  });
@@ -26,16 +26,17 @@ test('release parity and final verifier are package entry points', async () => {
26
26
  assert.equal(typeof verifyFinalClosureObject, 'function');
27
27
  });
28
28
 
29
- test('final closure verifier is implementation-independent from production helpers', async () => {
29
+ test('R37 final closure verifier is implementation-independent from production helpers', async () => {
30
30
  const verifier = await text('scripts/final-closure-verify.mjs');
31
31
  const writer = await text('scripts/final-closure.mjs');
32
32
  assert.doesNotMatch(verifier, /from ['"]\.\.\/src\//);
33
33
  assert.match(verifier, /DEADBYTE-R27-SLOT-UPDATE-V1/);
34
34
  assert.match(verifier, /DEADBYTE-MACHINE-PING-V1/);
35
- assert.match(verifier, /DEADBYTE-R35-FINAL-CLOSURE-V1/);
36
- assert.match(writer, /pointer\.version==='0\.9\.0'/);
37
- assert.match(verifier, /envelope\.body\.version==='0\.9\.0'/);
38
- assert.match(verifier, /release_label==='R35 FINAL MACHINE BASELINE'/);
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'/);
38
+ assert.match(verifier, /release_label==='R37 FINAL MACHINE BASELINE'/);
39
+ assert.match(verifier, /8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8/);
39
40
  });
40
41
 
41
42
  test('final closure verifier canonicalizes traversal order before exact-tree comparison', async () => {
@@ -44,11 +45,15 @@ test('final closure verifier canonicalizes traversal order before exact-tree com
44
45
  assert.match(verifier, /const expected=\[\.\.\.entries\.keys\(\)\]\.sort\(\(a,b\)=>a\.localeCompare\(b,'en'\)\);/);
45
46
  });
46
47
 
47
- test('autonomous live gate reuses the canonical R34 73-tool catalog', async () => {
48
+ test('R36 autonomous live gate binds the compact gateway contract instead of the historical 73-tool public catalog', async () => {
48
49
  const autonomous = await text('src/remote-mcp-autonomous-smoke-client.mjs');
49
- assert.match(autonomous, /import \{ R34_EXPECTED_TOOLS \} from '\.\/remote-mcp-r34-parity-client\.mjs';/);
50
- assert.doesNotMatch(autonomous, /const expectedTools\s*=\s*\[/);
51
- assert.match(autonomous, /JSON\.stringify\(names\) !== JSON\.stringify\(R34_EXPECTED_TOOLS\)/);
50
+ assert.match(autonomous, /R36_COMPACT_GATEWAYS/);
51
+ assert.match(autonomous, /R36_COMPACT_TOOL_LIMIT/);
52
+ assert.match(autonomous, /names\.length > R36_COMPACT_TOOL_LIMIT/);
53
+ for (const name of ['autonomous_goal_submit','autonomous_goal_run','autonomous_goal_verify','autonomous_release_gate','native_diff_apply','native_diff_verify']) {
54
+ assert.match(autonomous,new RegExp(name));
55
+ }
56
+ assert.doesNotMatch(autonomous, /R34_EXPECTED_TOOLS/);
52
57
  });
53
58
 
54
59
  test('R34 parity proves coding package tests before package-visible scratch mutation', async () => {
@@ -0,0 +1,104 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { readFile } from 'node:fs/promises';
4
+ import { validateParityEvidence, R35_PREDECESSOR_RELEASE_ID, R35_PREDECESSOR_MANIFEST } from '../scripts/release-parity-r36.mjs';
5
+ import { verifyFinalClosureObject } from '../scripts/final-closure-verify-r36.mjs';
6
+
7
+ const root=new URL('../',import.meta.url);
8
+ const text=rel=>readFile(new URL(rel,root),'utf8');
9
+
10
+ function parityFixture(){
11
+ const manifest='a'.repeat(64);
12
+ return {
13
+ schema:'deadbyte.r36-parity.v1',status:'passed',execution_provider:'deadbyte_mcp',rdc_operation_count:0,
14
+ candidate:{release_id:`v0.10.0-${manifest.slice(0,16)}`,version:'0.10.0',manifest_sha256:manifest},
15
+ immutable_slot:{protected:true,release_root:'C:/immutable/r36',development_root:'D:/Projects/deadbyte-mcp-r36-dev'},
16
+ local_full:{status:'passed',tool_count:76,strict_output_schemas:true},
17
+ public_compact:{status:'passed',tool_count:41,capability_closure:true,gateway_count:5},
18
+ autonomous:{status:'passed',signed_release_verified:true,observed_failure_before_replan:true},
19
+ before_rollback_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false},
20
+ rollback:{state:'completed'},stage_restore:{status:'restored',manifest_sha256:manifest},restore:{state:'completed'},
21
+ predecessor:{release_id:R35_PREDECESSOR_RELEASE_ID,version:'0.9.0',manifest_sha256:R35_PREDECESSOR_MANIFEST},
22
+ predecessor_disarmed:{status:'passed',tool_count:73},
23
+ successor:{release_id:`v0.10.0-${manifest.slice(0,16)}`,version:'0.10.0',manifest_sha256:manifest},
24
+ successor_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false},
25
+ requirements:Object.fromEntries(['tree_read','precondition_mutation','search','owned_process','observation','coding_loop','autonomy','interrupted_recovery','evidence_verification','compact_closure','full_surface'].map(key=>[key,true]))
26
+ };
27
+ }
28
+
29
+ test('R36 parity validator requires full-76, compact closure, exact R35 predecessor and immutable-slot separation',()=>{
30
+ const good=parityFixture();
31
+ assert.equal(validateParityEvidence(good),true);
32
+ assert.throws(()=>validateParityEvidence({...good,local_full:{...good.local_full,tool_count:75}}),/full 76/i);
33
+ assert.throws(()=>validateParityEvidence({...good,public_compact:{...good.public_compact,capability_closure:false}}),/compact closure/i);
34
+ assert.throws(()=>validateParityEvidence({...good,predecessor:{...good.predecessor,manifest_sha256:'b'.repeat(64)}}),/predecessor/i);
35
+ assert.throws(()=>validateParityEvidence({...good,immutable_slot:{...good.immutable_slot,development_root:good.immutable_slot.release_root}}),/immutable-slot/i);
36
+ assert.throws(()=>validateParityEvidence({...good,stage_restore:{status:'missing',manifest_sha256:good.candidate.manifest_sha256}}),/stage restore/i);
37
+ });
38
+
39
+ test('R36 compact disarmed probe carries signed machine status/ping evidence into closure',async()=>{
40
+ const probe=await text('src/r36-compact-disarmed-probe.mjs');
41
+ assert.match(probe,/op:'machine_ping'/);
42
+ assert.match(probe,/machine_status/);
43
+ assert.match(probe,/machine_ping/);
44
+ assert.match(probe,/nonce/);
45
+ });
46
+
47
+ test('R36 parity captures exact successor bridge before rollback and reuses it for restore',async()=>{
48
+ const parity=await text('scripts/release-parity-r36.mjs');
49
+ assert.match(parity,/loadPowerShellDataFile/);
50
+ assert.match(parity,/successorBridge/);
51
+ assert.match(parity,/Bridge\?\.WorkingDirectory/);
52
+ assert.match(parity,/Bridge\?\.ScriptSha256/);
53
+ assert.match(parity,/const stageRestore=await restoreFrozenStage\(\{developmentRoot,releaseRoot:active\.release_root,expectedManifestSha256:candidateManifest\}\)/);
54
+ assert.match(parity,/scheduleDeferred\('activate',candidateManifest,\{bridgeRoot:successorBridge\.root,bridgeScriptSha256:successorBridge\.sha256\}\)/);
55
+ });
56
+
57
+ test('R36 compact parity uses bounded release-parity tests instead of the full npm suite',async()=>{
58
+ const parity=await text('src/remote-mcp-r36-parity-client.mjs');
59
+ assert.match(parity,/const testScript='scripts\/release-parity-tests\.ps1'/);
60
+ assert.doesNotMatch(parity,/const testScript='scripts\/autonomous-tests\.ps1'/);
61
+ const script=await text('scripts/release-parity-tests.ps1');
62
+ assert.match(script,/r36-finalization\.test\.mjs/);
63
+ assert.match(script,/r36-release-identity\.test\.mjs/);
64
+ assert.match(script,/deferred-slot-operation\.test\.mjs/);
65
+ });
66
+
67
+ test('R36 compact parity treats stale machine-fs precondition denial as expected evidence',async()=>{
68
+ const parity=await text('src/remote-mcp-r36-parity-client.mjs');
69
+ assert.match(parity,/const staleValue=stale\.structuredContent/);
70
+ assert.match(parity,/stale\.isError!==true\|\|staleValue\.status!=='denied'/);
71
+ assert.doesNotMatch(parity,/structured\(stale,'machine_fs stale'\)/);
72
+ });
73
+
74
+ test('R36 final closure writer binds compact public evidence and R36 release evidence domains',async()=>{
75
+ const writer=await text('scripts/final-closure-r36.mjs');
76
+ assert.match(writer,/DEADBYTE-R36-FINAL-CLOSURE-V1/);
77
+ assert.match(writer,/deadbyte\.r36-final-closure\.v1/);
78
+ assert.match(writer,/pointer\.version==='0\.10\.0'/);
79
+ assert.match(writer,/release_label:'R36 FINAL MACHINE BASELINE'/);
80
+ assert.match(writer,/deadbyte\.r36-parity\.v1/);
81
+ assert.match(writer,/deadbyte\.r36-windows-gate\.v1/);
82
+ assert.match(writer,/tool_count.*76|local_full[\s\S]*76/);
83
+ assert.match(writer,/capability_closure/);
84
+ assert.match(writer,/R35_PREDECESSOR_RELEASE_ID|v0\.9\.0-b95e1ec1d9a7e26a/);
85
+ assert.match(writer,/development_root/);
86
+ });
87
+
88
+ test('R36 independent closure verifier binds full, compact, predecessor, restore, Windows gate and immutable slot',async()=>{
89
+ const verifier=await text('scripts/final-closure-verify-r36.mjs');
90
+ assert.equal(typeof verifyFinalClosureObject,'function');
91
+ assert.doesNotMatch(verifier,/from ['"]\.\.\/src\//);
92
+ assert.match(verifier,/DEADBYTE-R36-FINAL-CLOSURE-V1/);
93
+ assert.match(verifier,/deadbyte\.r36-final-closure\.v1/);
94
+ assert.match(verifier,/envelope\.body\.version==='0\.10\.0'/);
95
+ assert.match(verifier,/R36 FINAL MACHINE BASELINE/);
96
+ assert.match(verifier,/deadbyte\.r36-parity\.v1/);
97
+ assert.match(verifier,/deadbyte\.r36-windows-gate\.v1/);
98
+ assert.match(verifier,/76/);
99
+ assert.match(verifier,/42/);
100
+ assert.match(verifier,/b95e1ec1d9a7e26a96ef492306c1be4df18c883ff03ab3b6015f677d7429ec8d/);
101
+ assert.match(verifier,/development_root/);
102
+ assert.match(verifier,/release_root/);
103
+ assert.match(verifier,/successor_disarmed/);
104
+ });
@@ -0,0 +1,45 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { readFile } from 'node:fs/promises';
4
+
5
+ const root=new URL('../',import.meta.url);
6
+ const text=rel=>readFile(new URL(rel,root),'utf8');
7
+ const R35_RELEASE_ID='v0.9.0-b95e1ec1d9a7e26a';
8
+ const R35_MANIFEST='b95e1ec1d9a7e26a96ef492306c1be4df18c883ff03ab3b6015f677d7429ec8d';
9
+ const R36_RELEASE_ID='v0.10.0-8d1e5f09745e7647';
10
+ const R36_MANIFEST='8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8';
11
+
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([
14
+ text('scripts/gate-windows-r36.ps1'),text('scripts/release-parity-r36.mjs'),
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')
17
+ ]);
18
+ assert.match(gate,/DEADBYTE V0\.10\.0 \/ R36 WINDOWS BATCH GATE: PASS/);
19
+ assert.match(parity,/deadbyte\.r36-parity\.v1/);
20
+ assert.match(parity,new RegExp(R35_RELEASE_ID.replaceAll('.','\\.')));
21
+ assert.match(parity,new RegExp(R35_MANIFEST));
22
+ assert.match(closure,/DEADBYTE-R36-FINAL-CLOSURE-V1/);
23
+ assert.match(closure,/version:'0\.10\.0'/);
24
+ assert.match(closureVerify,/DEADBYTE-R36-FINAL-CLOSURE-V1/);
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));
28
+ });
29
+
30
+ test('current R37 controller still binds production remote to compact profile and restores parent environment',async()=>{
31
+ const controller=await text('controller/deadbyte-controller.ps1');
32
+ assert.match(controller,/Test-Path Env:DEADBYTE_CAPABILITY_PROFILE/);
33
+ assert.match(controller,/\$previousCapabilityProfileEnv = \$env:DEADBYTE_CAPABILITY_PROFILE/);
34
+ assert.match(controller,/\$env:DEADBYTE_CAPABILITY_PROFILE = 'compact'/);
35
+ assert.match(controller,/Remove-Item Env:DEADBYTE_CAPABILITY_PROFILE/);
36
+ assert.match(controller,/\$env:DEADBYTE_CAPABILITY_PROFILE = \$previousCapabilityProfileEnv/);
37
+ });
38
+
39
+ test('R36 surface contract remains exact full 76 plus compact gateway closure for R37',async()=>{
40
+ const parity=await text('src/remote-mcp-r36-parity-client.mjs');
41
+ assert.match(parity,/R36_EXPECTED_TOOLS/);
42
+ assert.match(parity,/R36_EXPECTED_TOOLS\.length !== 76|tool_count !== 76|length === 76/);
43
+ for(const name of ['capability_manifest','coding_inspect','machine_fs','process_session','machine_observe']) assert.match(parity,new RegExp(name));
44
+ assert.match(parity,/42/);
45
+ });
@@ -0,0 +1,92 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { readFile } from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { effectIdentity, loopGuardDisposition, bindEffectCompletion } from '../src/effect-ledger.mjs';
7
+ import { deriveAgentMemory, queryAgentMemory } from '../src/agent-memory-plane.mjs';
8
+ import { createWorkerScheduler } from '../src/worker-scheduler.mjs';
9
+ import { issueObservationLease, verifyObservationLease } from '../src/observation-lease.mjs';
10
+
11
+ const repo=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..');
12
+
13
+ test('R37 effect ledger detects semantically identical repeated effects across planner wording',()=>{
14
+ const base={goalId:'a'.repeat(64),planId:'b'.repeat(64),stepId:'fix',mutationEpoch:4,
15
+ action:{kind:'patch',operations:[{kind:'replace',path:'src/a.mjs',old_string:'x',new_string:'y'}]},
16
+ observationHeadSha256:'c'.repeat(64)};
17
+ const first=effectIdentity(base);
18
+ const second=effectIdentity({...base,plannerSummary:'different prose'});
19
+ assert.equal(first.fingerprint,second.fingerprint);
20
+ const events=[
21
+ {type:'effect_started',payload:{fingerprint:first.fingerprint,effect_id:first.effect_id}},
22
+ {type:'effect_completed',payload:{fingerprint:first.fingerprint,effect_id:first.effect_id}},
23
+ {type:'effect_started',payload:{fingerprint:first.fingerprint,effect_id:'d'.repeat(64)}},
24
+ {type:'effect_failed',payload:{fingerprint:first.fingerprint,effect_id:'d'.repeat(64)}}
25
+ ];
26
+ const guard=loopGuardDisposition(events,second,{maxRepeats:2,window:16});
27
+ assert.equal(guard.allowed,false);
28
+ assert.equal(guard.reason,'effect_repeat_limit');
29
+ assert.equal(guard.repeated_count,2);
30
+ const completion=bindEffectCompletion(first,{status:'passed',receipt_sha256:'e'.repeat(64)});
31
+ assert.equal(completion.effect_id,first.effect_id);
32
+ assert.match(completion.result_sha256,/^[0-9a-f]{64}$/);
33
+ });
34
+
35
+ test('R37 memory plane derives deterministic core archival and graph views from journal',()=>{
36
+ const events=[
37
+ {seq:1,type:'goal_created',event_sha256:'1'.repeat(64),payload:{acceptance:'all gates pass'}},
38
+ {seq:2,type:'profile_completed',event_sha256:'2'.repeat(64),payload:{profile_id:'quick-test',passed:true,receipt_sha256:'a'.repeat(64)}},
39
+ {seq:3,type:'native_diff_committed',event_sha256:'3'.repeat(64),payload:{paths:['src/a.mjs'],diff_receipt_sha256:'b'.repeat(64),mutation_epoch:1}},
40
+ {seq:4,type:'planner_rejected',event_sha256:'4'.repeat(64),payload:{reason:'stale approach'}},
41
+ {seq:5,type:'waiting_entered',event_sha256:'5'.repeat(64),payload:{reason:'needs evidence'}}
42
+ ];
43
+ const one=deriveAgentMemory(events);
44
+ const two=deriveAgentMemory(structuredClone(events));
45
+ assert.equal(one.memory_sha256,two.memory_sha256);
46
+ assert.deepEqual(one.core.acceptance_constraints,['all gates pass']);
47
+ assert.ok(one.archival.some(x=>x.type==='planner_rejected'));
48
+ assert.ok(one.graph.nodes.some(x=>x.id==='file:src/a.mjs'));
49
+ const local=queryAgentMemory(one,{query:'src a mjs',mode:'local',limit:8});
50
+ assert.ok(local.results.some(x=>JSON.stringify(x).includes('src/a.mjs')));
51
+ const global=queryAgentMemory(one,{query:'gates profiles blockers',mode:'global',limit:8});
52
+ assert.ok(global.results.length>0);
53
+ const drift=queryAgentMemory(one,{query:'src/a.mjs',mode:'drift',limit:8});
54
+ assert.ok(drift.results.length>0);
55
+ });
56
+
57
+ test('R37 worker scheduler enforces resources, leases and expiry recovery',()=>{
58
+ let now=1000;
59
+ const scheduler=createWorkerScheduler({maxConcurrent:2,totalCpuUnits:2,totalMemoryMb:1024,leaseMs:5000,clock:()=>now});
60
+ const a=scheduler.acquire({taskId:'test-a',workerClass:'test',cpuUnits:1,memoryMb:512});
61
+ const b=scheduler.acquire({taskId:'test-b',workerClass:'test',cpuUnits:1,memoryMb:512});
62
+ assert.equal(scheduler.snapshot().active.length,2);
63
+ assert.throws(()=>scheduler.acquire({taskId:'test-c',workerClass:'test',cpuUnits:1,memoryMb:128}),/capacity/i);
64
+ now=7000;
65
+ const c=scheduler.acquire({taskId:'test-c',workerClass:'test',cpuUnits:2,memoryMb:1024});
66
+ assert.equal(scheduler.snapshot().active.length,1);
67
+ assert.equal(c.task_id,'test-c');
68
+ assert.equal(scheduler.release(c.lease_id,{status:'passed'}).status,'released');
69
+ assert.equal(scheduler.snapshot().active.length,0);
70
+ assert.notEqual(a.lease_id,b.lease_id);
71
+ });
72
+
73
+ test('R37 observation leases bind effects to fresh observed state and mutation epoch',()=>{
74
+ const lease=issueObservationLease({goalId:'a'.repeat(64),mutationEpoch:3,
75
+ observations:[{event_sha256:'b'.repeat(64),receipt_sha256:'c'.repeat(64),result_head_sha256:'d'.repeat(64)}],
76
+ ttlMs:1000,nowMs:5000});
77
+ assert.equal(verifyObservationLease(lease,{goalId:'a'.repeat(64),currentMutationEpoch:3,nowMs:5500}).ok,true);
78
+ assert.throws(()=>verifyObservationLease(lease,{goalId:'a'.repeat(64),currentMutationEpoch:4,nowMs:5500}),/stale mutation epoch/i);
79
+ assert.throws(()=>verifyObservationLease(lease,{goalId:'a'.repeat(64),currentMutationEpoch:3,nowMs:7000}),/expired/i);
80
+ });
81
+
82
+ test('R37 autonomous runtime integrates memory, effect guard, worker scheduler and observation lease',async()=>{
83
+ const source=await readFile(path.join(repo,'src','autonomous-runtime.mjs'),'utf8');
84
+ assert.match(source,/deriveAgentMemory/);
85
+ assert.match(source,/effectIdentity/);
86
+ assert.match(source,/loopGuardDisposition/);
87
+ assert.match(source,/createWorkerScheduler/);
88
+ assert.match(source,/issueObservationLease/);
89
+ assert.match(source,/project_memory:memory/);
90
+ assert.match(source,/effect_guard_blocked/);
91
+ assert.match(source,/worker_lease_acquired/);
92
+ });
@@ -0,0 +1,60 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { classifyAutonomousTimeoutRecovery } from '../src/autonomous-timeout-recovery.mjs';
4
+
5
+ const before='a'.repeat(64);
6
+ const after='b'.repeat(64);
7
+ const base={status:'ok',state:'running',reason:null,journal_head_sha256:after,pending_request:null,pending_decision:null,run_busy:false,run_owner_pid:null,run_lock_created_at_utc:null};
8
+
9
+ test('R37 timeout recovery accepts signed durable terminal success',()=>{
10
+ assert.deepEqual(classifyAutonomousTimeoutRecovery({...base,state:'succeeded'},{beforeJournalHead:before}),
11
+ {kind:'completed',state:'succeeded',journal_head_sha256:after});
12
+ });
13
+
14
+ test('R37 timeout recovery surfaces paused or cancelled as terminal failure',()=>{
15
+ assert.equal(classifyAutonomousTimeoutRecovery({...base,state:'paused',reason:'benchmark_regression'},{beforeJournalHead:before}).kind,'terminal_failure');
16
+ assert.equal(classifyAutonomousTimeoutRecovery({...base,state:'cancelled'},{beforeJournalHead:before}).kind,'terminal_failure');
17
+ });
18
+
19
+ test('R37 timeout recovery waits while planner or decision is still in flight',()=>{
20
+ assert.equal(classifyAutonomousTimeoutRecovery({...base,pending_request:{request_id:'x'}},{beforeJournalHead:before}).kind,'wait');
21
+ assert.equal(classifyAutonomousTimeoutRecovery({...base,pending_decision:{event_sha256:'c'.repeat(64)}},{beforeJournalHead:before}).kind,'wait');
22
+ });
23
+
24
+ test('R37 timeout recovery resumes only after durable head advance and cleared pending state',()=>{
25
+ assert.deepEqual(classifyAutonomousTimeoutRecovery(base,{beforeJournalHead:before}),{
26
+ kind:'resumable',state:'running',reason:'durable_cycle_completed',journal_head_sha256:after
27
+ });
28
+ assert.equal(classifyAutonomousTimeoutRecovery({...base,journal_head_sha256:before},{beforeJournalHead:before}).kind,'wait');
29
+ });
30
+
31
+
32
+ test('R37 public autonomous smoke binds timeout recovery to pre-run journal head and resumes yielded work',async()=>{
33
+ const {readFile}=await import('node:fs/promises');
34
+ const src=await readFile(new URL('../src/remote-mcp-autonomous-smoke-client.mjs',import.meta.url),'utf8');
35
+ assert.match(src,/classifyAutonomousTimeoutRecovery/);
36
+ assert.match(src,/const beforeRun=structured\(await client\.callTool/);
37
+ assert.match(src,/recoverTimedOutGoal\(client, goalId, beforeRun\.journal_head_sha256\)/);
38
+ assert.match(src,/recovered\.kind === 'completed'/);
39
+ assert.match(src,/status:'yielded'/);
40
+ });
41
+
42
+
43
+ test('R37 timeout recovery waits until server-side run lock is released even after durable progress',()=>{
44
+ const busy={...base,run_busy:true,run_owner_pid:2904,run_lock_created_at_utc:'2026-09-18T14:22:02.000Z'};
45
+ const result=classifyAutonomousTimeoutRecovery(busy,{beforeJournalHead:before});
46
+ assert.equal(result.kind,'wait');
47
+ assert.equal(result.reason,'server_run_in_flight');
48
+ });
49
+
50
+ test('R37 autonomous goal status exposes run-lock state for timeout-safe clients',async()=>{
51
+ const {readFile}=await import('node:fs/promises');
52
+ const [runtime,contracts]=await Promise.all([
53
+ readFile(new URL('../src/autonomous-runtime.mjs',import.meta.url),'utf8'),
54
+ readFile(new URL('../src/autonomous-output-contracts.mjs',import.meta.url),'utf8')
55
+ ]);
56
+ assert.match(runtime,/runLockStatus/);
57
+ assert.match(runtime,/run_busy/);
58
+ assert.match(contracts,/run_busy:z\.boolean/);
59
+ assert.match(contracts,/run_owner_pid:z\.number\(\)\.int\(\)\.min\(1\)\.nullable/);
60
+ });
@@ -0,0 +1,74 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { readFile } from 'node:fs/promises';
4
+ import { validateParityEvidence, R36_PREDECESSOR_RELEASE_ID, R36_PREDECESSOR_MANIFEST } from '../scripts/release-parity.mjs';
5
+ import { verifyFinalClosureObject } from '../scripts/final-closure-verify.mjs';
6
+
7
+ const root=new URL('../',import.meta.url);
8
+ const text=rel=>readFile(new URL(rel,root),'utf8');
9
+
10
+ function parityFixture(){
11
+ const manifest='a'.repeat(64);
12
+ return {
13
+ schema:'deadbyte.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},
15
+ immutable_slot:{protected:true,release_root:'C:/immutable/r37',development_root:'D:/Projects/deadbyte-mcp-r36-dev'},
16
+ local_full:{status:'passed',tool_count:76,strict_output_schemas:true},
17
+ public_compact:{status:'passed',tool_count:41,capability_closure:true,gateway_count:5},
18
+ autonomous:{status:'passed',signed_release_verified:true,observed_failure_before_replan:true},
19
+ before_rollback_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false},
20
+ rollback:{state:'completed'},stage_restore:{status:'restored',manifest_sha256:manifest},restore:{state:'completed'},
21
+ predecessor:{release_id:R36_PREDECESSOR_RELEASE_ID,version:'0.10.0',manifest_sha256:R36_PREDECESSOR_MANIFEST},
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},
24
+ successor_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false},
25
+ requirements:Object.fromEntries(['tree_read','precondition_mutation','search','owned_process','observation','coding_loop','autonomy','interrupted_recovery','evidence_verification','compact_closure','full_surface'].map(key=>[key,true]))
26
+ };
27
+ }
28
+
29
+ test('R37 parity validator requires full-76, compact closure, exact R36 predecessor and immutable-slot separation',()=>{
30
+ const good=parityFixture();
31
+ assert.equal(validateParityEvidence(good),true);
32
+ assert.throws(()=>validateParityEvidence({...good,local_full:{...good.local_full,tool_count:75}}),/full 76/i);
33
+ assert.throws(()=>validateParityEvidence({...good,public_compact:{...good.public_compact,capability_closure:false}}),/compact closure/i);
34
+ assert.throws(()=>validateParityEvidence({...good,predecessor:{...good.predecessor,manifest_sha256:'b'.repeat(64)}}),/predecessor/i);
35
+ assert.throws(()=>validateParityEvidence({...good,immutable_slot:{...good.immutable_slot,development_root:good.immutable_slot.release_root}}),/immutable-slot/i);
36
+ assert.throws(()=>validateParityEvidence({...good,stage_restore:{status:'missing',manifest_sha256:good.candidate.manifest_sha256}}),/stage restore/i);
37
+ });
38
+
39
+ test('R37 parity captures R37 bridge, exact R36 predecessor, stage reseed and successor restore',async()=>{
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/);
43
+ assert.match(parity,/const stageRestore=await restoreFrozenStage/);
44
+ assert.match(parity,/publicR36Disarmed/);
45
+ assert.match(parity,/scheduleDeferred\('activate',candidateManifest,\{bridgeRoot:successorBridge\.root,bridgeScriptSha256:successorBridge\.sha256\}\)/);
46
+ });
47
+
48
+ test('R37 current final closure writer and independent verifier bind R37 domains and R36 predecessor',async()=>{
49
+ const [writer,verifier]=await Promise.all([text('scripts/final-closure.mjs'),text('scripts/final-closure-verify.mjs')]);
50
+ assert.equal(typeof verifyFinalClosureObject,'function');
51
+ assert.match(writer,/DEADBYTE-R37-FINAL-CLOSURE-V1/);
52
+ assert.match(writer,/deadbyte\.r37-final-closure\.v1/);
53
+ assert.match(writer,/pointer\.version==='0\.11\.0'/);
54
+ assert.match(writer,/R37 FINAL MACHINE BASELINE/);
55
+ assert.match(writer,/deadbyte\.r37-parity\.v1/);
56
+ assert.match(writer,/deadbyte\.r37-windows-gate\.v1/);
57
+ assert.match(writer,/R36_PREDECESSOR_RELEASE_ID/);
58
+ assert.doesNotMatch(verifier,/from ['"]\.\.\/src\//);
59
+ assert.match(verifier,/DEADBYTE-R37-FINAL-CLOSURE-V1/);
60
+ assert.match(verifier,/deadbyte\.r37-final-closure\.v1/);
61
+ assert.match(verifier,/envelope\.body\.version==='0\.11\.0'/);
62
+ assert.match(verifier,/R37 FINAL MACHINE BASELINE/);
63
+ assert.match(verifier,/deadbyte\.r37-parity\.v1/);
64
+ assert.match(verifier,/deadbyte\.r37-windows-gate\.v1/);
65
+ assert.match(verifier,/8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8/);
66
+ });
67
+
68
+ test('R37 bounded public parity suite covers current release identity and agent fabric',async()=>{
69
+ const script=await text('scripts/release-parity-tests.ps1');
70
+ assert.match(script,/r37-finalization\.test\.mjs/);
71
+ assert.match(script,/release-version\.test\.mjs/);
72
+ assert.match(script,/r37-agent-fabric\.test\.mjs/);
73
+ assert.match(script,/remote-live-log-r37\.test\.mjs/);
74
+ });