deadbyte-mcp 0.14.0 → 0.15.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 (105) hide show
  1. package/AGENTS.md +11 -18
  2. package/CONTEXT.md +3 -3
  3. package/MANIFEST.SHA256 +104 -53
  4. package/R43-PARENT.json +20 -0
  5. package/R44-DONORS.json +99 -0
  6. package/R44-PARENT.json +18 -0
  7. package/README.txt +7 -2
  8. package/controller/README.TXT +4 -5
  9. package/controller/deadbyte-controller.ps1 +1 -1
  10. package/docs/ARCHITECTURE.md +8 -1
  11. package/docs/R44-ARCHITECTURE.md +37 -0
  12. package/package.json +13 -8
  13. package/scripts/deferred-slot-operation-r43.mjs +126 -0
  14. package/scripts/deferred-slot-operation-r44.mjs +126 -0
  15. package/scripts/final-closure-r43.mjs +115 -0
  16. package/scripts/final-closure-r44.mjs +121 -0
  17. package/scripts/final-closure-verify-r43.mjs +213 -0
  18. package/scripts/final-closure-verify-r44.mjs +220 -0
  19. package/scripts/finalize-r43.mjs +217 -0
  20. package/scripts/finalize-r44.mjs +217 -0
  21. package/scripts/full-regression-r43.mjs +20 -0
  22. package/scripts/full-regression-r44.mjs +20 -0
  23. package/scripts/gate-windows-r43.ps1 +36 -0
  24. package/scripts/gate-windows-r44.ps1 +36 -0
  25. package/scripts/release-parity-r43.mjs +218 -0
  26. package/scripts/release-parity-r44.mjs +242 -0
  27. package/scripts/release-parity-tests-r43.ps1 +8 -0
  28. package/scripts/release-parity-tests-r44.ps1 +8 -0
  29. package/scripts/verify-r43-parent.mjs +126 -0
  30. package/scripts/verify-r44-parent.mjs +142 -0
  31. package/scripts/windows-gate-evidence-r43.mjs +55 -0
  32. package/scripts/windows-gate-evidence-r44.mjs +55 -0
  33. package/src/agent-backend-r44.mjs +254 -0
  34. package/src/autonomous-output-contracts.mjs +1 -1
  35. package/src/autonomous-policy.mjs +41 -4
  36. package/src/autonomous-runtime.mjs +25 -12
  37. package/src/autonomous-supervisor-host.mjs +12 -2
  38. package/src/capability-ledger.mjs +2 -1
  39. package/src/codex-app-server-r44.mjs +154 -0
  40. package/src/coding-plane.mjs +66 -19
  41. package/src/durable-job-r44.mjs +145 -0
  42. package/src/external-job-provider-r44.mjs +126 -0
  43. package/src/host-plane.mjs +27 -6
  44. package/src/job-supervisor-host-r44.mjs +112 -0
  45. package/src/machine-fs-smoke-client.mjs +1 -1
  46. package/src/machine-fs.mjs +21 -10
  47. package/src/mcp-host-smoke-client.mjs +1 -1
  48. package/src/mcp-server.mjs +20 -3
  49. package/src/mcp-smoke-client.mjs +1 -1
  50. package/src/native-diff-v2.mjs +3 -3
  51. package/src/native-diff.mjs +3 -2
  52. package/src/observation-smoke-client.mjs +1 -1
  53. package/src/operator-surface.mjs +2 -2
  54. package/src/process-policy.mjs +19 -0
  55. package/src/process-runtime.mjs +5 -2
  56. package/src/process-smoke-client.mjs +2 -2
  57. package/src/provider-circuit.mjs +8 -2
  58. package/src/r44-compact-disarmed-probe.mjs +74 -0
  59. package/src/r44-full-surface-probe.mjs +34 -0
  60. package/src/remote-device-r44.mjs +205 -0
  61. package/src/remote-mcp-autonomous-smoke-client.mjs +4 -4
  62. package/src/remote-mcp-r44-parity-client.mjs +203 -0
  63. package/src/remote-mcp-smoke-client.mjs +7 -4
  64. package/src/runtime-update.mjs +64 -31
  65. package/src/skill-mcp-tools-r44.mjs +37 -0
  66. package/src/skill-plane-r44.mjs +203 -0
  67. package/src/tunnel-stdio-compat-smoke.mjs +1 -1
  68. package/src/version.mjs +1 -1
  69. package/test/agent-backend-r44.test.mjs +115 -0
  70. package/test/agent-runtime.test.mjs +3 -3
  71. package/test/autonomous-loop.test.mjs +97 -11
  72. package/test/autonomous-runtime.test.mjs +2 -2
  73. package/test/capability-ledger-r36.test.mjs +3 -3
  74. package/test/cli-entrypoint.test.mjs +1 -1
  75. package/test/codex-app-server-r44.test.mjs +115 -0
  76. package/test/codex-autonomous-r44.test.mjs +87 -0
  77. package/test/coding-plane.test.mjs +2 -2
  78. package/test/coding-runtime.test.mjs +36 -1
  79. package/test/compact-catalog-r36.test.mjs +3 -3
  80. package/test/compact-max-catalog-r40.test.mjs +4 -2
  81. package/test/compact-max-catalog-r44.test.mjs +97 -0
  82. package/test/core.test.mjs +1 -1
  83. package/test/durable-job-r44.test.mjs +75 -0
  84. package/test/external-job-provider-r44.test.mjs +46 -0
  85. package/test/full-max-catalog-r40.test.mjs +5 -3
  86. package/test/full-max-catalog-r44.test.mjs +91 -0
  87. package/test/host-plane.test.mjs +15 -1
  88. package/test/native-diff.test.mjs +28 -0
  89. package/test/output-schema.test.mjs +2 -2
  90. package/test/process-policy.test.mjs +22 -1
  91. package/test/prompts-resources.test.mjs +1 -1
  92. package/test/r33-closeout-regression.test.mjs +13 -30
  93. package/test/r33-finalization.test.mjs +7 -7
  94. package/test/r43-finalization.test.mjs +31 -0
  95. package/test/r43-finalizer.test.mjs +34 -0
  96. package/test/r43-parent.test.mjs +29 -0
  97. package/test/r44-finalization.test.mjs +58 -0
  98. package/test/r44-finalizer.test.mjs +48 -0
  99. package/test/r44-parent.test.mjs +25 -0
  100. package/test/release-version.test.mjs +53 -19
  101. package/test/remote-device-r44.test.mjs +104 -0
  102. package/test/runtime-self-update.test.mjs +42 -0
  103. package/test/skill-mcp-r44.test.mjs +38 -0
  104. package/test/skill-plane-r44.test.mjs +93 -0
  105. package/test/standing-grants.test.mjs +5 -1
@@ -0,0 +1,217 @@
1
+ import { createHash, randomBytes } from 'node:crypto';
2
+ import { spawn, spawnSync } from 'node:child_process';
3
+ import { lstat, mkdir, readFile, realpath, rename, writeFile } from 'node:fs/promises';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { parseActivePointer } from '../src/release-slot.mjs';
8
+ import { loadPowerShellDataFile, parseControllerStatus, runSlotUpdateCli, windowsPowerShellEnvironment } from '../src/runtime-update.mjs';
9
+ import { verifyR44Parent } from './verify-r44-parent.mjs';
10
+ import { runReleaseParity } from './release-parity-r44.mjs';
11
+ import { writeFinalClosure } from './final-closure-r44.mjs';
12
+ import { verifyFinalClosureObject } from './final-closure-verify-r44.mjs';
13
+
14
+ const HEX64=/^[0-9a-f]{64}$/;
15
+ const EXPECTED_VERSION='0.15.0';
16
+ const PARENT_RELEASE_ID='v0.14.1-0a5a833892593283';
17
+ const PARENT_MANIFEST='0a5a8338925932830986421dda60ec5643f62f600404de4992fda2a5e79d09a9';
18
+ const PARENT_FINAL_CLOSURE='2f29e94dd726638c23b2e520a608dcf2a6919e43348855be3940599d557f920b';
19
+ const here=path.dirname(fileURLToPath(import.meta.url));
20
+ const packageRoot=path.resolve(here,'..');
21
+ const stateRoot=path.resolve(process.env.DEADBYTE_STATE_ROOT||path.join(os.homedir(),'.deadbyte-mcp'));
22
+ const evidenceRoot=path.join(stateRoot,'evidence','release','r44-finalization');
23
+ const launcher=path.join(stateRoot,'bin','DEADBYTE-MCP.ps1');
24
+ const ps=path.join(process.env.SystemRoot||'C:\\Windows','System32','WindowsPowerShell','v1.0','powershell.exe');
25
+ const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
26
+ const sleep=ms=>new Promise(resolve=>setTimeout(resolve,ms));
27
+ const insist=(ok,message)=>{if(!ok)throw new Error(message);};
28
+
29
+ async function atomicJson(file,value){
30
+ await mkdir(path.dirname(file),{recursive:true});
31
+ const bytes=Buffer.from(`${JSON.stringify(value,null,2)}\n`,'utf8');
32
+ const temp=`${file}.${process.pid}.${randomBytes(4).toString('hex')}.tmp`;
33
+ await writeFile(temp,bytes,{flag:'wx'});
34
+ await rename(temp,file);
35
+ return {path:file,sha256:sha256(bytes)};
36
+ }
37
+ async function activePointer(){
38
+ return parseActivePointer(await readFile(path.join(stateRoot,'active-release.json'),'utf8'));
39
+ }
40
+ async function bridgeArgs(){
41
+ const pointer=await activePointer();
42
+ const config=await loadPowerShellDataFile(pointer.config_path);
43
+ const raw=config?.Bridge?.WorkingDirectory;
44
+ insist(typeof raw==='string'&&path.isAbsolute(raw),'active Bridge.WorkingDirectory must be absolute');
45
+ const root=await realpath(path.resolve(raw));
46
+ const pkg=JSON.parse(await readFile(path.join(root,'package.json'),'utf8'));
47
+ insist(pkg?.name==='deadbyte-chatgpt-bridge','active Bridge package identity mismatch');
48
+ const script=path.join(root,'src','bridge.mjs');
49
+ return ['--bridge-root',root,'--bridge-script-sha256',sha256(await readFile(script))];
50
+ }
51
+ async function activationArgs(manifestSha256){
52
+ insist(HEX64.test(manifestSha256??''),'R44 finalizer manifest must be lowercase SHA-256');
53
+ const processPolicy=path.join(packageRoot,'controller','deadbyte-process-policy.json');
54
+ const desktopPolicy=path.join(packageRoot,'controller','deadbyte-desktop-policy.json');
55
+ const semantic=path.join(packageRoot,'controller','deadbyte-semantic-lsp-config.json');
56
+ return [
57
+ '--stage',packageRoot,'--development-root',packageRoot,'--expected-version',EXPECTED_VERSION,
58
+ '--expected-manifest',manifestSha256,
59
+ '--process-policy',processPolicy,'--process-policy-sha256',sha256(await readFile(processPolicy)),
60
+ '--desktop-policy',desktopPolicy,'--desktop-policy-sha256',sha256(await readFile(desktopPolicy)),
61
+ '--semantic-lsp-config',semantic,'--semantic-lsp-config-sha256',sha256(await readFile(semantic)),
62
+ '--enable-machine-fs','--enable-observation','--enable-desktop','--enable-autonomous-supervisor',
63
+ '--restore-standing-grants',
64
+ ...await bridgeArgs()
65
+ ];
66
+ }
67
+ export function validateFinalizerAuthorityStatus(status){
68
+ insist(status?.process_armed===true,'R44 finalizer requires Process standing grant');
69
+ insist(status?.coding_armed===true,'R44 finalizer requires Coding standing grant');
70
+ insist(status?.autonomous_armed===true,'R44 finalizer requires Autonomous standing grant');
71
+ insist(status?.desktop_armed===false,'R44 finalizer requires Desktop DISARMED');
72
+ insist(status?.host_armed===false,'R44 finalizer requires Host DISARMED');
73
+ return true;
74
+ }
75
+ function currentAuthorityStatus(){
76
+ const result=spawnSync(ps,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',launcher,'status'],
77
+ {encoding:'utf8',windowsHide:true,timeout:20000,env:windowsPowerShellEnvironment()});
78
+ if(result.error) throw result.error;
79
+ if(result.status!==0) throw new Error(`R44 finalizer controller status failed: ${result.stderr||result.stdout}`);
80
+ return parseControllerStatus(result.stdout??'');
81
+ }
82
+ export function validateWindowsGateEvidence(value,manifestSha256,parent){
83
+ insist(value?.schema==='deadbyte.r44-windows-gate.v1'&&value.status==='passed'&&value.exit_code===0,'R44 Windows gate evidence invalid');
84
+ insist(value.version===EXPECTED_VERSION&&value.manifest_sha256===manifestSha256,'R44 Windows gate candidate mismatch');
85
+ insist(value.marker==='DEADBYTE V0.15.0 / R44 REMOTE AGENT SKILL WINDOWS BATCH GATE: PASS','R44 Windows gate marker mismatch');
86
+ insist(value.parent?.release_id===parent.release_id&&value.parent?.manifest_sha256===parent.manifest_sha256,'R44 Windows gate parent mismatch');
87
+ insist(value.parent?.generation_manifest_sha256===parent.generation_manifest_sha256,'R44 Windows gate parent generation mismatch');
88
+ insist(value.parent?.final_closure_sha256===PARENT_FINAL_CLOSURE&&value.parent?.final_closure_sha256===parent.closure_sha256,'R44 Windows gate parent final closure mismatch');
89
+ 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']) {
90
+ insist(value.features?.[key]===true,`R44 Windows gate feature contract missing ${key}`);
91
+ }
92
+ return true;
93
+ }
94
+ function disarmFailClosed(){
95
+ const results=[];
96
+ for(const command of ['disarmdesktop','disarmautonomous','disarmcoding','disarmprocess','disarmhost']){
97
+ const result=spawnSync(ps,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',launcher,command],
98
+ {encoding:'utf8',windowsHide:true,timeout:20000,env:windowsPowerShellEnvironment()});
99
+ results.push({command,status:result.status,signal:result.signal??null});
100
+ }
101
+ return results;
102
+ }
103
+ async function mirrorRoot(){
104
+ const pointer=await activePointer();
105
+ const policy=JSON.parse(await readFile(path.join(pointer.generation_root,'coding-policy.json'),'utf8'));
106
+ const raw=policy?.roots?.parity_scratch?.path??policy?.roots?.parity_scratch?.real_path;
107
+ if(typeof raw!=='string'||!path.isAbsolute(raw)) throw new Error('active generation parity_scratch root unavailable');
108
+ const stat=await lstat(raw);
109
+ if(!stat.isDirectory()||stat.isSymbolicLink()) throw new Error('parity_scratch root must be a real directory');
110
+ return raw;
111
+ }
112
+ async function writeMirror(manifestSha256,value){
113
+ const root=await mirrorRoot();
114
+ const file=path.join(root,`r44-final-${manifestSha256.slice(0,16)}.json`);
115
+ return atomicJson(file,value);
116
+ }
117
+ async function verifyInputs(manifestSha256){
118
+ insist(HEX64.test(manifestSha256??''),'R44 finalizer manifest invalid');
119
+ const manifestBytes=await readFile(path.join(packageRoot,'MANIFEST.SHA256'));
120
+ insist(sha256(manifestBytes)===manifestSha256,'R44 finalizer manifest drift');
121
+ const pkg=JSON.parse(await readFile(path.join(packageRoot,'package.json'),'utf8'));
122
+ insist(pkg?.name==='deadbyte-mcp'&&pkg?.version===EXPECTED_VERSION,'R44 finalizer package identity mismatch');
123
+ const parent=await verifyR44Parent(path.join(packageRoot,'R44-PARENT.json'));
124
+ const authorityStatus=currentAuthorityStatus();
125
+ validateFinalizerAuthorityStatus(authorityStatus);
126
+ const before=await activePointer();
127
+ insist(before.release_id===PARENT_RELEASE_ID&&before.manifest_sha256===PARENT_MANIFEST,'R44 finalizer must start from exact sealed R43 parent');
128
+ const windowsGatePath=path.join(stateRoot,'evidence','release',`r44-windows-gate-${manifestSha256.slice(0,16)}.json`);
129
+ const windowsGateBytes=await readFile(windowsGatePath);
130
+ const windowsGate=JSON.parse(windowsGateBytes.toString('utf8').replace(/^\uFEFF/,''));
131
+ validateWindowsGateEvidence(windowsGate,manifestSha256,parent);
132
+ return {parent,before,authorityStatus,windowsGatePath,windowsGateFileSha256:sha256(windowsGateBytes)};
133
+ }
134
+ async function runWorker(manifestSha256,operationId){
135
+ const statePath=path.join(evidenceRoot,`${operationId}.json`);
136
+ let activation=null;
137
+ let parity=null;
138
+ try{
139
+ await atomicJson(statePath,{schema:'deadbyte.r44-finalization-state.v1',operation_id:operationId,status:'running',
140
+ manifest_sha256:manifestSha256,started_at_utc:new Date().toISOString()});
141
+ const inputs=await verifyInputs(manifestSha256);
142
+ activation=await runSlotUpdateCli(await activationArgs(manifestSha256),{stateRoot});
143
+ insist(activation?.pointer?.version===EXPECTED_VERSION&&activation.pointer.manifest_sha256===manifestSha256,'R44 activation result mismatch');
144
+ insist(activation?.final_authority?.process_armed===true&&activation?.final_authority?.coding_armed===true&&activation?.final_authority?.autonomous_armed===true,
145
+ 'R44 activation must restore prior Process+Coding+Autonomous standing grants for detached parity');
146
+ insist(activation?.final_authority?.desktop_armed===false&&activation?.final_authority?.host_armed===false,
147
+ 'R44 activation must keep Desktop+Host disarmed');
148
+
149
+ parity=await runReleaseParity(activation.receipt_path);
150
+ insist(parity?.evidence?.status==='passed'&&parity.evidence?.candidate?.manifest_sha256===manifestSha256,'R44 parity result mismatch');
151
+
152
+ const closure=await writeFinalClosure({parityPath:parity.evidence_path,activationPath:activation.receipt_path,
153
+ windowsGatePath:inputs.windowsGatePath});
154
+ const envelope=JSON.parse(await readFile(closure.path,'utf8'));
155
+ const verified=await verifyFinalClosureObject(envelope,{stateRoot});
156
+ insist(verified?.ok===true&&verified.status==='passed'&&verified.manifest_sha256===manifestSha256,'R44 independent final closure verification failed');
157
+
158
+ const pointer=await activePointer();
159
+ const result={schema:'deadbyte.r44-finalization-result.v1',status:'passed',verified:true,
160
+ completed_at_utc:new Date().toISOString(),release_id:pointer.release_id,version:pointer.version,
161
+ manifest_sha256:pointer.manifest_sha256,generation_manifest_sha256:pointer.generation_manifest_sha256,
162
+ activation_receipt_sha256:activation.receipt_sha256,
163
+ parity_sha256:parity.evidence_sha256,windows_gate_sha256:inputs.windowsGateFileSha256,
164
+ closure_file_sha256:closure.sha256,closure_sha256:closure.closure_sha256,
165
+ full_tool_count:verified.full_tool_count,compact_tool_count:verified.compact_tool_count,
166
+ parent_release_id:inputs.parent.release_id,parent_manifest_sha256:inputs.parent.manifest_sha256};
167
+ const mirror=await writeMirror(manifestSha256,result);
168
+ await atomicJson(statePath,{...result,operation_id:operationId,mirror_path:mirror.path,mirror_sha256:mirror.sha256,
169
+ activation_receipt_path:activation.receipt_path,parity_path:parity.evidence_path,closure_path:closure.path});
170
+ return result;
171
+ }catch(error){
172
+ let rollback=null;
173
+ try{
174
+ if(activation?.receipt_path){
175
+ const pointer=await activePointer().catch(()=>null);
176
+ if(pointer?.version===EXPECTED_VERSION&&pointer?.manifest_sha256===manifestSha256){
177
+ rollback=await runSlotUpdateCli(['--rollback-receipt',activation.receipt_path],{stateRoot});
178
+ }
179
+ }
180
+ }catch(rollbackError){rollback={error:String(rollbackError?.message??rollbackError)};}
181
+ const disarm=disarmFailClosed();
182
+ const failed={schema:'deadbyte.r44-finalization-result.v1',status:'failed',verified:false,
183
+ completed_at_utc:new Date().toISOString(),manifest_sha256:manifestSha256,
184
+ error:String(error?.message??error),rollback:rollback?{ok:rollback?.ok===true,error:rollback?.error??null}:null,disarm};
185
+ await atomicJson(statePath,{...failed,operation_id:operationId}).catch(()=>{});
186
+ await writeMirror(manifestSha256,failed).catch(()=>{});
187
+ throw error;
188
+ }
189
+ }
190
+ export async function scheduleFinalization(manifestSha256){
191
+ insist(HEX64.test(manifestSha256??''),'R44 finalizer manifest invalid');
192
+ const operationId=`r44-${manifestSha256.slice(0,16)}-${randomBytes(8).toString('hex')}`;
193
+ const statePath=path.join(evidenceRoot,`${operationId}.json`);
194
+ await atomicJson(statePath,{schema:'deadbyte.r44-finalization-state.v1',operation_id:operationId,status:'scheduled',
195
+ manifest_sha256:manifestSha256,scheduled_at_utc:new Date().toISOString()});
196
+ const child=spawn(process.execPath,[fileURLToPath(import.meta.url),manifestSha256,'--worker',operationId],{
197
+ cwd:packageRoot,detached:true,stdio:'ignore',windowsHide:true,env:{...process.env,DEADBYTE_STATE_ROOT:stateRoot}
198
+ });
199
+ child.unref();
200
+ return {status:'scheduled',operation_id:operationId,state_path:statePath,manifest_sha256:manifestSha256,
201
+ execution_provider:'deadbyte_mcp',rdc_operation_count:0};
202
+ }
203
+
204
+ const invoked=process.argv[1]&&path.resolve(process.argv[1])===fileURLToPath(import.meta.url);
205
+ if(invoked){
206
+ const [manifestSha256,flag,operationId]=process.argv.slice(2);
207
+ try{
208
+ if(flag==='--worker'){
209
+ insist(/^r44-[0-9a-f]{16}-[0-9a-f]{16}$/.test(operationId??''),'R44 finalizer worker operation id invalid');
210
+ await sleep(4000);
211
+ await runWorker(manifestSha256,operationId);
212
+ }else{
213
+ insist(flag===undefined&&operationId===undefined,'usage: node scripts/finalize-r44.mjs <manifest_sha256>');
214
+ console.log(JSON.stringify(await scheduleFinalization(manifestSha256)));
215
+ }
216
+ }catch(error){console.error(error instanceof Error?error.stack:String(error));process.exitCode=1;}
217
+ }
@@ -0,0 +1,20 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { readdir } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const here=path.dirname(fileURLToPath(import.meta.url));
7
+ const root=path.resolve(here,'..');
8
+ const testDir=path.join(root,'test');
9
+ const files=(await readdir(testDir,{withFileTypes:true}))
10
+ .filter(entry=>entry.isFile()&&entry.name.endsWith('.test.mjs'))
11
+ .map(entry=>path.join('test',entry.name))
12
+ .sort((a,b)=>a.localeCompare(b,'en'));
13
+ if(files.length<1) throw new Error('R43 full regression found no test files');
14
+ console.log(`R43-FULL-REGRESSION files=${files.length}`);
15
+ const result=spawnSync(process.execPath,['--test',...files],{
16
+ cwd:root,stdio:'inherit',windowsHide:true,shell:false
17
+ });
18
+ if(result.error) throw result.error;
19
+ if(result.signal) throw new Error(`R43 full regression terminated by ${result.signal}`);
20
+ process.exitCode=Number.isInteger(result.status)?result.status:1;
@@ -0,0 +1,20 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { readdir } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const here=path.dirname(fileURLToPath(import.meta.url));
7
+ const root=path.resolve(here,'..');
8
+ const testDir=path.join(root,'test');
9
+ const files=(await readdir(testDir,{withFileTypes:true}))
10
+ .filter(entry=>entry.isFile()&&entry.name.endsWith('.test.mjs'))
11
+ .map(entry=>path.join('test',entry.name))
12
+ .sort((a,b)=>a.localeCompare(b,'en'));
13
+ if(files.length<1) throw new Error('R44 full regression found no test files');
14
+ console.log(`R44-FULL-REGRESSION files=${files.length}`);
15
+ const result=spawnSync(process.execPath,['--test',...files],{
16
+ cwd:root,stdio:'inherit',windowsHide:true,shell:false
17
+ });
18
+ if(result.error) throw result.error;
19
+ if(result.signal) throw new Error(`R44 full regression terminated by ${result.signal}`);
20
+ process.exitCode=Number.isInteger(result.status)?result.status:1;
@@ -0,0 +1,36 @@
1
+ $ErrorActionPreference = 'Stop'
2
+ Set-StrictMode -Version 2.0
3
+ function Invoke-GateStep {
4
+ param([Parameter(Mandatory = $true)][string]$Name,[Parameter(Mandatory = $true)][string[]]$NpmArgs)
5
+ Write-Host "==== $Name ===="
6
+ & npm.cmd @NpmArgs
7
+ if ($LASTEXITCODE -ne 0) { throw "DEADBYTE V0.14.1 / R43 gate failed at $Name with exit code $LASTEXITCODE" }
8
+ }
9
+ Invoke-GateStep -Name 'r43-parent-verify' -NpmArgs @('run','r43:parent:verify')
10
+ Invoke-GateStep -Name 'containment-build' -NpmArgs @('run','containment:build')
11
+ Invoke-GateStep -Name 'process-policy-refresh' -NpmArgs @('run','process:policy:refresh')
12
+ Invoke-GateStep -Name 'desktop-policy-refresh' -NpmArgs @('run','desktop:policy:refresh')
13
+ Invoke-GateStep -Name 'release-manifest-write' -NpmArgs @('run','manifest:write')
14
+ Invoke-GateStep -Name 'release-manifest' -NpmArgs @('run','manifest:verify')
15
+ Write-Host '==== r43-hardening-focused ===='
16
+ & powershell.exe -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot 'release-parity-tests-r43.ps1')
17
+ if ($LASTEXITCODE -ne 0) { throw "DEADBYTE V0.14.1 / R43 gate failed at r43-hardening-focused with exit code $LASTEXITCODE" }
18
+ Invoke-GateStep -Name 'full-regression' -NpmArgs @('run','r43:full:test')
19
+ Invoke-GateStep -Name 'mcp-smoke' -NpmArgs @('run','mcp:smoke')
20
+ Invoke-GateStep -Name 'mcp-agent-smoke' -NpmArgs @('run','mcp:agent:smoke')
21
+ Invoke-GateStep -Name 'mcp-coding-smoke' -NpmArgs @('run','mcp:coding:smoke')
22
+ Invoke-GateStep -Name 'mcp-machine-fs-smoke' -NpmArgs @('run','mcp:machine-fs:smoke')
23
+ Invoke-GateStep -Name 'mcp-observation-smoke' -NpmArgs @('run','mcp:observation:smoke')
24
+ Invoke-GateStep -Name 'mcp-process-smoke' -NpmArgs @('run','mcp:process:smoke')
25
+ Invoke-GateStep -Name 'mcp-autonomous-smoke' -NpmArgs @('run','mcp:autonomous:smoke')
26
+ Invoke-GateStep -Name 'tunnel-stdio-compat-smoke' -NpmArgs @('run','mcp:tunnel-compat:smoke')
27
+ Invoke-GateStep -Name 'mcp-host-smoke' -NpmArgs @('run','mcp:host:smoke')
28
+ Invoke-GateStep -Name 'authority-smoke' -NpmArgs @('run','authority:smoke')
29
+ Invoke-GateStep -Name 'containment-smoke' -NpmArgs @('run','containment:smoke')
30
+ Invoke-GateStep -Name 'contained-smoke' -NpmArgs @('run','contained:smoke')
31
+ Invoke-GateStep -Name 'mcp-contained-smoke' -NpmArgs @('run','mcp:contained:smoke')
32
+ Invoke-GateStep -Name 'release-manifest-final' -NpmArgs @('run','manifest:verify')
33
+ Write-Host '==== windows-gate-evidence ===='
34
+ & node.exe (Join-Path $PSScriptRoot 'windows-gate-evidence-r43.mjs')
35
+ if ($LASTEXITCODE -ne 0) { throw "DEADBYTE V0.14.1 / R43 gate failed at windows-gate-evidence with exit code $LASTEXITCODE" }
36
+ Write-Host '==== DEADBYTE V0.14.1 / R43 AUTHORITY HARDENING WINDOWS BATCH GATE: PASS ===='
@@ -0,0 +1,36 @@
1
+ $ErrorActionPreference = 'Stop'
2
+ Set-StrictMode -Version 2.0
3
+ function Invoke-GateStep {
4
+ param([Parameter(Mandatory = $true)][string]$Name,[Parameter(Mandatory = $true)][string[]]$NpmArgs)
5
+ Write-Host "==== $Name ===="
6
+ & npm.cmd @NpmArgs
7
+ if ($LASTEXITCODE -ne 0) { throw "DEADBYTE V0.15.0 / R44 gate failed at $Name with exit code $LASTEXITCODE" }
8
+ }
9
+ Invoke-GateStep -Name 'r44-parent-verify' -NpmArgs @('run','r44:parent:verify')
10
+ Invoke-GateStep -Name 'containment-build' -NpmArgs @('run','containment:build')
11
+ Invoke-GateStep -Name 'process-policy-refresh' -NpmArgs @('run','process:policy:refresh')
12
+ Invoke-GateStep -Name 'desktop-policy-refresh' -NpmArgs @('run','desktop:policy:refresh')
13
+ Invoke-GateStep -Name 'release-manifest-write' -NpmArgs @('run','manifest:write')
14
+ Invoke-GateStep -Name 'release-manifest' -NpmArgs @('run','manifest:verify')
15
+ Write-Host '==== r44-feature-focused ===='
16
+ & powershell.exe -NoProfile -ExecutionPolicy Bypass -File (Join-Path $PSScriptRoot 'release-parity-tests-r44.ps1')
17
+ if ($LASTEXITCODE -ne 0) { throw "DEADBYTE V0.15.0 / R44 gate failed at r44-feature-focused with exit code $LASTEXITCODE" }
18
+ Invoke-GateStep -Name 'full-regression' -NpmArgs @('run','r44:full:test')
19
+ Invoke-GateStep -Name 'mcp-smoke' -NpmArgs @('run','mcp:smoke')
20
+ Invoke-GateStep -Name 'mcp-agent-smoke' -NpmArgs @('run','mcp:agent:smoke')
21
+ Invoke-GateStep -Name 'mcp-coding-smoke' -NpmArgs @('run','mcp:coding:smoke')
22
+ Invoke-GateStep -Name 'mcp-machine-fs-smoke' -NpmArgs @('run','mcp:machine-fs:smoke')
23
+ Invoke-GateStep -Name 'mcp-observation-smoke' -NpmArgs @('run','mcp:observation:smoke')
24
+ Invoke-GateStep -Name 'mcp-process-smoke' -NpmArgs @('run','mcp:process:smoke')
25
+ Invoke-GateStep -Name 'mcp-autonomous-smoke' -NpmArgs @('run','mcp:autonomous:smoke')
26
+ Invoke-GateStep -Name 'tunnel-stdio-compat-smoke' -NpmArgs @('run','mcp:tunnel-compat:smoke')
27
+ Invoke-GateStep -Name 'mcp-host-smoke' -NpmArgs @('run','mcp:host:smoke')
28
+ Invoke-GateStep -Name 'authority-smoke' -NpmArgs @('run','authority:smoke')
29
+ Invoke-GateStep -Name 'containment-smoke' -NpmArgs @('run','containment:smoke')
30
+ Invoke-GateStep -Name 'contained-smoke' -NpmArgs @('run','contained:smoke')
31
+ Invoke-GateStep -Name 'mcp-contained-smoke' -NpmArgs @('run','mcp:contained:smoke')
32
+ Invoke-GateStep -Name 'release-manifest-final' -NpmArgs @('run','manifest:verify')
33
+ Write-Host '==== windows-gate-evidence ===='
34
+ & node.exe (Join-Path $PSScriptRoot 'windows-gate-evidence-r44.mjs')
35
+ if ($LASTEXITCODE -ne 0) { throw "DEADBYTE V0.15.0 / R44 gate failed at windows-gate-evidence with exit code $LASTEXITCODE" }
36
+ Write-Host '==== DEADBYTE V0.15.0 / R44 REMOTE AGENT SKILL WINDOWS BATCH GATE: PASS ===='
@@ -0,0 +1,218 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { mkdir, readFile, realpath, writeFile } from 'node:fs/promises';
3
+ import { loadPowerShellDataFile } from '../src/runtime-update.mjs';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import { spawn } from 'node:child_process';
7
+ import { fileURLToPath } from 'node:url';
8
+ import { probeR40FullSurface } from '../src/r40-full-surface-probe.mjs';
9
+ import { runR40CompactParity } from '../src/remote-mcp-r40-parity-client.mjs';
10
+ import { probeR40CompactDisarmed } from '../src/r40-compact-disarmed-probe.mjs';
11
+ import { probeR36CompactDisarmed } from '../src/r36-compact-disarmed-probe.mjs';
12
+ import { runR40DesktopGuardedSmoke } from '../src/remote-mcp-desktop-r40-smoke-client.mjs';
13
+ import { verifyR41Memory } from './verify-memory-r41.mjs';
14
+
15
+ const here=path.dirname(fileURLToPath(import.meta.url));
16
+ const root=path.resolve(here,'..');
17
+ const stateRoot=path.resolve(process.env.DEADBYTE_STATE_ROOT||path.join(os.homedir(),'.deadbyte-mcp'));
18
+ const deferred=path.join(root,'scripts','deferred-slot-operation-r43.mjs');
19
+ const ps='C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe';
20
+ const launcher=path.join(stateRoot,'bin','DEADBYTE-MCP.ps1');
21
+ const sleep=ms=>new Promise(resolve=>setTimeout(resolve,ms));
22
+ const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
23
+
24
+ export const R43_PREDECESSOR_RELEASE_ID='v0.14.0-08cd8f3b98c90e0e';
25
+ export const R43_PREDECESSOR_MANIFEST='08cd8f3b98c90e0e250cf506ff396515065ff5457909f850b75b0b6e8ecc2dd1';
26
+
27
+ function assert(condition,message){if(!condition) throw new Error(message);}
28
+ function parseFrozenManifest(text){
29
+ const entries=[];const seen=new Set();
30
+ for(const [index,line] of text.split(/\r?\n/).entries()){
31
+ if(!line) continue;
32
+ const match=/^([0-9a-f]{64}) ([^\0]+)$/.exec(line);
33
+ assert(match,`frozen manifest line ${index+1} malformed`);
34
+ const rel=match[2];
35
+ assert(!path.posix.isAbsolute(rel)&&!rel.split('/').includes('..')&&!seen.has(rel),`unsafe/duplicate frozen manifest path: ${rel}`);
36
+ seen.add(rel);entries.push({sha256:match[1],path:rel});
37
+ }
38
+ return entries;
39
+ }
40
+ // Restore the mutable development stage from the immutable active release after live parity work may drift it.
41
+ export async function restoreFrozenStage({developmentRoot,releaseRoot,expectedManifestSha256}){
42
+ const dev=path.resolve(developmentRoot);const release=path.resolve(releaseRoot);
43
+ const manifestBytes=await readFile(path.join(release,'MANIFEST.SHA256'));
44
+ const manifestSha256=sha256(manifestBytes);
45
+ assert(manifestSha256===expectedManifestSha256,`immutable release manifest drift: ${manifestSha256}`);
46
+ const entries=parseFrozenManifest(manifestBytes.toString('utf8'));
47
+ for(const entry of entries){
48
+ const source=path.join(release,...entry.path.split('/'));const bytes=await readFile(source);
49
+ assert(sha256(bytes)===entry.sha256,`immutable release file drift: ${entry.path}`);
50
+ const destination=path.join(dev,...entry.path.split('/'));await mkdir(path.dirname(destination),{recursive:true});
51
+ await writeFile(destination,bytes);assert(sha256(await readFile(destination))===entry.sha256,`development restore verification failed: ${entry.path}`);
52
+ }
53
+ await writeFile(path.join(dev,'MANIFEST.SHA256'),manifestBytes);
54
+ assert(sha256(await readFile(path.join(dev,'MANIFEST.SHA256')))===expectedManifestSha256,'development manifest restore verification failed');
55
+ return {status:'restored',file_count:entries.length,manifest_sha256:manifestSha256};
56
+ }
57
+ function parseJsonOutput(text,label){
58
+ const trimmed=String(text).trim();const starts=[...trimmed.matchAll(/\{/g)].map(match=>match.index);
59
+ for(const start of starts){try{return JSON.parse(trimmed.slice(start));}catch{}}
60
+ throw new Error(`${label} did not emit JSON`);
61
+ }
62
+ function run(command,args,{timeoutMs=900000,env=process.env,cwd=root}={}){
63
+ return new Promise((resolve,reject)=>{
64
+ const child=spawn(command,args,{cwd,shell:false,windowsHide:true,env,stdio:['ignore','pipe','pipe']});
65
+ const out=[],err=[];const timer=setTimeout(()=>{child.kill();reject(new Error(`command timeout: ${path.basename(command)}`));},timeoutMs);
66
+ child.stdout.on('data',chunk=>out.push(Buffer.from(chunk)));child.stderr.on('data',chunk=>err.push(Buffer.from(chunk)));
67
+ child.on('error',error=>{clearTimeout(timer);reject(error);});child.on('exit',code=>{
68
+ clearTimeout(timer);const stdout=Buffer.concat(out).toString('utf8');const stderr=Buffer.concat(err).toString('utf8');
69
+ if(code!==0) reject(new Error(`command failed exit=${code}: ${stderr||stdout}`));else resolve({stdout,stderr,exitCode:code});
70
+ });
71
+ });
72
+ }
73
+ async function publicUrl(){
74
+ const value=(await readFile(path.join(stateRoot,'bridge','mcp-url.txt'),'utf8')).trim();const url=new URL(value);
75
+ if(url.protocol!=='https:') throw new Error('public MCP URL must be HTTPS');return value;
76
+ }
77
+ async function pointer(){return JSON.parse(await readFile(path.join(stateRoot,'active-release.json'),'utf8'));}
78
+ async function disarmAll(){
79
+ for(const command of ['disarmdesktop','disarmautonomous','disarmcoding','disarmprocess','disarmhost']){
80
+ await run(ps,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',launcher,command],{timeoutMs:60000});
81
+ }
82
+ }
83
+ async function waitDeferred(statePath,timeoutMs=180000){
84
+ const deadline=Date.now()+timeoutMs;
85
+ while(Date.now()<deadline){const state=JSON.parse(await readFile(statePath,'utf8'));if(state.state==='completed') return state;if(state.state==='failed') throw new Error(`deferred ${state.mode} failed: ${state.error}`);await sleep(500);}
86
+ throw new Error(`deferred operation timeout: ${statePath}`);
87
+ }
88
+ async function scheduleDeferred(mode,value,{bridgeRoot=null,bridgeScriptSha256=null}={}){
89
+ if((bridgeRoot===null)!==(bridgeScriptSha256===null)) throw new Error('deferred bridge override requires exact root + SHA pair');
90
+ const args=[deferred,mode,value];
91
+ if(bridgeRoot!==null) args.push('--bridge-root',bridgeRoot,'--bridge-script-sha256',bridgeScriptSha256);
92
+ const scheduled=parseJsonOutput((await run(process.execPath,args,{timeoutMs:30000})).stdout,`deferred ${mode}`);
93
+ assert(scheduled.status==='scheduled',`deferred ${mode} was not scheduled`);
94
+ assert(scheduled.execution_provider==='deadbyte_mcp'&&scheduled.rdc_operation_count===0,'deferred operation provider mismatch');
95
+ return {scheduled,completed:await waitDeferred(scheduled.state_path)};
96
+ }
97
+ async function publicR40PredecessorDisarmed(url){
98
+ const result=await probeR36CompactDisarmed(url);
99
+ assert(result.status==='passed'&&result.tool_count<=42&&result.capability_closure===true,'R42 predecessor public compact catalog mismatch');
100
+ assert(result.release_id===R43_PREDECESSOR_RELEASE_ID&&result.release_manifest_sha256===R43_PREDECESSOR_MANIFEST,'R42 predecessor machine binding mismatch');
101
+ assert(result.coding_armed===false&&result.autonomous_armed===false,'R42 predecessor authority remained armed');
102
+ return result;
103
+ }
104
+ async function mutableCore(pointerValue){
105
+ const policy=JSON.parse(await readFile(path.join(pointerValue.generation_root,'coding-policy.json'),'utf8'));
106
+ const raw=policy?.roots?.core?.path??policy?.roots?.core?.real_path;
107
+ assert(typeof raw==='string'&&raw,'R40 generation missing coding core root');
108
+ const core=path.resolve(raw);const release=path.resolve(pointerValue.release_root);
109
+ assert(core.toLowerCase()!==release.toLowerCase(),'R40 coding core must not point at immutable active release slot');
110
+ return core;
111
+ }
112
+
113
+ export function validateParityEvidence(value){
114
+ assert(value?.schema==='deadbyte.r43-parity.v1','R40 parity schema mismatch');
115
+ assert(value.status==='passed','R40 parity status is not passed');
116
+ assert(value.rdc_operation_count===0&&value.execution_provider==='deadbyte_mcp','R40 parity used non-DEADBYTE execution');
117
+ assert(value.candidate?.version==='0.14.1'&&/^[0-9a-f]{64}$/.test(value.candidate?.manifest_sha256??''),'R40 candidate identity missing');
118
+ assert(value.local_full?.status==='passed'&&value.local_full?.tool_count===80&&value.local_full?.strict_output_schemas===true,'R40 local full 80-tool proof missing');
119
+ assert(value.public_compact?.status==='passed'&&value.public_compact?.tool_count===42&&value.public_compact?.capability_closure===true&&value.public_compact?.gateway_count===6&&value.public_compact?.desktop_armed===false&&value.public_compact?.desktop_observation_receipt_verified===true&&value.public_compact?.desktop_grounding_receipt_verified===true,'R40 public compact/Desktop closure missing');
120
+ assert(value.desktop_guarded?.status==='passed'&&value.desktop_guarded?.native_injected===true&&value.desktop_guarded?.replay_performed===false&&
121
+ Number.isInteger(value.desktop_guarded?.predispatch_retry_count)&&value.desktop_guarded.predispatch_retry_count>=0&&value.desktop_guarded.predispatch_retry_count<=2&&
122
+ value.desktop_guarded?.observation_receipts_verified===value.desktop_guarded.predispatch_retry_count+1&&value.desktop_guarded?.action_receipts_verified===3,
123
+ 'R40 guarded Desktop proof missing');
124
+ assert(value.autonomous?.status==='passed'&&value.autonomous?.signed_release_verified===true,'R40 autonomous live proof missing');
125
+ assert(value.deterministic_memory?.status==='passed'&&value.deterministic_memory?.goal_count>=1&&value.deterministic_memory?.snapshot_count>=1&&value.deterministic_memory?.index_count>=1,'R41 deterministic memory proof missing');
126
+ assert(value.before_rollback_disarmed?.status==='passed'&&value.before_rollback_disarmed?.capability_closure===true&&value.before_rollback_disarmed?.coding_armed===false&&value.before_rollback_disarmed?.autonomous_armed===false&&value.before_rollback_disarmed?.desktop_armed===false,'R40 pre-rollback disarm proof missing');
127
+ assert(value.rollback?.state==='completed'&&value.restore?.state==='completed','R40 rollback/restore not completed');
128
+ assert(value.stage_restore?.status==='restored'&&value.stage_restore?.manifest_sha256===value.candidate.manifest_sha256,'R40 stage restore proof missing');
129
+ assert(value.predecessor?.release_id===R43_PREDECESSOR_RELEASE_ID&&value.predecessor?.manifest_sha256===R43_PREDECESSOR_MANIFEST&&value.predecessor?.version==='0.14.0','R43 exact R42 predecessor identity mismatch');
130
+ assert(value.predecessor_disarmed?.status==='passed'&&value.predecessor_disarmed?.tool_count<=42&&value.predecessor_disarmed?.capability_closure===true,'R42 predecessor public proof missing');
131
+ assert(value.successor?.version==='0.14.1'&&value.successor?.manifest_sha256===value.candidate.manifest_sha256,'R40 exact successor restore identity mismatch');
132
+ assert(value.successor_disarmed?.status==='passed'&&value.successor_disarmed?.capability_closure===true&&value.successor_disarmed?.coding_armed===false&&value.successor_disarmed?.autonomous_armed===false&&value.successor_disarmed?.desktop_armed===false,'R40 successor disarmed proof missing');
133
+ assert(value.immutable_slot?.protected===true&&value.immutable_slot?.development_root!==value.immutable_slot?.release_root,'R40 immutable-slot separation missing');
134
+ for(const key of ['tree_read','precondition_mutation','search','owned_process','observation','coding_loop','autonomy','interrupted_recovery','evidence_verification','compact_closure','full_surface','desktop_readonly','desktop_guarded_input','deterministic_memory']) assert(value.requirements?.[key]===true,`R43 parity requirement not proven: ${key}`);
135
+ return true;
136
+ }
137
+
138
+ export async function runReleaseParity(activationReceiptPath){
139
+ const active=await pointer();const candidateManifest=sha256(await readFile(path.join(root,'MANIFEST.SHA256')));
140
+ assert(active.version==='0.14.1','R43 parity requires active 0.14.1 candidate');
141
+ assert(active.manifest_sha256===candidateManifest,'active release is not canonical R40 candidate');
142
+ const activeConfig=await loadPowerShellDataFile(active.config_path);
143
+ const successorBridgeRootRaw=activeConfig?.Bridge?.WorkingDirectory;
144
+ const successorBridgeConfiguredSha=activeConfig?.Bridge?.ScriptSha256;
145
+ assert(typeof successorBridgeRootRaw==='string'&&path.isAbsolute(successorBridgeRootRaw),'R40 active bridge root missing');
146
+ assert(typeof successorBridgeConfiguredSha==='string'&&/^[0-9a-f]{64}$/.test(successorBridgeConfiguredSha),'R40 active bridge SHA missing');
147
+ const successorBridgeRoot=await realpath(path.resolve(successorBridgeRootRaw));
148
+ const successorBridgeActualSha=sha256(await readFile(path.join(successorBridgeRoot,'src','bridge.mjs')));
149
+ assert(successorBridgeActualSha===successorBridgeConfiguredSha,'R40 active bridge bytes do not match generation pin');
150
+ const successorBridge={root:successorBridgeRoot,sha256:successorBridgeActualSha};
151
+ const developmentRoot=await mutableCore(active);
152
+ const localFull=await probeR40FullSurface({packageRoot:active.release_root,generationRoot:active.generation_root,stateRoot});
153
+ const url=await publicUrl();
154
+ let publicCompact,autonomous,desktopGuarded;
155
+ try{
156
+ publicCompact=await runR40CompactParity(url);
157
+ autonomous=parseJsonOutput((await run(process.execPath,[path.join(root,'src','remote-mcp-autonomous-smoke-client.mjs'),url],{timeoutMs:900000})).stdout,'R40 autonomous compact parity');
158
+ assert(autonomous.status==='passed'&&autonomous.signed_release_verified===true,'R40 autonomous compact parity failed');
159
+ await run(ps,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',launcher,'armdesktop'],{timeoutMs:60000});
160
+ try{desktopGuarded=await runR40DesktopGuardedSmoke(url);}
161
+ finally{await run(ps,['-NoLogo','-NoProfile','-ExecutionPolicy','Bypass','-File',launcher,'disarmdesktop'],{timeoutMs:60000}).catch(()=>{});}
162
+ assert(desktopGuarded.status==='passed'&&desktopGuarded.native_injected===true&&desktopGuarded.action_receipts_verified===3,'R40 guarded Desktop public smoke failed');
163
+ }catch(error){await disarmAll().catch(()=>{});throw error;}
164
+ const deterministicMemory=await verifyR41Memory({memoryRoot:path.join(stateRoot,'evidence','autonomous','memory-r41',candidateManifest),
165
+ journalRoot:path.join(stateRoot,'evidence','autonomous','goals'),sourceReleaseManifest:candidateManifest,
166
+ publicKeyPath:path.join(stateRoot,'trust','ed25519-public.pem')});
167
+ assert(deterministicMemory.goal_count>=1&&deterministicMemory.snapshot_count>=1&&deterministicMemory.index_count>=1,'R41 live deterministic memory evidence missing');
168
+ await disarmAll();
169
+ const beforeRollback=await probeR40CompactDisarmed(url);
170
+ const rollbackPair=await scheduleDeferred('rollback',path.resolve(activationReceiptPath));
171
+ const predecessor=await pointer();
172
+ assert(predecessor.release_id===R43_PREDECESSOR_RELEASE_ID&&predecessor.manifest_sha256===R43_PREDECESSOR_MANIFEST&&predecessor.version==='0.14.0','rollback did not reach exact sealed R42 predecessor');
173
+ const predecessorDisarmed=await publicR40PredecessorDisarmed(url);
174
+ const stageRestore=await restoreFrozenStage({developmentRoot,releaseRoot:active.release_root,expectedManifestSha256:candidateManifest});
175
+ const restorePair=await scheduleDeferred('activate',candidateManifest,{bridgeRoot:successorBridge.root,bridgeScriptSha256:successorBridge.sha256});
176
+ const successor=await pointer();
177
+ assert(successor.version==='0.14.1'&&successor.manifest_sha256===candidateManifest,'restore did not return exact R40 candidate');
178
+ const successorDisarmed=await probeR40CompactDisarmed(url);
179
+ await disarmAll();
180
+
181
+ const evidence={
182
+ schema:'deadbyte.r43-parity.v1',status:'passed',completed_at_utc:new Date().toISOString(),execution_provider:'deadbyte_mcp',rdc_operation_count:0,
183
+ candidate:{release_id:active.release_id,version:active.version,manifest_sha256:candidateManifest},
184
+ immutable_slot:{protected:true,release_root:path.resolve(active.release_root),development_root:developmentRoot},
185
+ local_full:localFull,public_compact:publicCompact,autonomous,deterministic_memory:deterministicMemory,desktop_guarded:desktopGuarded,before_rollback_disarmed:beforeRollback,
186
+ rollback:{...rollbackPair.completed,scheduled_operation_id:rollbackPair.scheduled.operation_id},
187
+ predecessor:{release_id:predecessor.release_id,version:predecessor.version,manifest_sha256:predecessor.manifest_sha256},predecessor_disarmed:predecessorDisarmed,
188
+ stage_restore:stageRestore,
189
+ restore:{...restorePair.completed,scheduled_operation_id:restorePair.scheduled.operation_id},
190
+ successor:{release_id:successor.release_id,version:successor.version,manifest_sha256:successor.manifest_sha256},successor_disarmed:successorDisarmed,
191
+ requirements:{
192
+ tree_read:publicCompact.tree_entries>=0&&publicCompact.coding_stat_verified===true,
193
+ precondition_mutation:publicCompact.machine_fs_receipts_verified>=3,
194
+ search:publicCompact.coding_search_result_count>=1&&publicCompact.observation_search_result_count>=1,
195
+ owned_process:typeof publicCompact.process_session_id==='string'&&publicCompact.process_output_bytes>0,
196
+ observation:publicCompact.observation_receipts_verified>=2,
197
+ coding_loop:publicCompact.coding_receipts_verified===2,
198
+ autonomy:autonomous.signed_release_verified===true&&autonomous.observed_failure_before_replan===true,
199
+ interrupted_recovery:rollbackPair.completed.state==='completed'&&restorePair.completed.state==='completed',
200
+ evidence_verification:publicCompact.machine_fs_receipts_verified>=3&&autonomous.signed_release_verified===true,
201
+ compact_closure:publicCompact.capability_closure===true&&successorDisarmed.capability_closure===true,
202
+ full_surface:localFull.tool_count===80&&localFull.strict_output_schemas===true,
203
+ desktop_readonly:publicCompact.desktop_armed===false&&publicCompact.desktop_observation_receipt_verified===true&&publicCompact.desktop_grounding_receipt_verified===true,
204
+ desktop_guarded_input:desktopGuarded.native_injected===true&&desktopGuarded.replay_performed===false&&desktopGuarded.action_receipts_verified===3,
205
+ deterministic_memory:deterministicMemory.status==='passed'&&deterministicMemory.goal_count>=1&&deterministicMemory.snapshot_count>=1
206
+ }
207
+ };
208
+ validateParityEvidence(evidence);
209
+ const evidenceDir=path.join(stateRoot,'evidence','release');await mkdir(evidenceDir,{recursive:true});
210
+ const evidencePath=path.join(evidenceDir,`r43-parity-${candidateManifest.slice(0,16)}.json`);
211
+ const bytes=Buffer.from(`${JSON.stringify(evidence,null,2)}\n`,'utf8');await writeFile(evidencePath,bytes);
212
+ return {evidence,evidence_path:evidencePath,evidence_sha256:sha256(bytes)};
213
+ }
214
+
215
+ if(process.argv[1]&&path.resolve(process.argv[1])===fileURLToPath(import.meta.url)){
216
+ const receipt=process.argv[2];if(!receipt) throw new Error('usage: node scripts/release-parity-r43.mjs <activation-receipt.json>');
217
+ runReleaseParity(receipt).then(result=>console.log(JSON.stringify({status:'passed',...result},null,2))).catch(error=>{console.error(error instanceof Error?error.stack:String(error));process.exitCode=1;});
218
+ }