deadbyte-mcp 0.15.52 → 0.15.54
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.
- package/MANIFEST.SHA256 +32 -25
- package/PROVENANCE.json +27 -8
- package/README.txt +18 -18
- package/RELEASE.json +33 -6
- package/SBOM.cdx.json +2 -2
- package/TEST-MATRIX.json +32 -2
- package/bridge/src/remote-call-claims-r60.mjs +5 -0
- package/controller/deadbyte-process-policy.json +4 -4
- package/package.json +1 -1
- package/scripts/deploy-r48.mjs +51 -5
- package/src/activation-preflight-r65.mjs +35 -5
- package/src/commander-remote-bridge-r47.mjs +20 -2
- package/src/commander-remote-relay-r47.mjs +13 -2
- package/src/deadbyte-cli.mjs +10 -2
- package/src/legacy-offline-policy-proof-r146.mjs +204 -0
- package/src/release-generation.mjs +20 -1
- package/src/remote-device-r44.mjs +1 -1
- package/src/remote-live-log.mjs +43 -7
- package/src/version.mjs +1 -1
- package/test/commander-remote-bridge-r47.test.mjs +20 -1
- package/test/commander-remote-plane-r47.test.mjs +11 -0
- package/test/r130-release-security-contract.test.mjs +8 -8
- package/test/r132-release-identity.test.mjs +9 -9
- package/test/r144-claim-terminal-history.test.mjs +55 -0
- package/test/r144-controller-broad-roots-cleanup.test.mjs +54 -0
- package/test/r146-generation-scope-narrowing.test.mjs +64 -0
- package/test/r146-legacy-offline-policy-proof.test.mjs +199 -0
- package/test/r146-livelog-backpressure.test.mjs +105 -0
- package/test/r147-remote-request-hash.test.mjs +54 -0
- package/test/r59-tool-surface-compat.test.mjs +1 -1
- package/test/r65-activation-orchestration.test.mjs +53 -0
- package/test/r74-prepublish-contract.test.mjs +2 -2
- package/test/release-generation.test.mjs +8 -1
|
@@ -14,12 +14,13 @@ function fakePlane(){
|
|
|
14
14
|
|
|
15
15
|
test('R47 remote Commander bridge routes remote_device directly to remote-device-r44 plane',async()=>{
|
|
16
16
|
const server=fakeServer(),plane=fakePlane();
|
|
17
|
+
plane.probe=async value=>{plane.calls.push({op:'probe',value});return {device_id:value.deviceId,epoch:value.epoch,connection_id:'c',reachable:true};};
|
|
17
18
|
registerCommanderRemoteBridge(server,{remoteDevicePlane:plane});
|
|
18
19
|
assert.ok(server.tools.has('remote_device'));assert.ok(server.tools.has('remote_mcp'));
|
|
19
20
|
const tool=server.tools.get('remote_device').handler;const id='a'.repeat(64);
|
|
20
21
|
await tool({op:'pair',public_key_spki_base64:'ZmFrZQ==',display_name:'lab'});
|
|
21
22
|
await tool({op:'status',device_id:id});await tool({op:'report_online',device_id:id,epoch:1,connection_id:'c'});
|
|
22
|
-
await tool({op:'probe',device_id:id,epoch:1});await tool({op:'dispatch',device_id:id,epoch:1,capability_id:'machine.status',payload:{},request_id:'b'.repeat(64)});
|
|
23
|
+
await tool({op:'probe',device_id:id,epoch:1,connection_id:'c',nonce:'f'.repeat(64)});await tool({op:'dispatch',device_id:id,epoch:1,capability_id:'machine.status',payload:{},request_id:'b'.repeat(64)});
|
|
23
24
|
await tool({op:'revoke',device_id:id,epoch:1});await tool({op:'rotate_credential',device_id:id,epoch:1,encrypted_bundle_base64:'dG9rZW4=',expected_previous_sha256:null});await tool({op:'list'});
|
|
24
25
|
assert.deepEqual(plane.calls.map(x=>x.op),['pair','status','report_online','probe','dispatch','revoke','rotate_credential','list']);
|
|
25
26
|
});
|
|
@@ -37,3 +38,21 @@ test('R47 remote surfaces fail closed as unavailable when no remote-device-r44 p
|
|
|
37
38
|
const result=await server.tools.get('remote_device').handler({op:'list'});
|
|
38
39
|
assert.equal(result.status,'unavailable');assert.match(result.error,/remote-device-r44 plane is not configured/);
|
|
39
40
|
});
|
|
41
|
+
|
|
42
|
+
test('R146 remote readiness bridge binds the caller nonce and exact live connection',async()=>{
|
|
43
|
+
const server=fakeServer(),id='e'.repeat(64),nonce='f'.repeat(64),calls=[];
|
|
44
|
+
const plane={
|
|
45
|
+
async probe(value){calls.push(value);return {device_id:id,epoch:3,connection_id:'conn-3',reachable:true};}
|
|
46
|
+
};
|
|
47
|
+
registerCommanderRemoteBridge(server,{remoteDevicePlane:plane});
|
|
48
|
+
const registered=server.tools.get('remote_device');
|
|
49
|
+
const parsed=registered.meta.inputSchema.safeParse({op:'probe',device_id:id,epoch:3,connection_id:'conn-3',nonce});
|
|
50
|
+
assert.equal(parsed.success,true,'strict remote_device schema must accept the readiness challenge');
|
|
51
|
+
const result=await registered.handler(parsed.data);
|
|
52
|
+
assert.deepEqual(calls,[{deviceId:id,epoch:3}]);
|
|
53
|
+
assert.equal(result.device_id,id);assert.equal(result.epoch,3);
|
|
54
|
+
assert.equal(result.connection_id,'conn-3');assert.equal(result.nonce,nonce);assert.equal(result.ready,true);
|
|
55
|
+
|
|
56
|
+
plane.probe=async()=>({device_id:id,epoch:3,connection_id:'superseded',reachable:true});
|
|
57
|
+
await assert.rejects(registered.handler(parsed.data),/connection identity mismatch/i);
|
|
58
|
+
});
|
|
@@ -2,6 +2,7 @@ import test from 'node:test';
|
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
4
|
import { createHash } from 'node:crypto';
|
|
5
|
+
import { validateRemoteProbeResponseR47 } from '../src/commander-remote-relay-r47.mjs';
|
|
5
6
|
|
|
6
7
|
const sha=value=>createHash('sha256').update(value).digest('hex');
|
|
7
8
|
|
|
@@ -23,3 +24,13 @@ test('R47 relay is native MCP client and contains no Desktop Commander dependenc
|
|
|
23
24
|
assert.doesNotMatch(relay,/@wonderwhy-er\/desktop-commander/);
|
|
24
25
|
assert.equal(sha(relay).length,64);
|
|
25
26
|
});
|
|
27
|
+
|
|
28
|
+
test('R146 remote relay rejects fabricated or stale readiness acknowledgments',()=>{
|
|
29
|
+
const deviceId='a'.repeat(64),nonce='b'.repeat(64),connectionId='conn-live';
|
|
30
|
+
const good={device_id:deviceId,epoch:4,connection_id:connectionId,nonce,ready:true};
|
|
31
|
+
assert.deepEqual(validateRemoteProbeResponseR47(good,{deviceId,epoch:4,connectionId,nonce}),good);
|
|
32
|
+
assert.throws(()=>validateRemoteProbeResponseR47({...good,nonce:'c'.repeat(64)},{deviceId,epoch:4,connectionId,nonce}),/nonce mismatch/i);
|
|
33
|
+
assert.throws(()=>validateRemoteProbeResponseR47({...good,connection_id:'conn-stale'},{deviceId,epoch:4,connectionId,nonce}),/connection identity mismatch/i);
|
|
34
|
+
assert.throws(()=>validateRemoteProbeResponseR47({...good,device_id:'d'.repeat(64)},{deviceId,epoch:4,connectionId,nonce}),/device identity mismatch/i);
|
|
35
|
+
assert.throws(()=>validateRemoteProbeResponseR47({...good,ready:false},{deviceId,epoch:4,connectionId,nonce}),/not ready/i);
|
|
36
|
+
});
|
|
@@ -13,16 +13,16 @@ test('R130 security patch has a new immutable package identity and truthful sour
|
|
|
13
13
|
read('SBOM.cdx.json'),read('package-lock.json'),read('TEST-MATRIX.json')]);
|
|
14
14
|
assert.equal(pkg.name,'deadbyte-mcp');
|
|
15
15
|
for(const actual of [pkg.version,release.version,provenance.version,matrix.version,bom.metadata.component.version,lock.version,lock.packages[''].version,DEADBYTE_VERSION])
|
|
16
|
-
assert.equal(actual,'0.15.
|
|
17
|
-
assert.equal(release.train,'
|
|
18
|
-
assert.equal(matrix.train,'
|
|
19
|
-
assert.equal(release.source_predecessor.version,'0.15.
|
|
20
|
-
assert.match(release.source_predecessor.source_path,/0\.15\.
|
|
16
|
+
assert.equal(actual,'0.15.54');
|
|
17
|
+
assert.equal(release.train,'R146');
|
|
18
|
+
assert.equal(matrix.train,'R146');
|
|
19
|
+
assert.equal(release.source_predecessor.version,'0.15.53');
|
|
20
|
+
assert.match(release.source_predecessor.source_path,/0\.15\.53/);
|
|
21
21
|
assert.equal(release.runtime_predecessor.version,'0.15.45');
|
|
22
|
-
assert.equal(provenance.source_predecessor_version,'0.15.
|
|
23
|
-
assert.equal(provenance.source_predecessor_manifest_file_sha256,'
|
|
22
|
+
assert.equal(provenance.source_predecessor_version,'0.15.53');
|
|
23
|
+
assert.equal(provenance.source_predecessor_manifest_file_sha256,'04722504077844bbddb069aee72bfb7336b9ebfee8b6dd4733f48a82f4762cad');
|
|
24
24
|
assert.equal(pkg.dependencies['@modelcontextprotocol/client'],'2.3.1');
|
|
25
25
|
assert.equal(pkg.dependencies['@modelcontextprotocol/server'],'2.3.1');
|
|
26
26
|
for(const dep of ['@modelcontextprotocol/client','@modelcontextprotocol/server'])
|
|
27
27
|
assert.equal(pkg.bundleDependencies.includes(dep),true);
|
|
28
|
-
});
|
|
28
|
+
});
|
|
@@ -8,20 +8,20 @@ import {DEADBYTE_VERSION} from '../src/version.mjs';
|
|
|
8
8
|
const root=path.resolve(fileURLToPath(new URL('..',import.meta.url)));
|
|
9
9
|
const read=async rel=>JSON.parse(await readFile(path.join(root,rel),'utf8'));
|
|
10
10
|
|
|
11
|
-
test('
|
|
11
|
+
test('R144 package identities, R132 historic evidence and published predecessor are consistent',async()=>{
|
|
12
12
|
const [pkg,lock,release,prov,bom,matrix]=await Promise.all([
|
|
13
13
|
read('package.json'),read('package-lock.json'),read('RELEASE.json'),
|
|
14
14
|
read('PROVENANCE.json'),read('SBOM.cdx.json'),read('TEST-MATRIX.json')]);
|
|
15
15
|
for(const value of [pkg.version,lock.version,lock.packages[''].version,release.version,prov.version,bom.metadata.component.version,matrix.version,DEADBYTE_VERSION]){
|
|
16
|
-
assert.equal(value,'0.15.
|
|
16
|
+
assert.equal(value,'0.15.54');
|
|
17
17
|
}
|
|
18
|
-
assert.equal(release.train,'
|
|
19
|
-
assert.equal(matrix.train,'
|
|
20
|
-
assert.equal(release.source_predecessor.version,'0.15.
|
|
21
|
-
assert.match(release.source_predecessor.source_path,/0\.15\.
|
|
22
|
-
assert.equal(prov.source_predecessor_version,'0.15.
|
|
23
|
-
assert.equal(prov.source_predecessor_manifest_file_sha256,'
|
|
24
|
-
assert.equal(prov.parent_tarball_sha256,'
|
|
18
|
+
assert.equal(release.train,'R146');
|
|
19
|
+
assert.equal(matrix.train,'R146');
|
|
20
|
+
assert.equal(release.source_predecessor.version,'0.15.53');
|
|
21
|
+
assert.match(release.source_predecessor.source_path,/0\.15\.53/);
|
|
22
|
+
assert.equal(prov.source_predecessor_version,'0.15.53');
|
|
23
|
+
assert.equal(prov.source_predecessor_manifest_file_sha256,'04722504077844bbddb069aee72bfb7336b9ebfee8b6dd4733f48a82f4762cad');
|
|
24
|
+
assert.equal(prov.parent_tarball_sha256,'596aba2aefdb6d55824302e5aa2ca0e8ca2ea30eb2a6a13da4ec6ab036bd2a2c');
|
|
25
25
|
assert.equal(release.runtime_predecessor.version,'0.15.45');
|
|
26
26
|
assert.equal(prov.runtime_predecessor.release_id,release.runtime_predecessor.release_id);
|
|
27
27
|
assert.equal(prov.runtime_predecessor.manifest_sha256,release.runtime_predecessor.manifest_sha256);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {mkdtemp,rm,readFile,writeFile} from 'node:fs/promises';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import {performance} from 'node:perf_hooks';
|
|
7
|
+
import {openRemoteCallClaims} from '../bridge/src/remote-call-claims-r60.mjs';
|
|
8
|
+
|
|
9
|
+
const now=Date.parse('2029-01-01T00:00:00Z');
|
|
10
|
+
const base={device_id:'device-1',session_id:'session-1',request_id:'init',
|
|
11
|
+
tool:'coding_file_write',arguments:{root_id:'fixture',path:'a.txt',content:'A'},
|
|
12
|
+
expires_at_utc:'2030-01-01T00:00:00.000Z',release_id:'v-test',
|
|
13
|
+
generation_manifest_sha256:'a'.repeat(64),machine_id:'b'.repeat(64),
|
|
14
|
+
online_epoch:'c'.repeat(64),classification:'mutating'};
|
|
15
|
+
|
|
16
|
+
test('R144 terminal-heavy recovery ignores closed history and keeps live interruption fail-closed',async()=>{
|
|
17
|
+
const dir=await mkdtemp(path.join(os.tmpdir(),'r144-terminal-'));
|
|
18
|
+
try{
|
|
19
|
+
const store=openRemoteCallClaims({root:dir,clock:()=>now});
|
|
20
|
+
for(let i=0;i<200;i++){
|
|
21
|
+
const rec=await store.claim({...base,request_id:'terminal-'+i});
|
|
22
|
+
await store.dispatch(rec.claim_id);
|
|
23
|
+
await store.terminal(rec.claim_id,{status:'ok',value:i});
|
|
24
|
+
}
|
|
25
|
+
const pending=await store.claim({...base,request_id:'pending'});
|
|
26
|
+
const inflight=await store.claim({...base,request_id:'inflight'});
|
|
27
|
+
await store.dispatch(inflight.claim_id);
|
|
28
|
+
const start=performance.now(), recovered=await store.recover({limit:100});
|
|
29
|
+
const elapsed_ms=Math.round(performance.now()-start);
|
|
30
|
+
assert.deepEqual(new Set(recovered.records.map(x=>x.claim_id)),new Set([pending.claim_id,inflight.claim_id]));
|
|
31
|
+
assert.equal(recovered.next_cursor,null);
|
|
32
|
+
assert.equal((await store.state(inflight.claim_id)).state,'INTERRUPTED');
|
|
33
|
+
assert.equal((await store.state(inflight.claim_id)).side_effect_state,'unknown');
|
|
34
|
+
const replay=await store.claim({...base,request_id:'terminal-77'});
|
|
35
|
+
assert.equal(replay.owner,false);
|
|
36
|
+
assert.equal(replay.state,'TERMINAL');
|
|
37
|
+
console.log('R144_TERMINAL_HISTORY_BENCH',{terminal_count:200,elapsed_ms});
|
|
38
|
+
}finally{await rm(dir,{recursive:true,force:true});}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('R144 terminal marker cannot enable replay when its bytes are forged',async()=>{
|
|
42
|
+
const dir=await mkdtemp(path.join(os.tmpdir(),'r144-forged-'));
|
|
43
|
+
try{
|
|
44
|
+
const store=openRemoteCallClaims({root:dir,clock:()=>now});
|
|
45
|
+
const claim=await store.claim(base);
|
|
46
|
+
await store.dispatch(claim.claim_id);
|
|
47
|
+
await store.terminal(claim.claim_id,{status:'ok'});
|
|
48
|
+
const f=path.join(dir,claim.claim_id.slice(0,2),claim.claim_id+'.terminal.json');
|
|
49
|
+
const bytes=await readFile(f,'utf8');
|
|
50
|
+
await writeFile(f,bytes.replace('"status":"ok"','"status":"forged"'));
|
|
51
|
+
assert.equal((await store.recover({limit:100})).records.length,0);
|
|
52
|
+
await assert.rejects(store.claim(base),/terminal hash corrupt|remote claim state unreadable/);
|
|
53
|
+
await assert.rejects(store.dispatch(claim.claim_id),/already dispatched/);
|
|
54
|
+
}finally{await rm(dir,{recursive:true,force:true});}
|
|
55
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {readFile,writeFile,mkdtemp,mkdir,rm,access} from 'node:fs/promises';
|
|
4
|
+
import {spawnSync} from 'node:child_process';
|
|
5
|
+
import {createHash} from 'node:crypto';
|
|
6
|
+
import os from 'node:os';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
|
|
9
|
+
const q=x=>"'"+String(x).replaceAll("'","''")+"'";
|
|
10
|
+
const section=(src,start,end)=>{
|
|
11
|
+
const a=src.indexOf('function '+start+'('),b=src.indexOf('function '+end+'(',a);
|
|
12
|
+
assert.ok(a>=0&&b>a,start+' boundaries missing');
|
|
13
|
+
return src.slice(a,b);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
test('R144 broad Coding roots with no leases permit isolated cleanup without changing grants',async()=>{
|
|
17
|
+
const home='C:/Users/DEADBYTE/.deadbyte-mcp';
|
|
18
|
+
const cfgRoot=path.join(home,'generations','v0.15.45-34aa8d1241cfb8bf-ga9de1c56d5e65fa4');
|
|
19
|
+
const tmp=await mkdtemp(path.join(os.tmpdir(),'r144-broad-policy-cleanup-'));
|
|
20
|
+
try{
|
|
21
|
+
const runtime=path.join(tmp,'runtime');await mkdir(runtime);
|
|
22
|
+
const coding=JSON.parse(await readFile(path.join(cfgRoot,'coding-policy.json'),'utf8'));
|
|
23
|
+
const autonomous=JSON.parse(await readFile(path.join(cfgRoot,'autonomous-policy.json'),'utf8'));
|
|
24
|
+
assert.equal(coding.roots.local_c.path,'C:\\');
|
|
25
|
+
assert.equal(coding.roots.local_d.path,'D:\\');
|
|
26
|
+
coding.lease_file=path.join(runtime,'coding-grant.json');
|
|
27
|
+
const codingFile=path.join(tmp,'coding.json');
|
|
28
|
+
await writeFile(codingFile,JSON.stringify(coding));
|
|
29
|
+
autonomous.lease_file=path.join(runtime,'autonomous-grant.json');
|
|
30
|
+
autonomous.coding_policy_sha256=createHash('sha256').update(await readFile(codingFile)).digest('hex');
|
|
31
|
+
const autonomousFile=path.join(tmp,'autonomous.json');
|
|
32
|
+
await writeFile(autonomousFile,JSON.stringify(autonomous));
|
|
33
|
+
const src=await readFile(new URL('../controller/deadbyte-controller.ps1',import.meta.url),'utf8');
|
|
34
|
+
const code=[
|
|
35
|
+
"$ErrorActionPreference='Stop';",'$RuntimeDir='+q(runtime)+';',
|
|
36
|
+
'function Fail([string]$m){throw $m}',
|
|
37
|
+
'function Invoke-AuthorityEpochCommand{throw "UNEXPECTED_EPOCH_MUTATION"}',
|
|
38
|
+
section(src,'Assert-PolicyRootsAvailable','Get-AuthorityEpochStatus'),
|
|
39
|
+
section(src,'Read-ControllerPolicySnapshot','Get-CodingPolicyMetadata'),
|
|
40
|
+
section(src,'Get-CodingPolicyMetadata','Get-CodingLeaseStatus'),
|
|
41
|
+
section(src,'Disarm-Coding','Show-CodingStatus'),
|
|
42
|
+
section(src,'Get-AutonomousRevocationLeaseFile','Show-AutonomousStatus'),
|
|
43
|
+
'$cfg=@{CodingPolicyFile='+q(codingFile)+';AutonomousPolicyFile='+q(autonomousFile)+'};',
|
|
44
|
+
'Disarm-Coding $cfg; Disarm-Autonomous $cfg; Write-Output "R144_NO_GRANT_REVOKE_OK"'
|
|
45
|
+
].join('\n');
|
|
46
|
+
const run=spawnSync('powershell.exe',['-NoLogo','-NoProfile','-NonInteractive','-Command',code],{
|
|
47
|
+
encoding:'utf8',timeout:30000,maxBuffer:1024*1024
|
|
48
|
+
});
|
|
49
|
+
assert.equal(run.status,0,run.stderr+'\n'+run.stdout);
|
|
50
|
+
assert.match(run.stdout,/R144_NO_GRANT_REVOKE_OK/);
|
|
51
|
+
for(const f of ['coding-grant.json','autonomous-grant.json'])
|
|
52
|
+
await assert.rejects(access(path.join(runtime,f)),{code:'ENOENT'});
|
|
53
|
+
}finally{await rm(tmp,{recursive:true,force:true});}
|
|
54
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import {rebindCodingPolicy} from '../src/release-generation.mjs';
|
|
5
|
+
|
|
6
|
+
const settings={
|
|
7
|
+
developmentRoot:'D:\\Projects\\deadbyte-mcp\\r146',
|
|
8
|
+
stateRoot:'C:\\Users\\DEADBYTE\\.deadbyte-mcp',
|
|
9
|
+
parityScratchRoot:'C:\\Users\\DEADBYTE\\.deadbyte-mcp\\runtime\\r33-parity-scratch'
|
|
10
|
+
};
|
|
11
|
+
const root=folder=>({path:folder,read:true,write:true,exec:true,deny_paths:[]});
|
|
12
|
+
const base=()=>({
|
|
13
|
+
schema:'deadbyte.coding-policy.v1',
|
|
14
|
+
roots:{
|
|
15
|
+
core:root('D:\\Projects\\deadbyte-mcp\\old'),
|
|
16
|
+
projects:root('D:\\Projects'),
|
|
17
|
+
local_c:root('C:\\'),
|
|
18
|
+
local_d:root('D:\\')
|
|
19
|
+
},
|
|
20
|
+
commands:{
|
|
21
|
+
powershell_script:{root_ids:['core','local_c','local_d']},
|
|
22
|
+
cmd_script:{root_ids:['projects','local_d']},
|
|
23
|
+
node_script:{root_ids:['core','local_c']}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('R146 never inherits historical C/D whole-drive authority',()=>{
|
|
28
|
+
const original=base();
|
|
29
|
+
const rewritten=rebindCodingPolicy(original,settings);
|
|
30
|
+
assert.deepEqual(Object.keys(rewritten.roots).sort(),['core','parity_scratch','projects']);
|
|
31
|
+
assert.equal(rewritten.roots.core.path,settings.developmentRoot);
|
|
32
|
+
assert.equal(rewritten.roots.parity_scratch.exec,false);
|
|
33
|
+
assert.deepEqual(rewritten.commands.powershell_script.root_ids,['core']);
|
|
34
|
+
assert.deepEqual(rewritten.commands.cmd_script.root_ids,['projects']);
|
|
35
|
+
assert.deepEqual(rewritten.commands.node_script.root_ids,['core']);
|
|
36
|
+
assert.equal(original.roots.local_c.path,'C:\\');
|
|
37
|
+
assert.equal(original.roots.local_d.path,'D:\\');
|
|
38
|
+
assert.deepEqual(original.commands.powershell_script.root_ids,['core','local_c','local_d']);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('R146 unknown whole drive root is not silently adopted',()=>{
|
|
42
|
+
const raw=base();raw.roots.other=root('E:\\');
|
|
43
|
+
assert.throws(()=>rebindCodingPolicy(raw,settings),/unrecognized whole-drive Coding root/);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('R146 fail closed if a command loses its last root',()=>{
|
|
47
|
+
const raw=base();raw.commands.powershell_script.root_ids=['local_c'];
|
|
48
|
+
assert.throws(()=>rebindCodingPolicy(raw,settings),/every scoped root/);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('R146 preserves a separately scoped local root',()=>{
|
|
52
|
+
const raw=base();raw.roots.local_d.path='D:\\Projects\\scratch';
|
|
53
|
+
const result=rebindCodingPolicy(raw,settings);
|
|
54
|
+
assert.equal(result.roots.local_d.path,'D:\\Projects\\scratch');
|
|
55
|
+
assert.deepEqual(result.commands.cmd_script.root_ids,['projects','local_d']);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('R146 ordinary scoped policies retain their command roots',()=>{
|
|
59
|
+
const raw=base();delete raw.roots.local_c;delete raw.roots.local_d;
|
|
60
|
+
raw.commands.powershell_script.root_ids=['core'];raw.commands.cmd_script.root_ids=['projects'];raw.commands.node_script.root_ids=['core'];
|
|
61
|
+
const result=rebindCodingPolicy(raw,settings);
|
|
62
|
+
assert.deepEqual(result.commands.powershell_script.root_ids,['core']);
|
|
63
|
+
assert.equal(result.roots.projects.path,'D:\\Projects');
|
|
64
|
+
});
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {createHash,generateKeyPairSync,sign} from 'node:crypto';
|
|
4
|
+
import {mkdir,mkdtemp,readFile,rm,writeFile} from 'node:fs/promises';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import {proveLegacyOfflineScopeRepair} from '../src/legacy-offline-policy-proof-r146.mjs';
|
|
8
|
+
import {canonicalJson} from '../src/canonical-json.mjs';
|
|
9
|
+
|
|
10
|
+
const sha=x=>createHash('sha256').update(x).digest('hex');
|
|
11
|
+
const PLANES=['process','coding','autonomous','desktop','host'];
|
|
12
|
+
const GRANT={process:'grant_file',coding:'lease_file',autonomous:'lease_file',desktop:'grant_file',host:'arm_file'};
|
|
13
|
+
const APPROVAL_DOMAIN=Buffer.from('DEADBYTE-R146-POLICY-MIGRATION-APPROVAL\0','utf8');
|
|
14
|
+
const mkRoot=p=>({path:p,read:true,write:true,exec:true,deny_paths:[]});
|
|
15
|
+
async function fixture({thirdDrive=false,badBinding=false}={}){
|
|
16
|
+
const base=await mkdtemp(path.join(os.tmpdir(),'r146-offline-scope-'));
|
|
17
|
+
const stateRoot=path.join(base,'state'),runtime=path.join(stateRoot,'runtime');
|
|
18
|
+
const gen=path.join(stateRoot,'generations','predecessor');
|
|
19
|
+
await mkdir(runtime,{recursive:true});await mkdir(gen,{recursive:true});
|
|
20
|
+
const policyPaths={},policySha256={},files=[];
|
|
21
|
+
const coding={
|
|
22
|
+
schema:'deadbyte.coding-policy.v1',enabled:true,
|
|
23
|
+
lease_file:path.join(runtime,'coding-grant.json'),
|
|
24
|
+
roots:{core:mkRoot(path.join(base,'project')),local_c:mkRoot('C:\\'),local_d:mkRoot('D:\\')},
|
|
25
|
+
commands:{powershell_script:{root_ids:['core','local_c','local_d']}}
|
|
26
|
+
};
|
|
27
|
+
if(thirdDrive)coding.roots.other=mkRoot('E:\\');
|
|
28
|
+
const codingBytes=Buffer.from(JSON.stringify(coding)+'\n');
|
|
29
|
+
const autonomous={
|
|
30
|
+
schema:'deadbyte.autonomous-policy.v1',enabled:true,
|
|
31
|
+
lease_file:path.join(runtime,'autonomous-grant.json'),
|
|
32
|
+
coding_policy_sha256:badBinding?'a'.repeat(64):sha(codingBytes),
|
|
33
|
+
root_ids:['core'],profiles:{}
|
|
34
|
+
};
|
|
35
|
+
const policies={
|
|
36
|
+
coding,autonomous,
|
|
37
|
+
process:{schema:'deadbyte.process-policy.v1',enabled:true,grant_file:path.join(runtime,'process-grant.json')},
|
|
38
|
+
desktop:{schema:'deadbyte.desktop-policy.v1',enabled:true,grant_file:path.join(runtime,'desktop-grant.json')},
|
|
39
|
+
host:{schema:'deadbyte.host-policy.v2',enabled:true,arm_file:path.join(runtime,'host-grant.json')}
|
|
40
|
+
};
|
|
41
|
+
for(const plane of PLANES){
|
|
42
|
+
const file=path.join(gen,plane+'-policy.json');
|
|
43
|
+
const bytes=plane==='coding'?codingBytes:Buffer.from(JSON.stringify(policies[plane])+'\n');
|
|
44
|
+
await writeFile(file,bytes);
|
|
45
|
+
policyPaths[plane]=file;policySha256[plane]=sha(bytes);
|
|
46
|
+
files.push([plane+'-policy.json',sha(bytes)]);
|
|
47
|
+
}
|
|
48
|
+
const manifest=Buffer.from(files.sort((a,b)=>a[0].localeCompare(b[0],'en')).map(x=>x[1]+' '+x[0]).join('\n')+'\n');
|
|
49
|
+
await writeFile(path.join(gen,'GENERATION.SHA256'),manifest);
|
|
50
|
+
const parent={release_id:'v0.15.45-34aa8d1241cfb8bf',version:'0.15.45',
|
|
51
|
+
manifest_sha256:'1'.repeat(64),generation_manifest_sha256:sha(manifest)};
|
|
52
|
+
const pointer={...parent,generation_root:gen};
|
|
53
|
+
await writeFile(path.join(stateRoot,'active-release.json'),JSON.stringify(pointer)+'\n');
|
|
54
|
+
const authority=Object.fromEntries(PLANES.map(p=>[p,{
|
|
55
|
+
configured:true,armed:false,reason:p==='autonomous'?'unverified':'disarmed'
|
|
56
|
+
}]));
|
|
57
|
+
const authority_proof=Object.fromEntries(PLANES.map(p=>[p,{
|
|
58
|
+
state:p==='autonomous'?'UNVERIFIED':'VERIFIED_DISARMED',
|
|
59
|
+
grant_absent:true,policy_sha256:policySha256[p]
|
|
60
|
+
}]));
|
|
61
|
+
const observation={state:'OFFLINE',local_ready:false,
|
|
62
|
+
bridge:{alive:false},core:{alive:false},cloud:{alive:false},supervisor:{running:false},
|
|
63
|
+
authority,authority_proof,policy_sha256:policySha256,
|
|
64
|
+
active_release_id:parent.release_id,active_manifest_sha256:parent.manifest_sha256,
|
|
65
|
+
active_generation_manifest_sha256:parent.generation_manifest_sha256};
|
|
66
|
+
const candidate={version:'0.15.54',manifest_sha256:'9'.repeat(64)};
|
|
67
|
+
const preflightSubjectSha256='8'.repeat(64);
|
|
68
|
+
const {privateKey,publicKey}=generateKeyPairSync('ed25519');
|
|
69
|
+
const ownerKeyId=sha(publicKey.export({type:'spki',format:'der'}));
|
|
70
|
+
const trust=path.join(stateRoot,'trust');await mkdir(trust,{recursive:true});
|
|
71
|
+
const ownerPublicKeyPath=path.join(trust,'r70-owner-public.pem');
|
|
72
|
+
await writeFile(ownerPublicKeyPath,publicKey.export({type:'spki',format:'pem'}));
|
|
73
|
+
const subject={schema:'deadbyte.r146-policy-migration-subject.v1',action:'legacy_offline_scope_repair',
|
|
74
|
+
predecessor_release_id:parent.release_id,predecessor_version:parent.version,
|
|
75
|
+
predecessor_manifest_sha256:parent.manifest_sha256,
|
|
76
|
+
predecessor_generation_manifest_sha256:parent.generation_manifest_sha256,
|
|
77
|
+
candidate_version:candidate.version,candidate_manifest_sha256:candidate.manifest_sha256,
|
|
78
|
+
predecessor_policy_sha256:policySha256,preflight_subject_sha256:preflightSubjectSha256,
|
|
79
|
+
issued_at_utc:'2026-10-23T00:00:00.000Z',expires_at_utc:'2026-10-23T00:30:00.000Z'};
|
|
80
|
+
const subjectSha256=sha(Buffer.from(canonicalJson(subject),'utf8'));
|
|
81
|
+
const signed={schema:'deadbyte.r146-policy-migration-approval.v1',subject_sha256:subjectSha256,owner_key_id:ownerKeyId};
|
|
82
|
+
const approval={...signed,subject,signature_base64:sign(null,Buffer.concat([APPROVAL_DOMAIN,Buffer.from(canonicalJson(signed),'utf8')]),privateKey).toString('base64')};
|
|
83
|
+
const approvalPath=path.join(base,'approval.json'),approvalBytes=Buffer.from(JSON.stringify(approval));
|
|
84
|
+
await writeFile(approvalPath,approvalBytes);
|
|
85
|
+
return {
|
|
86
|
+
root:base,stateRoot,pointer,expectedParent:parent,observation,policyPaths,policySha256,
|
|
87
|
+
runtime,policies,candidate,expectedCandidate:candidate,preflightSubjectSha256,
|
|
88
|
+
approvalPath,approvalSha256:sha(approvalBytes),ownerPublicKeyPath,
|
|
89
|
+
now:new Date('2026-10-23T00:05:00.000Z'),async close(){await rm(base,{recursive:true,force:true});}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const invoke=x=>proveLegacyOfflineScopeRepair(x);
|
|
93
|
+
test('R146 verifies exact inactive legacy scope only with manifest, direct grant absence and parent binding',async()=>{
|
|
94
|
+
const x=await fixture();
|
|
95
|
+
try{
|
|
96
|
+
const got=await invoke(x);
|
|
97
|
+
assert.equal(got.state,'VERIFIED_OFFLINE_LEGACY_SCOPE_REPAIR');
|
|
98
|
+
assert.equal(got.coding_policy_sha256,x.policySha256.coding);
|
|
99
|
+
assert.equal(got.generation_manifest_sha256,x.pointer.generation_manifest_sha256);
|
|
100
|
+
assert.equal(got.candidate_manifest_sha256,x.candidate.manifest_sha256);
|
|
101
|
+
assert.equal(got.preflight_subject_sha256,x.preflightSubjectSha256);
|
|
102
|
+
assert.equal(got.owner_approval_verified,true);
|
|
103
|
+
assert.match(got.subject_sha256,/^[0-9a-f]{64}$/);
|
|
104
|
+
}finally{await x.close();}
|
|
105
|
+
});
|
|
106
|
+
test('R146 proof rejects candidate or approval subject drift',async()=>{
|
|
107
|
+
const x=await fixture();
|
|
108
|
+
try{
|
|
109
|
+
await assert.rejects(invoke({...x,candidate:{...x.candidate,manifest_sha256:'7'.repeat(64)}}),/candidate|approval/i);
|
|
110
|
+
await assert.rejects(invoke({...x,preflightSubjectSha256:'7'.repeat(64)}),/preflight subject/i);
|
|
111
|
+
}finally{await x.close();}
|
|
112
|
+
});
|
|
113
|
+
test('R146 proof rejects an expired or not-yet-valid owner approval',async()=>{
|
|
114
|
+
const x=await fixture();
|
|
115
|
+
try{
|
|
116
|
+
await assert.rejects(invoke({...x,now:new Date('2026-10-23T00:30:00.000Z')}),/approval expired or invalid/);
|
|
117
|
+
await assert.rejects(invoke({...x,now:new Date('2026-10-22T23:59:59.999Z')}),/approval expired or invalid/);
|
|
118
|
+
}finally{await x.close();}
|
|
119
|
+
});
|
|
120
|
+
test('R146 proof rejects a forged approval even when its file hash is repinned',async()=>{
|
|
121
|
+
const x=await fixture();
|
|
122
|
+
try{
|
|
123
|
+
const approval=JSON.parse(await readFile(x.approvalPath,'utf8'));
|
|
124
|
+
approval.signature_base64=Buffer.alloc(64,0x5a).toString('base64');
|
|
125
|
+
const bytes=Buffer.from(JSON.stringify(approval));
|
|
126
|
+
await writeFile(x.approvalPath,bytes);
|
|
127
|
+
await assert.rejects(invoke({...x,approvalSha256:sha(bytes)}),/approval signature invalid/);
|
|
128
|
+
}finally{await x.close();}
|
|
129
|
+
});
|
|
130
|
+
test('R146 proof rejects an owner trust-key substitution',async()=>{
|
|
131
|
+
const x=await fixture();
|
|
132
|
+
try{
|
|
133
|
+
const {publicKey}=generateKeyPairSync('ed25519');
|
|
134
|
+
await writeFile(x.ownerPublicKeyPath,publicKey.export({type:'spki',format:'pem'}));
|
|
135
|
+
await assert.rejects(invoke(x),/owner key identity mismatch/);
|
|
136
|
+
}finally{await x.close();}
|
|
137
|
+
});
|
|
138
|
+
test('R146 proof rejects any unresolved authority epoch lock',async()=>{
|
|
139
|
+
const x=await fixture();
|
|
140
|
+
try{
|
|
141
|
+
const lock=path.join(x.runtime,'authority-epochs','coding','.lock');
|
|
142
|
+
await mkdir(path.dirname(lock),{recursive:true});await writeFile(lock,'ambiguous');
|
|
143
|
+
await assert.rejects(invoke(x),/authority epoch lock present/);
|
|
144
|
+
}finally{await x.close();}
|
|
145
|
+
});
|
|
146
|
+
test('R146 any real grant overrides apparent DISARMED observation',async()=>{
|
|
147
|
+
const x=await fixture();
|
|
148
|
+
try{
|
|
149
|
+
await writeFile(path.join(x.runtime,'autonomous-grant.json'),'active');
|
|
150
|
+
await assert.rejects(invoke(x),/autonomous grant present/);
|
|
151
|
+
}finally{await x.close();}
|
|
152
|
+
});
|
|
153
|
+
test('R146 foreground ownership marker blocks offline scope repair',async()=>{
|
|
154
|
+
const x=await fixture();
|
|
155
|
+
try{
|
|
156
|
+
await writeFile(path.join(x.runtime,'remote-session.json'),'retained');
|
|
157
|
+
await assert.rejects(invoke(x),/ownership marker present/);
|
|
158
|
+
}finally{await x.close();}
|
|
159
|
+
});
|
|
160
|
+
test('R146 active or uncertain runtime blocks offline scope repair',async()=>{
|
|
161
|
+
const x=await fixture();
|
|
162
|
+
try{
|
|
163
|
+
x.observation.bridge.alive=true;
|
|
164
|
+
await assert.rejects(invoke(x),/not cleanly offline/);
|
|
165
|
+
}finally{await x.close();}
|
|
166
|
+
});
|
|
167
|
+
test('R146 any unrelated unverified authority plane blocks scope repair',async()=>{
|
|
168
|
+
const x=await fixture();
|
|
169
|
+
try{
|
|
170
|
+
x.observation.authority.host.reason='unverified';
|
|
171
|
+
await assert.rejects(invoke(x),/not physically inactive: host/);
|
|
172
|
+
}finally{await x.close();}
|
|
173
|
+
});
|
|
174
|
+
test('R146 extra whole-drive root fails the special repair proof',async()=>{
|
|
175
|
+
const x=await fixture({thirdDrive:true});
|
|
176
|
+
try{
|
|
177
|
+
await assert.rejects(invoke(x),/unexpected drive root/);
|
|
178
|
+
}finally{await x.close();}
|
|
179
|
+
});
|
|
180
|
+
test('R146 autonomous coding policy digest mismatch blocks recovery',async()=>{
|
|
181
|
+
const x=await fixture({badBinding:true});
|
|
182
|
+
try{
|
|
183
|
+
await assert.rejects(invoke(x),/Coding\/Autonomous binding invalid/);
|
|
184
|
+
}finally{await x.close();}
|
|
185
|
+
});
|
|
186
|
+
test('R146 predecessor generation bytes drift blocks offline repair',async()=>{
|
|
187
|
+
const x=await fixture();
|
|
188
|
+
try{
|
|
189
|
+
await writeFile(x.policyPaths.coding,'{}');
|
|
190
|
+
await assert.rejects(invoke(x),/generation file hash mismatch/);
|
|
191
|
+
}finally{await x.close();}
|
|
192
|
+
});
|
|
193
|
+
test('R146 predecessor identity drift cannot be attested',async()=>{
|
|
194
|
+
const x=await fixture();
|
|
195
|
+
try{
|
|
196
|
+
x.expectedParent.manifest_sha256='a'.repeat(64);
|
|
197
|
+
await assert.rejects(invoke(x),/predecessor mismatch/);
|
|
198
|
+
}finally{await x.close();}
|
|
199
|
+
});
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import {EventEmitter} from 'node:events';
|
|
4
|
+
import {createLiveTimelineWriter} from '../src/remote-live-log.mjs';
|
|
5
|
+
|
|
6
|
+
function blockedOutput(){
|
|
7
|
+
const stream=new EventEmitter();
|
|
8
|
+
const writes=[];
|
|
9
|
+
stream.isTTY=false;
|
|
10
|
+
let blockNext=false;
|
|
11
|
+
stream.write=chunk=>{
|
|
12
|
+
writes.push(chunk);
|
|
13
|
+
if(blockNext){blockNext=false;return false;}
|
|
14
|
+
return true;
|
|
15
|
+
};
|
|
16
|
+
return {stream,writes,block:()=>{blockNext=true;}};
|
|
17
|
+
}
|
|
18
|
+
test('R146 LiveLogs survives stdout backpressure without unbounded presentation writes',()=>{
|
|
19
|
+
const out=blockedOutput();
|
|
20
|
+
const writer=createLiveTimelineWriter({stream:out.stream,rewrite:false});
|
|
21
|
+
out.block();
|
|
22
|
+
writer.write('one');
|
|
23
|
+
for(let i=0;i<12000;i++)writer.write('status '+i);
|
|
24
|
+
assert.deepEqual(out.writes,['one\n']);
|
|
25
|
+
assert.equal(writer.retention().suppressed_since_drain,12000);
|
|
26
|
+
assert.equal(writer.retention().congested,true);
|
|
27
|
+
out.stream.emit('drain');
|
|
28
|
+
assert.match(out.writes[1],/LIVELOG.*12000.*suppressed.*audit/i);
|
|
29
|
+
assert.equal(writer.retention().suppressed_since_drain,0);
|
|
30
|
+
writer.write('after');
|
|
31
|
+
assert.equal(out.writes.at(-1),'after\n');
|
|
32
|
+
assert.equal(writer.retention().total_suppressed,12000);
|
|
33
|
+
});
|
|
34
|
+
test('R146 LiveLogs emits only one bounded warning for each backpressure window',()=>{
|
|
35
|
+
const out=blockedOutput();
|
|
36
|
+
const writer=createLiveTimelineWriter({stream:out.stream,rewrite:false});
|
|
37
|
+
out.block();writer.write('a');
|
|
38
|
+
writer.write('drop1');writer.write('drop2');
|
|
39
|
+
out.stream.emit('drain');
|
|
40
|
+
out.stream.emit('drain');
|
|
41
|
+
assert.equal(out.writes.length,2);
|
|
42
|
+
assert.match(out.writes[1],/2.*suppressed/);
|
|
43
|
+
});
|
|
44
|
+
test('R146 LiveLogs normal progress and TTY rewrite stay unchanged when drain never needed',()=>{
|
|
45
|
+
const out=blockedOutput();
|
|
46
|
+
out.stream.isTTY=true;
|
|
47
|
+
const writer=createLiveTimelineWriter({stream:out.stream,rewrite:true});
|
|
48
|
+
writer.write('RUN',{event_type:'tool.call',request_id:'a'});
|
|
49
|
+
writer.write('DONE',{event_type:'tool.result',request_id:'a'});
|
|
50
|
+
assert.deepEqual(out.writes,['RUN','\r\x1b[2KDONE\n']);
|
|
51
|
+
assert.equal(writer.retention().total_suppressed,0);
|
|
52
|
+
});
|
|
53
|
+
test('R146 LiveLogs refuses non-evented saturated stream instead of silently dropping output',()=>{
|
|
54
|
+
const sink={write(){return false;}};
|
|
55
|
+
const writer=createLiveTimelineWriter({stream:sink,rewrite:false});
|
|
56
|
+
assert.throws(()=>writer.write('line'),/drain-capable/);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test('R146 LiveLogs warns on a stalled TTY without leaving its partial START line attached',()=>{
|
|
60
|
+
const out=blockedOutput();
|
|
61
|
+
out.stream.isTTY=true;
|
|
62
|
+
const writer=createLiveTimelineWriter({stream:out.stream,rewrite:true});
|
|
63
|
+
out.block();
|
|
64
|
+
writer.write('RUN',{event_type:'tool.call',request_id:'a'});
|
|
65
|
+
writer.write('DONE',{event_type:'tool.result',request_id:'a'});
|
|
66
|
+
assert.equal(writer.retention().suppressed_since_drain,1);
|
|
67
|
+
out.stream.emit('drain');
|
|
68
|
+
assert.equal(out.writes[0],'RUN');
|
|
69
|
+
assert.equal(out.writes[1],'\n');
|
|
70
|
+
assert.match(out.writes[2],/1 presentation lines suppressed/);
|
|
71
|
+
writer.write('AFTER');
|
|
72
|
+
assert.equal(out.writes[3],'AFTER\n');
|
|
73
|
+
});
|
|
74
|
+
test('R146 LiveLogs repeated backpressure during warning remains bounded and recovers',()=>{
|
|
75
|
+
const out=blockedOutput();
|
|
76
|
+
const writer=createLiveTimelineWriter({stream:out.stream,rewrite:false});
|
|
77
|
+
out.block();writer.write('START');writer.write('hidden 1');
|
|
78
|
+
out.block();out.stream.emit('drain');
|
|
79
|
+
assert.equal(writer.retention().congested,true);
|
|
80
|
+
writer.write('hidden 2');
|
|
81
|
+
out.stream.emit('drain');
|
|
82
|
+
assert.equal(writer.retention().congested,false);
|
|
83
|
+
assert.equal(writer.retention().total_suppressed,2);
|
|
84
|
+
assert.match(out.writes[1],/1 presentation lines suppressed/);
|
|
85
|
+
assert.match(out.writes[2],/1 presentation lines suppressed/);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('R146 LiveLogs session summary reports untracked overflow beyond its bounded in-flight cap',async()=>{
|
|
89
|
+
const {createLiveTimelineTracker}=await import('../src/remote-live-log.mjs');
|
|
90
|
+
const tracker=createLiveTimelineTracker({displayMode:'ascii'});
|
|
91
|
+
for(let i=0;i<4100;i++){
|
|
92
|
+
tracker.observe({event_type:'tool.request',tool:'coding_file_read',
|
|
93
|
+
request_id:'too-many-'+String(i).padStart(8,'0'),args:{root_id:'core',path:'readme'}},{sequence:i+1});
|
|
94
|
+
}
|
|
95
|
+
assert.equal(tracker.retention().pending,4096);
|
|
96
|
+
assert.equal(tracker.retention().pending_overflow,4);
|
|
97
|
+
assert.match(tracker.summary(),/4.*presentation spans.*(?:overflow|untracked)/i);
|
|
98
|
+
});
|
|
99
|
+
test('R146 CLI reports any still-congested output during final cleanup',async()=>{
|
|
100
|
+
const {readFile}=await import('node:fs/promises');
|
|
101
|
+
const cli=await readFile(new URL('../src/deadbyte-cli.mjs',import.meta.url),'utf8');
|
|
102
|
+
assert.match(cli,/timelineWriter\.retention\(\)/);
|
|
103
|
+
assert.match(cli,/suppressed_since_drain/);
|
|
104
|
+
assert.match(cli,/process\.stderr\.write/);
|
|
105
|
+
});
|