deadbyte-mcp 0.15.39 → 0.15.41

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.
@@ -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});}
@@ -28,7 +28,7 @@ export const codingInspectInputSchema=z.discriminatedUnion('op',[
28
28
  export const machineFsGatewayInputSchema=z.discriminatedUnion('op',[
29
29
  z.strictObject({op:z.literal('stat'),root_id:id,path:rel.default('.'),hash:z.boolean().default(false)}),
30
30
  z.strictObject({op:z.literal('list'),root_id:id,path:rel.default('.'),cursor,limit:z.number().int().min(1).max(1000).default(100),hash_files:z.boolean().default(false)}),
31
- z.strictObject({op:z.literal('read'),root_id:id,path:rel,offset:z.number().int().min(-4*1024*1024).max(4*1024*1024).default(0),max_bytes:z.number().int().min(1).max(4*1024*1024).default(65536),hash_file:z.boolean().default(false),timeout_ms:z.number().int().min(100).max(180000).default(30000)}),
31
+ z.strictObject({op:z.literal('read'),root_id:id,path:rel,offset:z.number().int().min(-4*1024*1024).max(Number.MAX_SAFE_INTEGER).default(0),max_bytes:z.number().int().min(1).max(4*1024*1024).default(65536),hash_file:z.boolean().default(false),timeout_ms:z.number().int().min(100).max(180000).default(30000)}),
32
32
  z.strictObject({op:z.literal('write'),root_id:id,path:rel,content:z.string().max(12*1024*1024),encoding:z.enum(['utf8','base64']).default('utf8'),expected_sha256:z.string().regex(/^(?:absent|[0-9a-f]{64})$/)}),
33
33
  z.strictObject({op:z.literal('edit_exact'),root_id:id,path:rel,expected_sha256:hex64,old_string:z.string().min(1).max(262144),new_string:z.string().max(524288),expected_replacements:z.number().int().min(1).max(64).default(1)}),
34
34
  z.strictObject({op:z.literal('mkdir'),root_id:id,path:rel}),
@@ -20,7 +20,7 @@ import { windowsPowerShellEnvironment } from './runtime-update.mjs';
20
20
  import { resolveStateRoot } from './state-root.mjs';
21
21
  import {foregroundIdentityMatches,queryForegroundIdentity,validForegroundIdentity} from './foreground-process-identity.mjs';
22
22
  import {acquireForegroundSessionLock} from './foreground-session-lock.mjs';
23
- import { AUTHORITY_PLANES, authorityVector, parseAuthorityObservation, assertAuthorityVector, assertRuntimeReadyObservation, authorityBanner } from './remote-authority.mjs';
23
+ import { AUTHORITY_PLANES, authorityVector, authorityRestorePlan, parseAuthorityObservation, assertAuthorityVector, assertRuntimeReadyObservation, authorityBanner } from './remote-authority.mjs';
24
24
  import { decodeRemoteLogBytes, boundedRemoteDiagnostic, safeRemoteLogPrefixLength } from './remote-log-decode-r60.mjs';
25
25
 
26
26
  const REMOTE_COMMANDS=new Set([
@@ -137,6 +137,20 @@ async function synchronizeForegroundRuntime(ctx,{displayMode='unicode'}={}){
137
137
  }
138
138
  });
139
139
  }
140
+ async function synchronizeOneShotRuntime(ctx,{displayMode='ascii'}={}){
141
+ const active=await readActiveRuntimeBinding(ctx.root);
142
+ if(!active||active.version===DEADBYTE_VERSION) return synchronizeForegroundRuntime(ctx,{displayMode});
143
+ const before=observedAuthority(ctx);
144
+ const expected=Object.fromEntries(AUTHORITY_PLANES.map(plane=>[plane,before.authority[plane].armed]));
145
+ const result=await synchronizeForegroundRuntime(ctx,{displayMode});
146
+ if(result.status!=='upgraded') return result;
147
+ for(const command of authorityRestorePlan(before)){
148
+ const restored=invokeController(ctx,command,{capture:true,allowFailure:true,echoCaptured:false,timeoutMs:REMOTE_STATUS_TIMEOUT_MS});
149
+ if(restored.status!==0) throw new Error(`runtime coherence authority restore '${command}' failed exit=${restored.status}`);
150
+ }
151
+ assertAuthorityVector(observedAuthority(ctx),expected);
152
+ return result;
153
+ }
140
154
  async function readControllerStartFailure(root,command,{maxChars=2048}={}){
141
155
  const file=path.join(root,'runtime','controller-start-failure.json');
142
156
  let raw;
@@ -629,7 +643,7 @@ async function runRemote(args){
629
643
  if(positional.length>1) throw new Error('remote accepts one controller command');
630
644
  const command=positional[0];if(!REMOTE_COMMANDS.has(command)) throw new Error(`unsupported remote command '${command}'`);
631
645
  const ctx=await remoteContext();
632
- await reportVersionCoherence(ctx.root,{displayMode:'ascii'});
646
+ await synchronizeOneShotRuntime(ctx,{displayMode:'ascii'});
633
647
  const result=invokeController(ctx,command,{allowFailure:true});
634
648
  process.exitCode=result.status;
635
649
  }
@@ -38,7 +38,7 @@ export function registerMachineFsTools(server, { runtime }) {
38
38
  });
39
39
  server.registerTool('machine_fs_read', {
40
40
  description:'Read one bounded byte range from a root-relative regular file.',
41
- inputSchema:z.strictObject({ root_id:id, path:rel, offset:z.number().int().min(-4*1024*1024).max(4*1024*1024).default(0), max_bytes:z.number().int().min(1).max(4*1024*1024).default(65536), hash_file:z.boolean().default(false), timeout_ms:z.number().int().min(100).max(180000).default(30000) }),
41
+ inputSchema:z.strictObject({ root_id:id, path:rel, offset:z.number().int().min(-4*1024*1024).max(Number.MAX_SAFE_INTEGER).default(0), max_bytes:z.number().int().min(1).max(4*1024*1024).default(65536), hash_file:z.boolean().default(false), timeout_ms:z.number().int().min(100).max(180000).default(30000) }),
42
42
  outputSchema:machineFsReadOutputSchema
43
43
  }, async ({root_id,path,offset,max_bytes,hash_file,timeout_ms}) => {
44
44
  try { return ok(machineFsReadOutputSchema, await runtime.read({rootId:root_id,relativePath:path,offset,maxBytes:max_bytes,hashFile:hash_file,timeoutMs:timeout_ms})); }
@@ -21,10 +21,10 @@ const MAX_DIRECTORY_IDENTITY_ENTRIES = 4096;
21
21
  const sha256Bytes = bytes => createHash('sha256').update(bytes).digest('hex');
22
22
  const sha256Object = value => sha256Bytes(Buffer.from(canonicalJson(value), 'utf8'));
23
23
  const nowUtc = () => new Date().toISOString();
24
- async function sha256File(file) {
24
+ async function sha256File(file, signal = undefined) {
25
25
  const hash = createHash('sha256');
26
26
  await new Promise((resolve, reject) => {
27
- const stream = createReadStream(file);
27
+ const stream = createReadStream(file, { signal });
28
28
  stream.on('data', chunk => hash.update(chunk));
29
29
  stream.once('error', reject);
30
30
  stream.once('end', resolve);
@@ -35,11 +35,13 @@ async function sha256File(file) {
35
35
  const machineFsReadWorkerPath = fileURLToPath(new URL('./machine-fs-read-worker.mjs', import.meta.url));
36
36
  async function boundedReadInProcess({ file, offset, length, hashFile, timeoutMs }) {
37
37
  const handle = await open(file, 'r');
38
+ const abortController = new AbortController();
38
39
  let timer;
39
40
  let settled = false;
40
41
  const abort = new Promise((_, reject) => {
41
42
  timer = setTimeout(() => {
42
43
  settled = true;
44
+ abortController.abort();
43
45
  void handle.close().catch(() => {});
44
46
  reject(new Error(`machine fs read timed out after ${timeoutMs}ms`));
45
47
  }, timeoutMs);
@@ -50,7 +52,7 @@ async function boundedReadInProcess({ file, offset, length, hashFile, timeoutMs
50
52
  const buffer = Buffer.alloc(length);
51
53
  const result = length ? await handle.read(buffer, 0, length, offset) : { bytesRead: 0 };
52
54
  let fileSha256 = null;
53
- if (hashFile) fileSha256 = await sha256File(file);
55
+ if (hashFile) fileSha256 = await sha256File(file, abortController.signal);
54
56
  return { schema: 'deadbyte.machine-fs-read-worker.v1', bytes_read: result.bytesRead,
55
57
  data_base64: buffer.subarray(0, result.bytesRead).toString('base64'), file_sha256: fileSha256 };
56
58
  })();
@@ -408,13 +410,14 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath,
408
410
  return { status: 'ok', root_id: rootId, path: found.relative, entries, next_cursor: nextCursor };
409
411
  }
410
412
  async function readRange({ rootId, relativePath, offset = 0, maxBytes = 65536, hashFile = false, timeoutMs = 30000 }) {
411
- if (!Number.isInteger(offset) || offset < -policy.max_read_bytes || offset > policy.max_read_bytes) throw new Error(`machine fs read offset must be in [-${policy.max_read_bytes}, ${policy.max_read_bytes}]`);
413
+ if (!Number.isSafeInteger(offset) || offset < -policy.max_read_bytes) throw new Error(`machine fs read offset must be a safe integer >= -${policy.max_read_bytes}`);
412
414
  if (!Number.isInteger(maxBytes) || maxBytes < 1 || maxBytes > policy.max_read_bytes) throw new Error(`machine fs max_bytes must be in [1, ${policy.max_read_bytes}]`);
413
415
  if (!Number.isInteger(timeoutMs) || timeoutMs < 100 || timeoutMs > 180000) throw new Error('machine fs read timeout_ms must be in [100, 180000]');
414
416
  const grant = await assertCodingReadAllowed(policy, rootId);
415
417
  const found = await resolveExisting(policy, grant, rootId, relativePath, 'read', false);
416
418
  const info = await lstat(found.resolved);
417
419
  if (!info.isFile()) throw new Error('machine fs read target must be a regular file');
420
+ if (!Number.isSafeInteger(info.size)) throw new Error('machine fs read file size exceeds safe integer range');
418
421
  const effectiveOffset = offset < 0 ? Math.max(0, info.size + offset) : offset;
419
422
  if (effectiveOffset > info.size) throw new Error('machine fs read offset exceeds file size');
420
423
  const length = Math.min(maxBytes, info.size - effectiveOffset);
@@ -11,6 +11,16 @@ export function authorityVector(mode='default'){
11
11
  });
12
12
  }
13
13
 
14
+ export function authorityRestorePlan(snapshot){
15
+ const disarm=[],arm=[];
16
+ for(const plane of AUTHORITY_PLANES){
17
+ const entry=snapshot?.authority?.[plane];
18
+ if(!entry||typeof entry.armed!=='boolean') throw new Error(`authority ${plane} observation invalid`);
19
+ (entry.armed?arm:disarm).push(`${entry.armed?'arm':'disarm'}${plane}`);
20
+ }
21
+ return Object.freeze([...disarm,...arm]);
22
+ }
23
+
14
24
  export function parseAuthorityObservation(raw){
15
25
  let value;
16
26
  try{value=typeof raw==='string'?JSON.parse(raw.replace(/^\uFEFF/,'')):raw;}
package/src/version.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export const DEADBYTE_VERSION = '0.15.39';
1
+ export const DEADBYTE_VERSION = '0.15.41';
2
2
  export const MCP_PROTOCOL_VERSION = '2026-07-28';
3
3
  export const RECEIPT_SCHEMA_V1 = 'deadbyte.receipt.v1';
4
4
  export const RECEIPT_SCHEMA_V2 = 'deadbyte.receipt.v2';
@@ -71,7 +71,7 @@ async function captureCurrentSurface(){
71
71
  }
72
72
  }
73
73
 
74
- test('R59 compact client-visible tool names and schemas match sealed 0.15.35 baseline',async()=>{
74
+ test('R59 compact baseline changes only at the explicitly authorized R64 read-offset bound',async()=>{
75
75
  const raw=JSON.parse(await readFile(fixturePath,'utf8'));
76
76
  assert.equal(raw.schema,'deadbyte.tool-surface-baseline.v1');
77
77
  assert.equal(raw.release_id,'v0.15.35-1b5715b276facbc0');
@@ -82,9 +82,19 @@ test('R59 compact client-visible tool names and schemas match sealed 0.15.35 bas
82
82
  const diff=diffToolSurface(baseline,current);
83
83
  assert.deepEqual(diff.added,[]);
84
84
  assert.deepEqual(diff.removed,[]);
85
- assert.deepEqual(diff.schema_changed,[]);
86
- assert.equal(diff.unchanged.length,43);
87
- assert.equal(current.surface_sha256,baseline.surface_sha256);
85
+ const packageVersion=JSON.parse(await readFile(path.join(repoRoot,'package.json'),'utf8')).version;
86
+ if(packageVersion==='0.15.41'){
87
+ assert.deepEqual(diff.schema_changed,['machine_fs']);
88
+ assert.equal(diff.unchanged.length,42);
89
+ const prior=baseline.tools.find(tool=>tool.name==='machine_fs');
90
+ const present=current.tools.find(tool=>tool.name==='machine_fs');
91
+ assert.equal(present.output_sha256,prior.output_sha256,'output contract must remain unchanged');
92
+ assert.notEqual(present.input_sha256,prior.input_sha256,'R64 must expose the widened read offset');
93
+ }else{
94
+ assert.deepEqual(diff.schema_changed,[]);
95
+ assert.equal(diff.unchanged.length,43);
96
+ assert.equal(current.surface_sha256,baseline.surface_sha256);
97
+ }
88
98
  console.log(JSON.stringify({baseline_release:raw.release_id,surface_sha256:current.surface_sha256,
89
99
  unchanged:diff.unchanged.length,added:diff.added,removed:diff.removed,schema_changed:diff.schema_changed}));
90
100
  });
@@ -4,6 +4,7 @@ import {readFile} from 'node:fs/promises';
4
4
 
5
5
  const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
6
6
  const json=rel=>read(rel).then(raw=>JSON.parse(raw.replace(/^\uFEFF/,'')));
7
+ const currentPackage=await json('package.json');
7
8
  const PARENT={
8
9
  version:'0.15.38',
9
10
  release_id:'v0.15.38-917901b3fcb2a77f',
@@ -11,7 +12,7 @@ const PARENT={
11
12
  generation_manifest_sha256:'9d320a8af1ba8e9e6a23552f35263da2670c00af1355464820552d849d9033c6'
12
13
  };
13
14
 
14
- test('R62 identity binds exact sealed 0.15.38 parent and transaction reconciliation scope',async()=>{
15
+ test('R62 identity binds exact sealed 0.15.38 parent and transaction reconciliation scope',{skip:currentPackage.version!=='0.15.39'},async()=>{
15
16
  const [pkg,lock,bridge,release,provenance,matrix,sbom,version,gate]=await Promise.all([
16
17
  json('package.json'),json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
17
18
  json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),
@@ -0,0 +1,38 @@
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
+
7
+ const root=path.resolve(fileURLToPath(new URL('..',import.meta.url)));
8
+ const authority=await import('../src/remote-authority.mjs');
9
+
10
+ test('R63 one-shot upgrade restore plan reproduces the exact pre-upgrade authority vector',()=>{
11
+ assert.equal(typeof authority.authorityRestorePlan,'function','authorityRestorePlan must exist');
12
+ const snapshot={
13
+ authority:{
14
+ process:{configured:true,armed:true,reason:'standing-grant'},
15
+ coding:{configured:true,armed:true,reason:'standing-grant'},
16
+ autonomous:{configured:true,armed:true,reason:'standing-grant'},
17
+ desktop:{configured:true,armed:false,reason:'disarmed'},
18
+ host:{configured:true,armed:true,reason:'standing-grant'}
19
+ }
20
+ };
21
+ assert.deepEqual(authority.authorityRestorePlan(snapshot),[
22
+ 'disarmdesktop',
23
+ 'armprocess','armcoding','armautonomous','armhost'
24
+ ]);
25
+ });
26
+
27
+ test('R63 explicit remote command synchronizes runtime before dispatch instead of warn-only skew reporting',async()=>{
28
+ const source=await readFile(path.join(root,'src','deadbyte-cli.mjs'),'utf8');
29
+ const start=source.indexOf('async function runRemote(args){');
30
+ const end=source.indexOf('\nasync function runSupervisor(',start);
31
+ assert.ok(start>=0&&end>start,'runRemote source boundary missing');
32
+ const body=source.slice(start,end);
33
+ const sync=body.indexOf("await synchronizeOneShotRuntime(ctx,{displayMode:'ascii'});");
34
+ const dispatch=body.indexOf('invokeController(ctx,command,{allowFailure:true})');
35
+ assert.ok(sync>=0,'one-shot remote command must synchronize the active runtime');
36
+ assert.ok(dispatch>sync,'runtime synchronization must complete before controller dispatch');
37
+ assert.doesNotMatch(body,/reportVersionCoherence/,'warn-only skew path must not remain in one-shot dispatch');
38
+ });
@@ -0,0 +1,59 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {readFile} from 'node:fs/promises';
4
+
5
+ const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
6
+ const json=rel=>read(rel).then(raw=>JSON.parse(raw.replace(/^\uFEFF/,'')));
7
+ const currentPackage=await json('package.json');
8
+ const PARENT={
9
+ version:'0.15.39',
10
+ release_id:'v0.15.39-3cda3b1c65b7b7c5',
11
+ manifest_sha256:'3cda3b1c65b7b7c561c5a8617156ab87d69cf162f447f3e99a4cb4a76471b3de',
12
+ generation_manifest_sha256:'f47cb96083679e764725df1bde6eda53169a39f55772c173ab22f89a1dfaa7ab'
13
+ };
14
+
15
+ test('R63 identity binds exact active 0.15.39 parent and one-shot runtime coherence repair',{skip:currentPackage.version!=='0.15.40'},async()=>{
16
+ const pkg=await json('package.json');
17
+ assert.equal(pkg.version,'0.15.40');
18
+ assert.match(pkg.scripts['r63:focused:test'],/r63-one-shot-coherence\.test\.mjs/);
19
+ assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r63-prepublish.ps1');
20
+
21
+ const [lock,bridge,release,provenance,matrix,sbom,version,gate]=await Promise.all([
22
+ json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),json('PROVENANCE.json'),
23
+ json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),read('scripts/gate-windows-r63-prepublish.ps1')
24
+ ]);
25
+ assert.equal(lock.version,pkg.version);
26
+ assert.equal(lock.packages[''].version,pkg.version);
27
+ assert.equal(bridge.version,pkg.version);
28
+ assert.match(version,/DEADBYTE_VERSION = '0\.15\.40'/);
29
+ assert.equal(release.version,pkg.version);
30
+ assert.equal(release.train,'R63');
31
+ assert.equal(release.parent.version,PARENT.version);
32
+ assert.equal(release.parent.release_id,PARENT.release_id);
33
+ assert.equal(release.parent.manifest_sha256,PARENT.manifest_sha256);
34
+ assert.equal(release.parent.generation_manifest_sha256,PARENT.generation_manifest_sha256);
35
+ assert.deepEqual(release.runtime_predecessor,{
36
+ release_id:PARENT.release_id,
37
+ manifest_sha256:PARENT.manifest_sha256,
38
+ generation_manifest_sha256:PARENT.generation_manifest_sha256
39
+ });
40
+ assert.equal(provenance.version,pkg.version);
41
+ assert.equal(provenance.parent_release_id,PARENT.release_id);
42
+ assert.equal(provenance.parent_manifest_sha256,PARENT.manifest_sha256);
43
+ assert.equal(provenance.parent_generation_manifest_sha256,PARENT.generation_manifest_sha256);
44
+ assert.equal(matrix.version,pkg.version);
45
+ assert.equal(matrix.train,'R63');
46
+ assert.equal(sbom.metadata.component.version,pkg.version);
47
+ assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r63:0.15.40');
48
+ assert.equal(release.r63_one_shot_runtime_coherence.public_surface_tool_count,43);
49
+ assert.equal(release.r63_one_shot_runtime_coherence.new_authority_scopes,0);
50
+ assert.equal(release.r63_one_shot_runtime_coherence.one_shot_auto_coherence,true);
51
+ assert.equal(release.r63_one_shot_runtime_coherence.pre_upgrade_authority_snapshot,true);
52
+ assert.equal(release.r63_one_shot_runtime_coherence.exact_authority_restore_verified,true);
53
+ assert.equal(release.r63_one_shot_runtime_coherence.warn_only_skew_path_removed,true);
54
+ assert.equal(release.r63_one_shot_runtime_coherence.stable_final_claim,false);
55
+ assert.match(gate,/v0\.15\.39-3cda3b1c65b7b7c5/);
56
+ assert.match(gate,/3cda3b1c65b7b7c561c5a8617156ab87d69cf162f447f3e99a4cb4a76471b3de/);
57
+ assert.match(gate,/f47cb96083679e764725df1bde6eda53169a39f55772c173ab22f89a1dfaa7ab/);
58
+ assert.match(gate,/r63:focused:test/);
59
+ });
@@ -0,0 +1,136 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {createHash} from 'node:crypto';
4
+ import fs from 'node:fs';
5
+ import {EventEmitter} from 'node:events';
6
+ import {mkdtemp, mkdir, readFile, writeFile, rm} from 'node:fs/promises';
7
+ import {syncBuiltinESMExports} from 'node:module';
8
+ import {tmpdir} from 'node:os';
9
+ import path from 'node:path';
10
+ import {loadCodingPolicy} from '../src/coding-plane.mjs';
11
+ import {createMachineFsRuntime} from '../src/machine-fs.mjs';
12
+ import {generateTrustKeypair} from '../src/trust.mjs';
13
+ import {machineFsGatewayInputSchema} from '../src/compact-gateway-mcp-tools.mjs';
14
+ import {registerMachineFsTools} from '../src/machine-fs-mcp-tools.mjs';
15
+
16
+ const PAGE=4*1024*1024;
17
+
18
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
19
+
20
+ async function fixture(t,{read=true}={}){
21
+ const root=await mkdtemp(path.join(tmpdir(),'deadbyte-r64-read-'));
22
+ t.after(()=>rm(root,{recursive:true,force:true}));
23
+ const project=path.join(root,'project');
24
+ await mkdir(project);
25
+ const policyPath=path.join(root,'policy.json');
26
+ await writeFile(policyPath,JSON.stringify({
27
+ schema:'deadbyte.coding-policy.v1',enabled:true,
28
+ lease_file:path.join(root,'coding-grant.json'),evidence_dir:path.join(root,'evidence'),
29
+ roots:{project:{path:project,read,write:false,exec:false,deny_paths:[]}},
30
+ commands:{},max_read_bytes:PAGE,max_write_bytes:65536
31
+ }));
32
+ const policy=await loadCodingPolicy(policyPath);
33
+ const keys=await generateTrustKeypair({privateKeyPath:path.join(root,'private.pem'),publicKeyPath:path.join(root,'public.pem')});
34
+ return {root,project,policy,keys,runtime:createMachineFsRuntime({policy,signingKeyPath:keys.privateKeyPath,verifyKeyPath:keys.publicKeyPath})};
35
+ }
36
+
37
+ test('R64 full and compact read schemas accept next_offset beyond one-page bound',()=>{
38
+ const server={registerTool(name,definition){if(name==='machine_fs_read')this.read=definition;}};
39
+ registerMachineFsTools(server,{runtime:{}});
40
+ const args={root_id:'project',path:'large.bin',offset:PAGE+2,max_bytes:64,hash_file:false,timeout_ms:30000};
41
+ assert.equal(server.read.inputSchema.safeParse(args).success,true,'full tool rejects a valid next_offset');
42
+ assert.equal(machineFsGatewayInputSchema.safeParse({op:'read',...args}).success,true,'compact tool rejects a valid next_offset');
43
+ assert.equal(server.read.inputSchema.safeParse({...args,max_bytes:PAGE+1}).success,false,'per-call byte cap must remain');
44
+ assert.equal(machineFsGatewayInputSchema.safeParse({op:'read',...args,max_bytes:PAGE+1}).success,false);
45
+ assert.equal(server.read.inputSchema.safeParse({...args,offset:Number.MAX_SAFE_INTEGER+1}).success,false);
46
+ assert.equal(machineFsGatewayInputSchema.safeParse({op:'read',...args,offset:Number.MAX_SAFE_INTEGER+1}).success,false);
47
+ });
48
+
49
+ test('R64 reads page two using next_offset beyond 4 MiB',async t=>{
50
+ const f=await fixture(t);
51
+ const bytes=Buffer.alloc(PAGE+32,0x61);
52
+ bytes[0]=0x5a;
53
+ bytes[1]=0x5b;
54
+ bytes[PAGE+2]=0x7f;
55
+ await writeFile(path.join(f.project,'large.bin'),bytes);
56
+ const first=await f.runtime.read({rootId:'project',relativePath:'large.bin',offset:2,maxBytes:PAGE});
57
+ assert.equal(first.next_offset,PAGE+2);
58
+ assert.equal(first.eof,false);
59
+ const second=await f.runtime.read({rootId:'project',relativePath:'large.bin',offset:first.next_offset,maxBytes:64});
60
+ assert.equal(second.offset,PAGE+2);
61
+ assert.equal(Buffer.from(second.data_base64,'base64')[0],0x7f);
62
+ assert.equal(second.eof,true);
63
+ assert.equal(second.next_offset,bytes.length);
64
+ const atEof=await f.runtime.read({rootId:'project',relativePath:'large.bin',offset:bytes.length,maxBytes:1});
65
+ assert.equal(atEof.eof,true);
66
+ assert.equal(Buffer.from(atEof.data_base64,'base64').length,0);
67
+ assert.equal(atEof.next_offset,bytes.length);
68
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:bytes.length+1,maxBytes:1}),/exceeds file size/);
69
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:Number.MAX_SAFE_INTEGER+1,maxBytes:1}),/safe integer/);
70
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:0,maxBytes:PAGE+1}),/max_bytes/);
71
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:-PAGE-1,maxBytes:1}),/offset/);
72
+ });
73
+
74
+ test('R64 pages are independent observations and hash_file reveals replacement between calls',async t=>{
75
+ const f=await fixture(t);
76
+ const file=path.join(f.project,'large.bin');
77
+ const before=Buffer.alloc(PAGE+32,0x61);
78
+ const after=Buffer.alloc(PAGE+32,0x62);
79
+ await writeFile(file,before);
80
+ const first=await f.runtime.read({rootId:'project',relativePath:'large.bin',offset:2,maxBytes:PAGE,hashFile:true});
81
+ assert.equal(first.file_sha256,sha(before));
82
+ await writeFile(file,after);
83
+ const second=await f.runtime.read({rootId:'project',relativePath:'large.bin',offset:first.next_offset,maxBytes:64,hashFile:true});
84
+ assert.equal(second.file_sha256,sha(after));
85
+ assert.notEqual(second.file_sha256,first.file_sha256,'the caller must not treat these pages as one snapshot');
86
+ });
87
+
88
+ test('R64 a denied read root remains denied at a large offset',async t=>{
89
+ const f=await fixture(t,{read:false});
90
+ await writeFile(path.join(f.project,'large.bin'),Buffer.alloc(PAGE+16));
91
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:PAGE+1,maxBytes:1}),/does not allow read/);
92
+ });
93
+
94
+ test('R64 large offset does not bypass root containment',async t=>{
95
+ const f=await fixture(t);
96
+ await writeFile(path.join(f.root,'outside.bin'),Buffer.alloc(PAGE+16));
97
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'../outside.bin',offset:PAGE+1,maxBytes:1}),/relative|traversal|path|outside/i);
98
+ });
99
+
100
+ test('R64 large-offset read retains bounded worker cancellation',async t=>{
101
+ const f=await fixture(t);
102
+ await writeFile(path.join(f.project,'large.bin'),Buffer.alloc(PAGE+16));
103
+ const worker=path.join(f.root,'slow-read-worker.mjs');
104
+ await writeFile(worker,'setTimeout(() => process.stdout.write("{}"), 30000);\n');
105
+ const runtime=createMachineFsRuntime({policy:f.policy,signingKeyPath:f.keys.privateKeyPath,verifyKeyPath:f.keys.publicKeyPath,readWorkerPath:worker});
106
+ await assert.rejects(()=>runtime.read({rootId:'project',relativePath:'large.bin',offset:PAGE+1,maxBytes:1,timeoutMs:100}),/timed out after 100ms/);
107
+ });
108
+
109
+ test('R64 default hash stream is abort-bound to read timeout',async()=>{
110
+ const source=await readFile(new URL('../src/machine-fs.mjs',import.meta.url),'utf8');
111
+ assert.ok(/createReadStream\(file,\s*\{\s*signal\s*\}\)/.test(source),'hash stream must receive the read abort signal');
112
+ assert.ok(/abortController\.abort\(\)/.test(source),'read timeout must abort its hash stream');
113
+ });
114
+
115
+ test('R64 timed-out default hash stream receives abort and stops',async t=>{
116
+ const f=await fixture(t);
117
+ await writeFile(path.join(f.project,'large.bin'),Buffer.alloc(PAGE+16));
118
+ const original=fs.createReadStream;
119
+ let observedAbort=false;
120
+ fs.createReadStream=(_file,options={})=>{
121
+ const stream=new EventEmitter();
122
+ options.signal?.addEventListener('abort',()=>{
123
+ observedAbort=true;
124
+ queueMicrotask(()=>stream.emit('error',new Error('aborted')));
125
+ },{once:true});
126
+ return stream;
127
+ };
128
+ syncBuiltinESMExports();
129
+ try{
130
+ await assert.rejects(()=>f.runtime.read({rootId:'project',relativePath:'large.bin',offset:PAGE+1,maxBytes:1,hashFile:true,timeoutMs:100}),/timed out after 100ms/);
131
+ assert.equal(observedAbort,true,'default hash stream continued after timeout');
132
+ }finally{
133
+ fs.createReadStream=original;
134
+ syncBuiltinESMExports();
135
+ }
136
+ });
@@ -0,0 +1,51 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {readFile} from 'node:fs/promises';
4
+
5
+ const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
6
+ const json=async rel=>JSON.parse((await read(rel)).replace(/^\uFEFF/,''));
7
+ const sourceSha='d6f75feada9ad0ae2c248b3a833ac9cf0e04150d2430ddaa70b3dfb64a0b0a86';
8
+ const runtime={
9
+ release_id:'v0.15.39-3cda3b1c65b7b7c5',
10
+ manifest_sha256:'3cda3b1c65b7b7c561c5a8617156ab87d69cf162f447f3e99a4cb4a76471b3de',
11
+ generation_manifest_sha256:'f47cb96083679e764725df1bde6eda53169a39f55772c173ab22f89a1dfaa7ab'
12
+ };
13
+
14
+ test('R64 release identity distinguishes unsealed source predecessor from active runtime predecessor',async()=>{
15
+ const [pkg,lock,bridge,release,provenance,matrix,sbom,scope,gaps,version,gate]=await Promise.all([
16
+ json('package.json'),json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
17
+ json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),json('docs/R64-SCOPE.json'),
18
+ json('docs/R64-REFERENCE-GAP-MATRIX.json'),read('src/version.mjs'),read('scripts/gate-windows-r64-prepublish.ps1')
19
+ ]);
20
+ assert.equal(pkg.version,'0.15.41');
21
+ assert.equal(lock.version,pkg.version);
22
+ assert.equal(lock.packages[''].version,pkg.version);
23
+ assert.equal(bridge.version,pkg.version);
24
+ assert.match(version,/DEADBYTE_VERSION = '0\.15\.41'/);
25
+ assert.equal(release.version,pkg.version);
26
+ assert.equal(release.train,'R64');
27
+ assert.equal(provenance.version,pkg.version);
28
+ assert.equal(matrix.version,pkg.version);
29
+ assert.equal(matrix.train,'R64');
30
+ assert.equal(sbom.metadata.component.version,pkg.version);
31
+ assert.equal(sbom.serialNumber,'urn:cdx:deadbyte-mcp:r64:0.15.41');
32
+ assert.deepEqual(release.runtime_predecessor,runtime);
33
+ assert.deepEqual(provenance.runtime_predecessor,runtime);
34
+ assert.equal(release.source_predecessor.version,'0.15.40');
35
+ assert.equal(release.source_predecessor.manifest_file_sha256,sourceSha);
36
+ assert.equal(release.source_predecessor.release_status,'NOT_PROVEN_RELEASED');
37
+ assert.equal(provenance.source_predecessor_manifest_file_sha256,sourceSha);
38
+ assert.equal(scope.source_predecessor.manifest_sha256,sourceSha);
39
+ assert.deepEqual(scope.runtime_predecessor,runtime);
40
+ assert.equal(release.r64_bounded_large_file_read.new_public_tools,0);
41
+ assert.equal(release.r64_bounded_large_file_read.new_authority_scopes,0);
42
+ assert.equal(release.r64_bounded_large_file_read.cross_page_atomic_snapshot_claim,false);
43
+ assert.equal(matrix.r64.prepublish_only,true);
44
+ assert.equal(gaps.references.length,7);
45
+ assert.equal(gaps.references.filter(row=>row.proposed_action.startsWith('ADAPT')).length,1);
46
+ assert.equal(pkg.scripts['gate:windows'],'powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r64-prepublish.ps1');
47
+ assert.match(pkg.scripts['r64:focused:test'],/r64-machine-fs-large-read\.test\.mjs/);
48
+ assert.match(gate,/d6f75feada9ad0ae2c248b3a833ac9cf0e04150d2430ddaa70b3dfb64a0b0a86/);
49
+ assert.match(gate,/v0\.15\.39-3cda3b1c65b7b7c5/);
50
+ assert.doesNotMatch(gate,/npm\.cmd publish|--publish-only/);
51
+ });
@@ -1,5 +1,6 @@
1
1
  import test from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
+ import { createHash } from 'node:crypto';
3
4
  import { mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
4
5
  import os from 'node:os';
5
6
  import path from 'node:path';
@@ -645,13 +646,14 @@ winTest('explicit remote status remains a one-shot controller command',async()=>
645
646
  }finally{await rm(fx.dir,{recursive:true,force:true});}
646
647
  });
647
648
 
648
- winTest('explicit remote status reports CLI package and active runtime VERSION SKEW',async()=>{
649
+ winTest('explicit remote status keeps the coherent runtime one-shot and silent',async()=>{
649
650
  const fx=await fixture({statusOnline:true});
650
651
  try{
651
- const manifest='1'.repeat(64),generation='2'.repeat(64),launcher='3'.repeat(64);
652
+ const manifest=createHash('sha256').update(await readFile(path.join(root,'MANIFEST.SHA256'))).digest('hex');
653
+ const generation='2'.repeat(64),launcher='3'.repeat(64);
652
654
  await writeFile(path.join(fx.state,'active-release.json'),JSON.stringify({
653
- schema:'deadbyte.active-release.v1',release_id:`v0.15.16-${manifest.slice(0,16)}`,version:'0.15.16',manifest_sha256:manifest,
654
- release_root:'C:/deadbyte/releases/0.15.16',generation_root:'C:/deadbyte/generations/0.15.16',generation_manifest_sha256:generation,
655
+ schema:'deadbyte.active-release.v1',release_id:`v${DEADBYTE_VERSION}-${manifest.slice(0,16)}`,version:DEADBYTE_VERSION,manifest_sha256:manifest,
656
+ release_root:'C:/deadbyte/releases/current',generation_root:'C:/deadbyte/generations/current',generation_manifest_sha256:generation,
655
657
  launcher_sha256:launcher,config_path:'C:/deadbyte/config.psd1'
656
658
  }),'utf8');
657
659
  const child=spawn(process.execPath,[cliPath,'remote','status'],{env:fx.env,stdio:['ignore','pipe','pipe'],windowsHide:true});
@@ -659,7 +661,7 @@ winTest('explicit remote status reports CLI package and active runtime VERSION S
659
661
  const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
660
662
  assert.equal(ended.timeout,undefined);
661
663
  assert.equal(ended.code,0,output.stderr);
662
- assert.ok(output.stderr.includes(`VERSION SKEW: CLI package ${DEADBYTE_VERSION}; active runtime 0.15.16`),output.stderr);
664
+ assert.doesNotMatch(output.stderr,/VERSION SKEW/);
663
665
  assert.deepEqual(await traceCommands(fx.trace),['status']);
664
666
  }finally{await rm(fx.dir,{recursive:true,force:true});}
665
667
  });