deadbyte-mcp 0.15.39 → 0.15.42

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 (100) hide show
  1. package/DEADBYTE-MCP.cmd +8 -4
  2. package/MANIFEST.SHA256 +99 -45
  3. package/PROVENANCE.json +90 -20
  4. package/README.txt +39 -18
  5. package/RELEASE.json +85 -20
  6. package/SBOM.cdx.json +2 -2
  7. package/TEST-MATRIX.json +134 -34
  8. package/bridge/package.json +1 -1
  9. package/controller/deadbyte-controller.ps1 +132 -12
  10. package/controller/deadbyte-process-policy.json +4 -4
  11. package/docs/R64-EVIDENCE.json +95 -0
  12. package/docs/R64-REFERENCE-GAP-MATRIX.json +98 -0
  13. package/docs/R64-SCOPE.json +41 -0
  14. package/docs/R65-AUTHORITY-CONTINUITY-DESIGN.json +27 -0
  15. package/docs/R65-REFERENCE-GAP-MATRIX.json +22 -0
  16. package/package.json +7 -4
  17. package/scripts/deploy-r48.mjs +123 -7
  18. package/scripts/gate-windows-r63-prepublish.ps1 +45 -0
  19. package/scripts/gate-windows-r64-prepublish.ps1 +68 -0
  20. package/scripts/gate-windows-r65-prepublish.ps1 +65 -0
  21. package/scripts/npm-publication-r65.mjs +139 -0
  22. package/scripts/npm-release-r48.mjs +62 -37
  23. package/scripts/r64-predecessor-reproducer.mjs +32 -0
  24. package/scripts/r64-read-benchmark.mjs +84 -0
  25. package/scripts/r65-canonical-full.mjs +45 -0
  26. package/scripts/r65-focused.mjs +37 -0
  27. package/scripts/verify-r65-parent-source.mjs +75 -0
  28. package/src/activation-continuity-engine-r65.mjs +225 -0
  29. package/src/activation-lock-r65.mjs +155 -0
  30. package/src/activation-preflight-r65.mjs +197 -0
  31. package/src/authority-continuity-r65.mjs +541 -0
  32. package/src/authority-epoch-cli-r65.mjs +10 -0
  33. package/src/autonomous-policy.mjs +7 -3
  34. package/src/coding-plane.mjs +12 -3
  35. package/src/compact-gateway-mcp-tools.mjs +1 -1
  36. package/src/deadbyte-cli.mjs +16 -2
  37. package/src/desktop-policy-r40.mjs +6 -3
  38. package/src/doctor-transactions-r58.mjs +1 -1
  39. package/src/host-plane.mjs +9 -3
  40. package/src/machine-fs-mcp-tools.mjs +1 -1
  41. package/src/machine-fs.mjs +7 -4
  42. package/src/process-policy.mjs +7 -4
  43. package/src/remote-authority.mjs +20 -1
  44. package/src/runtime-update.mjs +15 -5
  45. package/src/version.mjs +1 -1
  46. package/test/audit-context.test.mjs +15 -4
  47. package/test/autonomous-local-supervisor.test.mjs +7 -6
  48. package/test/autonomous-supervisor-integration.test.mjs +8 -7
  49. package/test/capability-resolver.test.mjs +11 -5
  50. package/test/codex-autonomous-r44.test.mjs +7 -6
  51. package/test/coding-observation.test.mjs +4 -3
  52. package/test/commander-real-parity-r47.test.mjs +5 -4
  53. package/test/commander-torture-r47.test.mjs +5 -4
  54. package/test/desktop-policy-r40.test.mjs +6 -4
  55. package/test/desktop-runtime-r40.test.mjs +8 -3
  56. package/test/host-inline-r45.test.mjs +4 -3
  57. package/test/machine-fs-runtime.test.mjs +4 -3
  58. package/test/process-longrun-r36.test.mjs +3 -2
  59. package/test/process-policy.test.mjs +10 -6
  60. package/test/process-runtime.test.mjs +9 -6
  61. package/test/r52-host-revocation.test.mjs +1 -0
  62. package/test/r59-tool-surface-compat.test.mjs +14 -4
  63. package/test/r62-release-contract.test.mjs +2 -1
  64. package/test/r63-one-shot-coherence.test.mjs +38 -0
  65. package/test/r63-release-contract.test.mjs +59 -0
  66. package/test/r64-machine-fs-large-read.test.mjs +136 -0
  67. package/test/r64-release-contract.test.mjs +52 -0
  68. package/test/r65-activation-lock-recovery.test.mjs +72 -0
  69. package/test/r65-activation-lock.test.mjs +59 -0
  70. package/test/r65-activation-orchestration.test.mjs +179 -0
  71. package/test/r65-activation-preflight.test.mjs +35 -0
  72. package/test/r65-authority-continuity-decision.test.mjs +58 -0
  73. package/test/r65-authority-durable-policy-binding.test.mjs +34 -0
  74. package/test/r65-authority-epoch-cli.test.mjs +125 -0
  75. package/test/r65-authority-epoch-races.test.mjs +87 -0
  76. package/test/r65-authority-epoch-recovery.test.mjs +82 -0
  77. package/test/r65-authority-epoch-store.test.mjs +94 -0
  78. package/test/r65-authority-fixture.mjs +41 -0
  79. package/test/r65-authority-grant-capture.test.mjs +37 -0
  80. package/test/r65-authority-observation-epoch.test.mjs +25 -0
  81. package/test/r65-authority-policy-envelope.test.mjs +46 -0
  82. package/test/r65-authority-restored-safe.test.mjs +75 -0
  83. package/test/r65-authority-runtime-epoch.test.mjs +115 -0
  84. package/test/r65-authority-runtime-policy-binding.test.mjs +29 -0
  85. package/test/r65-authority-test-trust.mjs +20 -0
  86. package/test/r65-cli-invocation.test.mjs +38 -0
  87. package/test/r65-controller-authority-epoch-live.test.mjs +100 -0
  88. package/test/r65-controller-authority-epoch.test.mjs +37 -0
  89. package/test/r65-deploy-preflight.test.mjs +55 -0
  90. package/test/r65-epoch-native-activation-integration.test.mjs +141 -0
  91. package/test/r65-epoch-native-continuity-engine.test.mjs +112 -0
  92. package/test/r65-epoch-native-cross-plane.test.mjs +95 -0
  93. package/test/r65-legacy-authority-migration.test.mjs +63 -0
  94. package/test/r65-legacy-auto-restore-rejection.test.mjs +17 -0
  95. package/test/r65-npm-publication.test.mjs +114 -0
  96. package/test/r65-parent-source-verifier.test.mjs +63 -0
  97. package/test/r65-release-contract.test.mjs +74 -0
  98. package/test/r65-transaction-precondition.test.mjs +36 -0
  99. package/test/remote-session-cli.test.mjs +13 -11
  100. package/test/standing-grants.test.mjs +20 -4
@@ -1,6 +1,9 @@
1
1
  import { spawnSync } from 'node:child_process';
2
- import { verifyPublishedTarballIdentity } from './npm-artifact-identity-r61.mjs';
3
- import { mkdtemp, readFile, rm, unlink } from 'node:fs/promises';
2
+ import { createHash } from 'node:crypto';
3
+ import { reconcileNpmPublication } from './npm-publication-r65.mjs';
4
+ import { mkdtemp, readFile, rm, unlink, mkdir, rename } from 'node:fs/promises';
5
+ import { existsSync } from 'node:fs';
6
+ import { resolveStateRoot } from '../src/state-root.mjs';
4
7
  import path from 'node:path';
5
8
  import os from 'node:os';
6
9
  import { fileURLToPath } from 'node:url';
@@ -10,7 +13,7 @@ const node = process.execPath;
10
13
  const npmCli = process.env.npm_execpath || path.join(path.dirname(process.execPath), 'node_modules', 'npm', 'bin', 'npm-cli.js');
11
14
 
12
15
  function run(command, args, options = {}) {
13
- const { cwd = root, timeout = 180000 } = options;
16
+ const { cwd = root, timeout = 180000, env=process.env } = options;
14
17
  const r = spawnSync(command, args, {
15
18
  cwd,
16
19
  encoding: 'utf8',
@@ -18,6 +21,7 @@ function run(command, args, options = {}) {
18
21
  stdio: ['ignore', 'pipe', 'pipe'],
19
22
  shell: false,
20
23
  windowsHide: true,
24
+ env,
21
25
  });
22
26
  if (r.error) throw r.error;
23
27
  if (r.status !== 0) {
@@ -94,30 +98,34 @@ async function main() {
94
98
  const existingText = (existing.stdout || '').trim();
95
99
  const isAlreadyPublished = existing.status === 0 && existingText && existingText !== 'null';
96
100
 
97
- if (isAlreadyPublished) {
98
- if (!isVerifyOnly) {
99
- throw new Error(`deadbyte-mcp@${version} is already published on registry: ${existingText}`);
100
- } else {
101
- console.log(`Notice: deadbyte-mcp@${version} is already published on registry (${existingText}), proceeding with pre-publish verification only.`);
102
- }
103
- }
101
+ if (isAlreadyPublished) console.log(`Notice: deadbyte-mcp@${version} exists on registry (${existingText}); exact-byte reconciliation is required.`);
104
102
 
105
103
  console.log('[2/7] Pre-pack gates: verifying working tree manifest and doctor...');
106
104
  run(node, [path.join(root, 'scripts', 'release-manifest.mjs'), 'verify']);
107
- run(node, [path.join(root, 'src', 'deadbyte-cli.mjs'), 'doctor']);
105
+ const doctorState=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-release-doctor-'));
106
+ try{run(node,[path.join(root,'src','deadbyte-cli.mjs'),'doctor'],{env:{...process.env,DEADBYTE_STATE_ROOT:doctorState}});}
107
+ finally{await rm(doctorState,{recursive:true,force:true});}
108
108
 
109
109
  console.log('[3/7] Packing artifact with npm pack...');
110
- const packed = parseJson(runNpm(['pack', '--json'], { timeout: 180000 }));
111
- const packRecord = Array.isArray(packed) ? packed[0] : packed?.[pkg.name];
110
+ const publicationDir=isVerifyOnly?null:path.join(resolveStateRoot(),'evidence','npm-publication',version);
111
+ const preservedTarball=publicationDir?path.join(publicationDir,`deadbyte-mcp-${version}.tgz`):null;
112
+ const resuming=Boolean(preservedTarball&&existsSync(path.join(publicationDir,'claim.json')));
113
+ if(publicationDir)await mkdir(publicationDir,{recursive:true});
114
+ if(resuming&&!existsSync(preservedTarball))throw new Error('immutable npm publication claim exists but exact local tarball is missing; manual artifact reconciliation required');
115
+ if(!resuming&&preservedTarball&&existsSync(preservedTarball))throw new Error('unclaimed preserved npm tarball exists; inspect artifact evidence before another pack');
116
+ const packed=resuming?null:parseJson(runNpm(['pack', '--json'], { timeout: 180000 }));
117
+ const packRecord=resuming?{filename:path.basename(preservedTarball)}:(Array.isArray(packed) ? packed[0] : packed?.[pkg.name]);
112
118
  const filename = packRecord?.filename;
113
119
  if (!filename) throw new Error('npm pack did not return a tarball filename');
114
- const tarball = path.join(root, filename);
120
+ const tarball = resuming?preservedTarball:path.join(root, filename);
115
121
  let releaseSucceeded = false;
116
122
  let publishAttempted = false;
123
+ let releasePending = false;
117
124
 
118
125
  try {
119
126
  console.log('[4/7] Verifying packed artifact file surface against MANIFEST.SHA256 and packaging contract...');
120
127
  const manifestText = await readFile(path.join(root, 'MANIFEST.SHA256'), 'utf8');
128
+ const manifestSha256=createHash('sha256').update(manifestText).digest('hex');
121
129
  const manifestEntries = new Set();
122
130
  for (const line of manifestText.split(/\r?\n/)) {
123
131
  if (!line) continue;
@@ -168,7 +176,7 @@ async function main() {
168
176
  }
169
177
 
170
178
  run(node, [path.join(extractedPackage, 'src', 'deadbyte-cli.mjs'), 'doctor'], {
171
- cwd: extractedPackage,
179
+ cwd: extractedPackage,env:{...process.env,DEADBYTE_STATE_ROOT:path.join(sandbox,'state')},
172
180
  });
173
181
 
174
182
  console.log('Artifact isolation gate PASS (clean doctor and version check on unpacked tarball in sandbox)');
@@ -177,36 +185,48 @@ async function main() {
177
185
  }
178
186
 
179
187
  if (isVerifyOnly) {
188
+ const packedBytes = await readFile(tarball);
189
+ const sha256 = createHash('sha256').update(packedBytes).digest('hex');
190
+ const sha512Integrity = `sha512-${createHash('sha512').update(packedBytes).digest('base64')}`;
191
+ if (packRecord.integrity !== sha512Integrity) throw new Error('npm pack integrity differs from packed tarball bytes');
192
+ console.log('VERIFIED_TARBALL ' + JSON.stringify({filename,bytes:packedBytes.length,sha256,integrity:sha512Integrity,shasum:packRecord.shasum}));
180
193
  console.log('[6/7] [VERIFY-ONLY] Skipping npm publish.');
181
194
  console.log('[7/7] [VERIFY-ONLY] Skipping external registry smoke test.');
182
195
  console.log('\nVERIFY-ONLY PIPELINE PASS: All pre-pack, artifact surface, and isolated sandbox gates passed successfully.');
183
196
  return;
184
197
  }
185
198
 
186
- const localBytes = await readFile(tarball);
199
+ if(!resuming)await rename(tarball,preservedTarball);
200
+ const publishTarball=preservedTarball;
201
+ const localBytes = await readFile(publishTarball);
202
+ const localIntegrity=`sha512-${createHash('sha512').update(localBytes).digest('base64')}`;
203
+ if(packRecord.integrity&&packRecord.integrity!==localIntegrity)throw new Error('npm packed artifact integrity changed before publication');
187
204
 
188
205
  console.log('[6/7] Publishing artifact to npm registry...');
189
206
  publishAttempted = true;
190
- let publishOut;
191
- try {
192
- publishOut = runNpmInteractive(['publish', tarball, '--access', 'public', '--auth-type=web'], { timeout: 300000 });
193
- } catch (publishError) {
194
- const detail = String(publishError?.message || publishError);
195
- if (/EOTP|one-time password|two-factor|2FA|security.?key|authentication/i.test(detail)) {
196
- console.error('Publish requires interactive npm authentication (Security Key/WebAuthn).');
197
- console.error('Tarball preserved for retry: ' + tarball);
198
- }
199
- throw publishError;
207
+ const reconciliation=await reconcileNpmPublication({recordPath:publicationDir,version,manifestSha256,localBytes,
208
+ publish:async()=>runNpmInteractive(['publish',publishTarball,'--access','public','--auth-type=web'],{timeout:300000}),
209
+ lookup:async()=>{
210
+ try{
211
+ const viewed=parseJson(runNpm(['view',`deadbyte-mcp@${version}`,'version','dist.integrity','dist.shasum','dist.tarball','--json'],{timeout:120000}));
212
+ return Array.isArray(viewed)?viewed[0]:viewed;
213
+ }catch(error){if(/E404|404 Not Found/.test(String(error?.message)))return null;throw error;}
214
+ },
215
+ tags:async()=>parseJson(runNpm(['view','deadbyte-mcp','dist-tags','--json'],{timeout:120000})),
216
+ fetchTarball:async published=>{
217
+ const response=await fetch(published?.dist?.tarball,{signal:AbortSignal.timeout(120000)});
218
+ if(!response.ok)throw Object.assign(new Error(`registry tarball fetch failed status=${response.status}`),{status:response.status});
219
+ return Buffer.from(await response.arrayBuffer());
220
+ }});
221
+ if(reconciliation.state!=='REGISTRY_IDENTITY_VERIFIED'){
222
+ console.log('RELEASE_PENDING '+JSON.stringify({state:reconciliation.state,version,tarball:publishTarball,record_path:publicationDir,reason:reconciliation.reason??null}));
223
+ releasePending=true;
224
+ process.exitCode=2;return;
200
225
  }
201
- const viewed = parseJson(runNpm(['view', `deadbyte-mcp@${version}`, 'version', 'dist.integrity', 'dist.shasum', 'dist.tarball', '--json'], { timeout: 120000 }));
202
- const published = Array.isArray(viewed) ? viewed[0] : viewed;
203
- const dist = published?.dist ?? published;
204
- if(typeof dist?.tarball !== 'string')throw new Error('published registry tarball URL missing');
205
- const registryResponse = await fetch(dist.tarball,{signal:AbortSignal.timeout(120000)});
206
- if(!registryResponse.ok) throw new Error(`registry tarball fetch failed status=${registryResponse.status}`);
207
- const registryBytes = Buffer.from(await registryResponse.arrayBuffer());
208
- const tags = parseJson(runNpm(['view', 'deadbyte-mcp', 'dist-tags', '--json'], { timeout: 120000 }));
209
- const identity=verifyPublishedTarballIdentity({version,localBytes,registryBytes,published,tags});
226
+ const identity=reconciliation.identity;
227
+ const published={version,dist:{integrity:identity.npm_integrity,shasum:identity.shasum}};
228
+ const tags={latest:version};
229
+ const publishOut='registry identity verified by durable reconciliation';
210
230
 
211
231
  console.log('[7/7] Post-publish external registry smoke test (executed outside repo in temp)...');
212
232
  const tempDir = os.tmpdir();
@@ -221,6 +241,7 @@ async function main() {
221
241
  const externalDoctor = runNpm(['exec', '--yes', `--package=deadbyte-mcp@${version}`, '--', 'deadbyte-mcp', 'doctor'], {
222
242
  cwd: tempDir,
223
243
  timeout: 300000,
244
+ env:{...process.env,DEADBYTE_STATE_ROOT:path.join(publicationDir,'external-doctor-state')},
224
245
  });
225
246
 
226
247
  if(!publishOnly){
@@ -247,10 +268,14 @@ async function main() {
247
268
  }, null, 2));
248
269
 
249
270
  } finally {
250
- if ((releaseSucceeded && !publishOnly) || !publishAttempted) {
271
+ if (isVerifyOnly || (!publishAttempted&&!publicationDir)) {
251
272
  await unlink(tarball).catch(() => {});
273
+ } else if(releasePending){
274
+ console.log('Publication processing or reconciliation pending; exact tarball preserved: '+preservedTarball);
275
+ } else if(releaseSucceeded){
276
+ console.log('Verified release tarball retained for audit: '+preservedTarball);
252
277
  } else {
253
- console.error('Release artifact preserved after failure: ' + tarball);
278
+ console.error('Release artifact preserved for reconciliation: ' + preservedTarball);
254
279
  }
255
280
  }
256
281
  }
@@ -0,0 +1,32 @@
1
+ import {mkdtemp,mkdir,writeFile,rm} from 'node:fs/promises';
2
+ import {tmpdir} from 'node:os';
3
+ import path from 'node:path';
4
+ import {pathToFileURL} from 'node:url';
5
+
6
+ const sourceRoot=process.argv[2];
7
+ if(!sourceRoot||!path.isAbsolute(sourceRoot))throw new Error('absolute predecessor root required');
8
+ const load=name=>import(pathToFileURL(path.join(sourceRoot,name)).href);
9
+ const [{loadCodingPolicy},{createMachineFsRuntime},{generateTrustKeypair},{machineFsGatewayInputSchema},{registerMachineFsTools}]=await Promise.all([
10
+ load('src/coding-plane.mjs'),load('src/machine-fs.mjs'),load('src/trust.mjs'),
11
+ load('src/compact-gateway-mcp-tools.mjs'),load('src/machine-fs-mcp-tools.mjs')
12
+ ]);
13
+ const root=await mkdtemp(path.join(tmpdir(),'deadbyte-r64-red-'));
14
+ try{
15
+ const project=path.join(root,'project');await mkdir(project);
16
+ await writeFile(path.join(project,'large.bin'),Buffer.alloc(4*1024*1024+64,0x52));
17
+ const policyPath=path.join(root,'policy.json');
18
+ await writeFile(policyPath,JSON.stringify({schema:'deadbyte.coding-policy.v1',enabled:true,lease_file:path.join(root,'grant.json'),evidence_dir:path.join(root,'evidence'),roots:{project:{path:project,read:true,write:false,exec:false,deny_paths:[]}},commands:{},max_read_bytes:4*1024*1024,max_write_bytes:65536}));
19
+ const policy=await loadCodingPolicy(policyPath);
20
+ const keys=await generateTrustKeypair({privateKeyPath:path.join(root,'private.pem'),publicKeyPath:path.join(root,'public.pem')});
21
+ const runtime=createMachineFsRuntime({policy,signingKeyPath:keys.privateKeyPath,verifyKeyPath:keys.publicKeyPath});
22
+ const first=await runtime.read({rootId:'project',relativePath:'large.bin',offset:2,maxBytes:4*1024*1024});
23
+ const args={root_id:'project',path:'large.bin',offset:first.next_offset,max_bytes:64,hash_file:false,timeout_ms:30000};
24
+ const server={registerTool(name,definition){if(name==='machine_fs_read')this.read=definition;}};
25
+ registerMachineFsTools(server,{runtime:{}});
26
+ let runtimeError=null;
27
+ try{await runtime.read({rootId:'project',relativePath:'large.bin',offset:first.next_offset,maxBytes:64});}
28
+ catch(error){runtimeError=String(error?.message||error);}
29
+ const result={source_root:sourceRoot,page_two_offset:first.next_offset,full_schema_accepts:server.read.inputSchema.safeParse(args).success,compact_schema_accepts:machineFsGatewayInputSchema.safeParse({op:'read',...args}).success,runtime_error:runtimeError};
30
+ console.log(JSON.stringify(result));
31
+ if(result.full_schema_accepts||result.compact_schema_accepts||!runtimeError)process.exitCode=1;
32
+ }finally{await rm(root,{recursive:true,force:true});}
@@ -0,0 +1,84 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {mkdtemp,mkdir,readFile,rm,writeFile} from 'node:fs/promises';
3
+ import {performance} from 'node:perf_hooks';
4
+ import path from 'node:path';
5
+ import {pathToFileURL} from 'node:url';
6
+
7
+ const [beforeRoot,afterRoot,scratchRoot,outputPath]=process.argv.slice(2);
8
+ if([beforeRoot,afterRoot,scratchRoot,outputPath].some(value=>!value||!path.isAbsolute(value)))throw new Error('four absolute paths required: R63 R64 scratch output');
9
+ const rounds=7,operations=400,concurrency=4;
10
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
11
+ const percentile=(values,p)=>[...values].sort((a,b)=>a-b)[Math.ceil(values.length*p)-1];
12
+ await mkdir(scratchRoot,{recursive:true});
13
+ const scratch=await mkdtemp(path.join(scratchRoot,'read-bench-'));
14
+ try{
15
+ const project=path.join(scratch,'project');
16
+ await mkdir(project);
17
+ const file=path.join(project,'fixture.bin');
18
+ const content=Buffer.alloc(4*1024*1024+131072,0x52);
19
+ await writeFile(file,content);
20
+ const policyPath=path.join(scratch,'policy.json');
21
+ await writeFile(policyPath,JSON.stringify({schema:'deadbyte.coding-policy.v1',enabled:true,
22
+ lease_file:path.join(scratch,'grant.json'),evidence_dir:path.join(scratch,'evidence'),
23
+ roots:{project:{path:project,read:true,write:false,exec:false,deny_paths:[]}},
24
+ commands:{},max_read_bytes:4*1024*1024,max_write_bytes:65536}));
25
+ const rows=[];
26
+ for(let round=0;round<rounds;round++){
27
+ for(const [label,root] of (round%2?[['after',afterRoot],['before',beforeRoot]]:[['before',beforeRoot],['after',afterRoot]])){
28
+ const url=name=>pathToFileURL(path.join(root,name)).href;
29
+ const [{loadCodingPolicy},{createMachineFsRuntime},{generateTrustKeypair},{createBridgeGovernor}]=await Promise.all([
30
+ import(url('src/coding-plane.mjs')),import(url('src/machine-fs.mjs')),
31
+ import(url('src/trust.mjs')),import(url('bridge/src/r40-governor.mjs'))
32
+ ]);
33
+ const keys=await generateTrustKeypair({privateKeyPath:path.join(scratch,`private-${label}-${round}.pem`),publicKeyPath:path.join(scratch,`public-${label}-${round}.pem`)});
34
+ const policy=await loadCodingPolicy(policyPath);
35
+ const runtime=createMachineFsRuntime({policy,signingKeyPath:keys.privateKeyPath,verifyKeyPath:keys.publicKeyPath});
36
+ const governor=createBridgeGovernor();
37
+ const latencies=[],control=[],errors=[];
38
+ let next=0,peakRss=process.memoryUsage().rss;
39
+ const started=performance.now();
40
+ async function bulkWorker(){
41
+ for(;;){
42
+ const index=next++;
43
+ if(index>=operations)return;
44
+ const mark=performance.now();
45
+ const ticket=await governor.acquire('machine_fs',{op:'read'});
46
+ try{
47
+ const result=await runtime.read({rootId:'project',relativePath:'fixture.bin',offset:(index%32)*65536,maxBytes:65536});
48
+ if(result.status!=='ok'||Buffer.from(result.data_base64,'base64').length!==65536)throw new Error('read oracle failed');
49
+ }catch(error){errors.push(String(error));}
50
+ finally{ticket.release();latencies.push(performance.now()-mark);peakRss=Math.max(peakRss,process.memoryUsage().rss);}
51
+ }
52
+ }
53
+ async function controlWorker(){
54
+ for(let index=0;index<operations;index++){
55
+ const mark=performance.now();
56
+ const ticket=await governor.acquire(index%2?'machine_status':'machine_ping');
57
+ try{if(index%2)await readFile(policyPath);else sha(Buffer.from(`ping-${index}`));}
58
+ finally{ticket.release();control.push(performance.now()-mark);}
59
+ }
60
+ }
61
+ await Promise.all([...Array.from({length:concurrency},()=>bulkWorker()),controlWorker()]);
62
+ const elapsed=performance.now()-started;
63
+ await governor.close();
64
+ const boundaryStart=performance.now();
65
+ let boundary={status:'unknown'};
66
+ try{
67
+ const first=await runtime.read({rootId:'project',relativePath:'fixture.bin',offset:65536,maxBytes:4*1024*1024});
68
+ const second=await runtime.read({rootId:'project',relativePath:'fixture.bin',offset:first.next_offset,maxBytes:65536});
69
+ if(first.next_offset<=4*1024*1024||second.eof!==true||Buffer.from(second.data_base64,'base64').length!==65536)throw new Error('cross-boundary oracle failed');
70
+ boundary={status:'pass',page_two_offset:first.next_offset,elapsed_ms:performance.now()-boundaryStart};
71
+ }catch(error){boundary={status:'rejected',reason:String(error?.message||error),elapsed_ms:performance.now()-boundaryStart};}
72
+ if(label==='before'&&boundary.status!=='rejected')errors.push('R63 unexpectedly accepted page two');
73
+ if(label==='after'&&boundary.status!=='pass')errors.push('R64 cross-boundary paging failed');
74
+ rows.push({round,label,source_sha256:sha(await readFile(path.join(root,'src/machine-fs.mjs'))),
75
+ ops:latencies.length,ops_per_second:operations*1000/elapsed,p50_ms:percentile(latencies,.5),p95_ms:percentile(latencies,.95),
76
+ control_p95_ms:percentile(control,.95),peak_rss_bytes:peakRss,boundary,errors});
77
+ }
78
+ }
79
+ const report={schema:'deadbyte.r64.read-benchmark.v1',node:process.version,rounds,operations_per_round:operations,concurrency,
80
+ source_roots:{before:beforeRoot,after:afterRoot},rows,
81
+ limitations:['same-host sequential alternating runs; OS scheduling noise remains','comparable throughput rows use inherited sub-4-MiB reads; boundary timings are separate because R63 cannot execute page two','control probe uses governor and local read/hash, not public MCP machine_ping or machine_status']};
82
+ await writeFile(outputPath,JSON.stringify(report,null,2)+'\n',{flag:'wx'});
83
+ console.log(JSON.stringify({output_path:outputPath,rows:rows.length,errors:rows.reduce((sum,row)=>sum+row.errors.length,0)}));
84
+ }finally{await rm(scratch,{recursive:true,force:true});}
@@ -0,0 +1,45 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {mkdirSync,readdirSync,writeFileSync} from 'node:fs';
3
+ import {spawnSync} from 'node:child_process';
4
+ import path from 'node:path';
5
+
6
+ const runId=process.argv[2]??'manual';
7
+ if(!/^[A-Za-z0-9._-]{1,96}$/.test(runId))throw new Error('invalid run id');
8
+ const testDir=path.join(process.cwd(),'test');
9
+ const tests=readdirSync(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
+ const startedAt=new Date().toISOString();
14
+ const run=spawnSync(process.execPath,['--test','--test-concurrency=4',...tests],{
15
+ cwd:process.cwd(),
16
+ encoding:'utf8',
17
+ maxBuffer:128*1024*1024,
18
+ windowsHide:true,
19
+ shell:false
20
+ });
21
+ const stdout=run.stdout||'',stderr=run.stderr||'';
22
+ const evidenceDir=path.resolve(process.cwd(),'..','..','testing','0.15.42-r65','full-runs',runId);
23
+ mkdirSync(evidenceDir,{recursive:true});
24
+ writeFileSync(path.join(evidenceDir,'stdout.log'),stdout,'utf8');
25
+ writeFileSync(path.join(evidenceDir,'stderr.log'),stderr,'utf8');
26
+ const grab=(name)=>{const m=stdout.match(new RegExp('(?:ℹ|#)\\s*'+name+'\\s+(\\d+)','i'));return m?Number(m[1]):null;};
27
+ const result={
28
+ schema:'deadbyte.r65-full-run.v1',
29
+ run_id:runId,
30
+ started_at_utc:startedAt,
31
+ finished_at_utc:new Date().toISOString(),
32
+ command:[process.execPath,'--test','--test-concurrency=4',...tests],
33
+ test_files:tests.length,
34
+ exit_code:run.status??null,
35
+ signal:run.signal??null,
36
+ error:run.error?String(run.error.stack||run.error):null,
37
+ tests:grab('tests'),pass:grab('pass'),fail:grab('fail'),skipped:grab('skipped'),
38
+ stdout_sha256:createHash('sha256').update(stdout).digest('hex'),
39
+ stderr_sha256:createHash('sha256').update(stderr).digest('hex')
40
+ };
41
+ writeFileSync(path.join(evidenceDir,'result.json'),JSON.stringify(result,null,2)+'\n','utf8');
42
+ process.stdout.write(stdout);
43
+ process.stderr.write(stderr);
44
+ if(run.error)process.stderr.write(String(run.error.stack||run.error)+'\n');
45
+ process.exit(run.status??1);
@@ -0,0 +1,37 @@
1
+ import {spawnSync} from 'node:child_process';
2
+
3
+ const tests=[
4
+ 'test/r65-activation-lock.test.mjs',
5
+ 'test/r65-activation-lock-recovery.test.mjs',
6
+ 'test/r65-activation-orchestration.test.mjs',
7
+ 'test/r65-activation-preflight.test.mjs',
8
+ 'test/r65-authority-continuity-decision.test.mjs',
9
+ 'test/r65-authority-durable-policy-binding.test.mjs',
10
+ 'test/r65-authority-epoch-cli.test.mjs',
11
+ 'test/r65-authority-epoch-races.test.mjs',
12
+ 'test/r65-authority-epoch-recovery.test.mjs',
13
+ 'test/r65-authority-epoch-store.test.mjs',
14
+ 'test/r65-authority-grant-capture.test.mjs',
15
+ 'test/r65-authority-observation-epoch.test.mjs',
16
+ 'test/r65-authority-policy-envelope.test.mjs',
17
+ 'test/r65-authority-runtime-epoch.test.mjs',
18
+ 'test/r65-authority-runtime-policy-binding.test.mjs',
19
+ 'test/r65-authority-restored-safe.test.mjs',
20
+ 'test/r65-controller-authority-epoch.test.mjs',
21
+ 'test/r65-controller-authority-epoch-live.test.mjs',
22
+ 'test/r65-deploy-preflight.test.mjs',
23
+ 'test/r65-epoch-native-activation-integration.test.mjs',
24
+ 'test/r65-epoch-native-continuity-engine.test.mjs',
25
+ 'test/r65-epoch-native-cross-plane.test.mjs',
26
+ 'test/r65-legacy-authority-migration.test.mjs',
27
+ 'test/r65-legacy-auto-restore-rejection.test.mjs',
28
+ 'test/r65-parent-source-verifier.test.mjs',
29
+ 'test/r65-release-contract.test.mjs',
30
+ 'test/r65-transaction-precondition.test.mjs'
31
+ ];
32
+ const run=spawnSync(process.execPath,['--test','--test-concurrency=2',...tests],{
33
+ cwd:process.cwd(),encoding:'utf8',maxBuffer:64*1024*1024,windowsHide:true
34
+ });
35
+ process.stdout.write(run.stdout||'');
36
+ process.stderr.write(run.stderr||'');
37
+ process.exit(run.status??1);
@@ -0,0 +1,75 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {lstat,readFile,realpath} from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import {fileURLToPath} from 'node:url';
5
+
6
+ const HEX64=/^[0-9a-f]{64}$/;
7
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
8
+
9
+ function parseArgs(argv){
10
+ const out={root:null,expectedManifestSha256:null};
11
+ for(let i=0;i<argv.length;i++){
12
+ const arg=argv[i];
13
+ if(arg==='--root')out.root=argv[++i]??null;
14
+ else if(arg==='--expected-manifest-sha256')out.expectedManifestSha256=argv[++i]??null;
15
+ else throw new Error('unknown argument '+arg);
16
+ }
17
+ if(typeof out.root!=='string'||out.root.length<1)throw new Error('--root required');
18
+ if(!HEX64.test(String(out.expectedManifestSha256)))throw new Error('--expected-manifest-sha256 must be lowercase hex');
19
+ return out;
20
+ }
21
+
22
+ function parseManifest(text){
23
+ const entries=[];
24
+ const seen=new Set();
25
+ for(const raw of text.split(/\r?\n/)){
26
+ if(raw==='')continue;
27
+ const match=/^([0-9a-f]{64}) (.+)$/.exec(raw);
28
+ if(!match)throw new Error('manifest line invalid');
29
+ const rel=match[2];
30
+ if(rel.includes('\\')||path.posix.isAbsolute(rel)||rel==='.'||rel.split('/').includes('..')||path.posix.normalize(rel)!==rel)
31
+ throw new Error('manifest path invalid: '+rel);
32
+ if(seen.has(rel))throw new Error('manifest duplicate path: '+rel);
33
+ seen.add(rel);
34
+ entries.push({sha256:match[1],rel});
35
+ }
36
+ if(entries.length<1)throw new Error('manifest has no entries');
37
+ return entries;
38
+ }
39
+
40
+ export async function verifyDeclaredParentSource({root,expectedManifestSha256}){
41
+ const absolute=path.resolve(root);
42
+ const rootReal=await realpath(absolute);
43
+ const manifestPath=path.join(absolute,'MANIFEST.SHA256');
44
+ const manifestBytes=await readFile(manifestPath);
45
+ const actualManifestSha=sha(manifestBytes);
46
+ if(actualManifestSha!==expectedManifestSha256)
47
+ throw new Error(`manifest SHA-256 mismatch expected=${expectedManifestSha256} actual=${actualManifestSha}`);
48
+ const entries=parseManifest(manifestBytes.toString('utf8'));
49
+ for(const entry of entries){
50
+ const target=path.resolve(absolute,...entry.rel.split('/'));
51
+ const info=await lstat(target).catch(error=>{
52
+ if(error?.code==='ENOENT')throw new Error('listed file missing: '+entry.rel);
53
+ throw error;
54
+ });
55
+ if(!info.isFile()||info.isSymbolicLink())throw new Error('listed path is not a regular file: '+entry.rel);
56
+ const targetReal=await realpath(target);
57
+ const prefix=rootReal.endsWith(path.sep)?rootReal:rootReal+path.sep;
58
+ if(targetReal!==rootReal&&!targetReal.startsWith(prefix))throw new Error('listed path escapes root: '+entry.rel);
59
+ const actual=sha(await readFile(target));
60
+ if(actual!==entry.sha256)throw new Error(`hash mismatch ${entry.rel} expected=${entry.sha256} actual=${actual}`);
61
+ }
62
+ return Object.freeze({files:entries.length,manifest_sha256:actualManifestSha,root:rootReal});
63
+ }
64
+
65
+ const invoked=process.argv[1]&&path.resolve(process.argv[1])===path.resolve(fileURLToPath(import.meta.url));
66
+ if(invoked){
67
+ try{
68
+ const opts=parseArgs(process.argv.slice(2));
69
+ const result=await verifyDeclaredParentSource(opts);
70
+ console.log(`R65_PARENT_SOURCE_VERIFY_OK files=${result.files} manifest_sha256=${result.manifest_sha256}`);
71
+ }catch(error){
72
+ console.error('R65_PARENT_SOURCE_VERIFY_FAIL '+String(error?.stack??error));
73
+ process.exitCode=1;
74
+ }
75
+ }