deadbyte-mcp 0.15.51 → 0.15.53

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 (48) hide show
  1. package/MANIFEST.SHA256 +47 -18
  2. package/PROVENANCE.json +27 -9
  3. package/README.txt +18 -18
  4. package/RELEASE.json +33 -6
  5. package/SBOM.cdx.json +2 -2
  6. package/TEST-MATRIX.json +32 -2
  7. package/bridge/src/remote-call-claims-r60.mjs +5 -0
  8. package/controller/deadbyte-process-policy.json +4 -4
  9. package/docs/R135-AUTONOMOUS-SCOPE.md +21 -0
  10. package/docs/R136-SCOPED-OBSERVER.md +21 -0
  11. package/docs/R137-DESKTOP-COMMANDER-FOUNDATION.md +31 -0
  12. package/docs/R138-COMMANDER-WORKFLOW.md +21 -0
  13. package/docs/R139-COMMANDER-ERGONOMICS.md +17 -0
  14. package/docs/THIRD-PARTY-DESKTOP-COMMANDER-MIT.md +27 -0
  15. package/package.json +1 -1
  16. package/src/autonomous-scope-r135.mjs +91 -0
  17. package/src/commander-config-recovery-r137.mjs +67 -0
  18. package/src/commander-extended-runtime.mjs +22 -5
  19. package/src/commander-external-process-r48.mjs +25 -3
  20. package/src/commander-large-text-r139.mjs +66 -0
  21. package/src/commander-wire-adapter-r47.mjs +63 -12
  22. package/src/deadbyte-cli.mjs +5 -1
  23. package/src/scoped-observer-launcher-r136.mjs +77 -0
  24. package/src/scoped-observer-worker-r136.mjs +65 -0
  25. package/src/version.mjs +1 -1
  26. package/test/commander-wire-contract-r47.test.mjs +8 -5
  27. package/test/r130-release-security-contract.test.mjs +8 -8
  28. package/test/r132-release-identity.test.mjs +9 -9
  29. package/test/r135-autonomous-scope.test.mjs +103 -0
  30. package/test/r136-scoped-command-rights.test.mjs +39 -0
  31. package/test/r136-scoped-observer.test.mjs +89 -0
  32. package/test/r137-commander-config-recovery.test.mjs +111 -0
  33. package/test/r137-commander-three-version-contract.test.mjs +56 -0
  34. package/test/r138-commander-process-pagination.test.mjs +42 -0
  35. package/test/r138-commander-session-list.test.mjs +24 -0
  36. package/test/r138-commander-stream-resume.test.mjs +50 -0
  37. package/test/r139-large-text-edit.test.mjs +51 -0
  38. package/test/r139-large-text-read.test.mjs +46 -0
  39. package/test/r139-process-start-preview.test.mjs +50 -0
  40. package/test/r139-search-partial.test.mjs +42 -0
  41. package/test/r140-large-text-integrity.test.mjs +68 -0
  42. package/test/r141-commander-tail-utf8.test.mjs +55 -0
  43. package/test/r141-real-windows-disk.test.mjs +71 -0
  44. package/test/r142-native-machinefs-authority.test.mjs +127 -0
  45. package/test/r144-claim-terminal-history.test.mjs +55 -0
  46. package/test/r144-controller-broad-roots-cleanup.test.mjs +54 -0
  47. package/test/r59-tool-surface-compat.test.mjs +1 -1
  48. package/test/r74-prepublish-contract.test.mjs +3 -3
@@ -0,0 +1,65 @@
1
+ import {readFile,lstat,realpath} from 'node:fs/promises';
2
+ import {createHash} from 'node:crypto';
3
+ import path from 'node:path';
4
+
5
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
6
+ const digest=/^[0-9a-f]{64}$/;
7
+ const eq=(a,b)=>process.platform==='win32'?a.toLowerCase()===b.toLowerCase():a===b;
8
+ async function fileInside(state,filename,expected){
9
+ if(!digest.test(expected??''))throw new Error('policy digest invalid');
10
+ const root=path.resolve(state),file=path.resolve(filename);
11
+ const rel=path.relative(root,file);
12
+ if(rel===''||path.isAbsolute(rel)||rel==='..'||rel.startsWith('..'+path.sep))throw new Error('policy outside isolated state');
13
+ const item=await lstat(file);
14
+ if(!item.isFile()||item.isSymbolicLink()||!eq(await realpath(file),file))throw new Error('policy not regular');
15
+ const bytes=await readFile(file);
16
+ if(sha(bytes)!==expected)throw new Error('policy digest mismatch');
17
+ return JSON.parse(bytes.toString('utf8'));
18
+ }
19
+ async function boot(){
20
+ if(!process.send)throw new Error('IPC required');
21
+ const [state,codingFile,codingDigest,autoFile,autoDigest]=process.argv.slice(2);
22
+ if(!state||!path.isAbsolute(state))throw new Error('isolated state required');
23
+ const isolated=path.resolve(state);
24
+ if(!eq(await realpath(isolated),isolated))throw new Error('isolated state redirected');
25
+ const coding=await fileInside(isolated,codingFile,codingDigest);
26
+ const auto=await fileInside(isolated,autoFile,autoDigest);
27
+ if(coding?.schema!=='deadbyte.coding-policy.v1'||coding.enabled!==true)throw new Error('coding schema invalid');
28
+ if(auto?.schema!=='deadbyte.autonomous-policy.v1'||auto.enabled!==true)throw new Error('autonomous schema invalid');
29
+ if(auto.coding_policy_sha256!==codingDigest)throw new Error('autonomous binding invalid');
30
+ const ids=Object.keys(coding.roots??{}),selected=auto.root_ids;
31
+ if(!Array.isArray(selected)||selected.length!==1||ids.length!==1||ids[0]!==selected[0])throw new Error('root scope mismatch');
32
+ const id=ids[0],root=coding.roots[id]?.path;
33
+ if(!path.isAbsolute(root??'')||eq(path.resolve(root),path.parse(root).root))throw new Error('broad Coding root forbidden');
34
+ const stat=await lstat(root);
35
+ if(!stat.isDirectory()||stat.isSymbolicLink()||!eq(await realpath(root),path.resolve(root)))throw new Error('untrusted project root');
36
+ const commands=Object.entries(coding.commands??{});
37
+ for(const [,command] of commands){
38
+ if(!Array.isArray(command.root_ids)||command.root_ids.length!==1||command.root_ids[0]!==id)
39
+ throw new Error('command root scope mismatch');
40
+ }
41
+ for(const p of Object.values(auto.profiles??{})){
42
+ if(p?.root_id!==id||!Object.hasOwn(coding.commands,p.command_id))throw new Error('autonomous profile mismatch');
43
+ }
44
+ for(const lease of [coding.lease_file,auto.lease_file]){
45
+ if(typeof lease!=='string'||!path.isAbsolute(lease)||!eq(path.dirname(lease),path.join(isolated,'runtime')))
46
+ throw new Error('lease state isolation mismatch');
47
+ try{await lstat(lease);throw new Error('inherited grant present');}
48
+ catch(error){if(error?.code!=='ENOENT')throw error;}
49
+ }
50
+ const ambient=Object.keys(process.env).filter(k=>k.toUpperCase().startsWith('DEADBYTE_'));
51
+ const ready={pid:process.pid,status:'DISARMED',root_ids:ids,command_ids:commands.map(x=>x[0]),
52
+ coding_sha256:codingDigest,autonomous_sha256:autoDigest,ambient_deadbyte_keys:ambient.length,
53
+ node_options_present:Object.hasOwn(process.env,'NODE_OPTIONS'),
54
+ user_token_present:Object.keys(process.env).some(k=>/OPENAI_API_KEY|NPM_TOKEN|GITHUB_TOKEN|GH_TOKEN|AWS_SECRET_ACCESS_KEY/i.test(k)),
55
+ grant_files_present:false};
56
+ process.send({kind:'ready',result:ready});
57
+ process.on('message',msg=>{
58
+ if(!msg||msg.kind!=='request'||!Number.isSafeInteger(msg.id))return;
59
+ if(msg.op==='shutdown'){process.send({kind:'reply',id:msg.id,result:{status:'STOPPING'}});return process.exit(0);}
60
+ const result=msg.op==='status'?{status:'DISARMED',root_ids:ids}:
61
+ {status:'DENIED_UNAUTHORIZED',op:typeof msg.op==='string'?msg.op:''};
62
+ process.send({kind:'reply',id:msg.id,result});
63
+ });
64
+ }
65
+ boot().catch(err=>{process.send?.({kind:'boot-error',reason:String(err.message??err).slice(0,140)});process.exitCode=3;});
package/src/version.mjs CHANGED
@@ -1,4 +1,4 @@
1
- export const DEADBYTE_VERSION = '0.15.51';
1
+ export const DEADBYTE_VERSION = '0.15.53';
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';
@@ -406,13 +406,14 @@ test('R48 read_file tails a large text file from the end without reading the who
406
406
  policy:{roots:{project:{real_path:'D:\\RDC-COMPAT-TEST'}},max_read_bytes:64},
407
407
  async read(args){
408
408
  calls.push({...args});
409
- if(args.offset>=0) return {
410
- data_base64:Buffer.from('HEAD-ONLY').toString('base64'),
411
- file_sha256:null,file_size:1024,eof:false,offset:0,next_offset:9
409
+ if(args.offset===959) return {
410
+ data_base64:Buffer.from('x').toString('base64'),
411
+ file_sha256:null,file_size:1024,eof:false,offset:959,next_offset:960
412
412
  };
413
413
  assert.equal(args.offset,-64);
414
+ const suffix='older\nline7\nline8\nline9\n';
414
415
  return {
415
- data_base64:Buffer.from('older\nline7\nline8\nline9\n').toString('base64'),
416
+ data_base64:Buffer.from('p'.repeat(64-Buffer.byteLength(suffix))+suffix).toString('base64'),
416
417
  file_sha256:null,file_size:1024,eof:true,offset:960,next_offset:1024
417
418
  };
418
419
  }
@@ -423,8 +424,10 @@ test('R48 read_file tails a large text file from the end without reading the who
423
424
  });
424
425
  assert.equal(result.isError,undefined,JSON.stringify(result));
425
426
  assert.equal(result.structuredContent.content,'line8\nline9');
426
- assert.equal(calls.length,1);
427
+ assert.equal(calls.length,2);
427
428
  assert.equal(calls[0].offset,-64);
429
+ assert.equal(calls[1].offset,959);
430
+ assert.equal(calls[1].maxBytes,1);
428
431
  });
429
432
 
430
433
  test('R48 edit_block range mutates XLSX through native ZIP/XML writer with hash precondition',async()=>{
@@ -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.51');
17
- assert.equal(release.train,'R132');
18
- assert.equal(matrix.train,'R132');
19
- assert.equal(release.source_predecessor.version,'0.15.50');
20
- assert.match(release.source_predecessor.source_path,/0\.15\.50/);
16
+ assert.equal(actual,'0.15.53');
17
+ assert.equal(release.train,'R144');
18
+ assert.equal(matrix.train,'R144');
19
+ assert.equal(release.source_predecessor.version,'0.15.52');
20
+ assert.match(release.source_predecessor.source_path,/0\.15\.52/);
21
21
  assert.equal(release.runtime_predecessor.version,'0.15.45');
22
- assert.equal(provenance.source_predecessor_version,'0.15.50');
23
- assert.equal(provenance.source_predecessor_manifest_file_sha256,'98dd37c71adae980856adc17b9c59d58d167a01d46c61106055956d0f306fede');
22
+ assert.equal(provenance.source_predecessor_version,'0.15.52');
23
+ assert.equal(provenance.source_predecessor_manifest_file_sha256,'e00223a76ef6d0e0fa7e850de597fa44cd6113cd49725535492da73f1daf4244');
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('R132 candidate identities and published source predecessor are consistent',async()=>{
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.51');
16
+ assert.equal(value,'0.15.53');
17
17
  }
18
- assert.equal(release.train,'R132');
19
- assert.equal(matrix.train,'R132');
20
- assert.equal(release.source_predecessor.version,'0.15.50');
21
- assert.match(release.source_predecessor.source_path,/0\.15\.50/);
22
- assert.equal(prov.source_predecessor_version,'0.15.50');
23
- assert.equal(prov.source_predecessor_manifest_file_sha256,'98dd37c71adae980856adc17b9c59d58d167a01d46c61106055956d0f306fede');
24
- assert.equal(prov.parent_tarball_sha256,'133b9f4adedee14a3e4f2fd1c9433f7ebf102742a73398161b238fd68eb42d84');
18
+ assert.equal(release.train,'R144');
19
+ assert.equal(matrix.train,'R144');
20
+ assert.equal(release.source_predecessor.version,'0.15.52');
21
+ assert.match(release.source_predecessor.source_path,/0\.15\.52/);
22
+ assert.equal(prov.source_predecessor_version,'0.15.52');
23
+ assert.equal(prov.source_predecessor_manifest_file_sha256,'e00223a76ef6d0e0fa7e850de597fa44cd6113cd49725535492da73f1daf4244');
24
+ assert.equal(prov.parent_tarball_sha256,'ec675df8885a0d96b1486607956b7091fe47088509b4756194a7e15004d8d97f');
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,103 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {mkdtemp,mkdir,rm,readFile,writeFile} from 'node:fs/promises';
4
+ import {createHash} from 'node:crypto';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import {deriveIsolatedAutonomousScope} from '../src/autonomous-scope-r135.mjs';
8
+ import {assertAutonomousBootstrapRoots} from '../src/runtime-update.mjs';
9
+ const hash=bytes=>createHash('sha256').update(bytes).digest('hex');
10
+ async function fixture(run){
11
+ const base=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r135-scope-'));
12
+ try{
13
+ const core=path.join(base,'safe-project'),scratch=path.join(base,'child-state');
14
+ await mkdir(core);await mkdir(scratch);
15
+ const original={schema:'deadbyte.coding-policy.v1',enabled:true,
16
+ lease_file:path.join(base,'parent-coding-grant.json'),
17
+ evidence_dir:path.join(base,'parent-evidence'),
18
+ roots:{core:{path:core,read:true,write:true,exec:true,deny_paths:[]},
19
+ local_c:{path:path.parse(base).root,read:true,write:true,exec:true,deny_paths:[]},
20
+ downloads:{path:path.join(base,'downloads'),read:true,write:true,exec:true,deny_paths:[]}},
21
+ commands:{node_script:{executable:'node',args:[],root_ids:['core','local_c']},unused_command:{executable:'cmd',args:[],root_ids:['local_c']}}};
22
+ const autonomous={schema:'deadbyte.autonomous-policy.v1',enabled:true,
23
+ lease_file:path.join(base,'parent-autonomous-grant.json'),evidence_dir:path.join(base,'old-auto-evidence'),
24
+ coding_policy_sha256:'a'.repeat(64),root_ids:['core'],
25
+ planner:{backend:'client_sampling',max_tokens:2048},
26
+ profiles:{quick:{kind:'command',root_id:'core',command_id:'node_script',
27
+ script_path:'test.mjs',script_sha256:'b'.repeat(64)}}};
28
+ await run({base,core,scratch,original,autonomous});
29
+ }finally{await rm(base,{recursive:true,force:true})}
30
+ }
31
+ test('R135 projects only the chosen project root and its pinned commands without modifying manual Coding',async()=>{
32
+ await fixture(async({scratch,original,autonomous})=>{
33
+ const before=JSON.stringify(original),beforeAutonomous=JSON.stringify(autonomous);
34
+ const result=deriveIsolatedAutonomousScope({manualCodingPolicy:original,autonomousPolicy:autonomous,
35
+ scopeRootId:'core',isolatedStateRoot:scratch});
36
+ assert.deepEqual(Object.keys(result.codingPolicy.roots),['core']);
37
+ assert.deepEqual(Object.keys(result.codingPolicy.commands),['node_script']);
38
+ assert.equal(result.autonomousPolicy.coding_policy_sha256,hash(result.codingBytes));
39
+ assert.deepEqual(result.autonomousPolicy.root_ids,['core']);
40
+ assert.deepEqual(assertAutonomousBootstrapRoots(result.autonomousPolicy,result.codingPolicy,hash(result.codingBytes)),['core']);
41
+ assert.equal(JSON.stringify(original),before);
42
+ assert.equal(JSON.stringify(autonomous),beforeAutonomous);
43
+ assert.notEqual(result.codingPolicy.lease_file,original.lease_file);
44
+ assert.notEqual(result.autonomousPolicy.lease_file,autonomous.lease_file);
45
+ await assert.rejects(()=>readFile(result.codingPolicy.lease_file),{code:'ENOENT'});
46
+ await assert.rejects(()=>readFile(result.autonomousPolicy.lease_file),{code:'ENOENT'});
47
+ });
48
+ });
49
+ test('R135 scope projector refuses direct whole-drive root and does not weaken R70 security gate',async()=>{
50
+ await fixture(async({scratch,original,autonomous})=>{
51
+ const wide={...autonomous,root_ids:['local_c'],
52
+ profiles:{quick:{...autonomous.profiles.quick,root_id:'local_c'}}};
53
+ assert.throws(()=>deriveIsolatedAutonomousScope({manualCodingPolicy:original,autonomousPolicy:wide,
54
+ scopeRootId:'local_c',isolatedStateRoot:scratch}),/project-scoped root/);
55
+ assert.throws(()=>assertAutonomousBootstrapRoots(autonomous,original,'a'.repeat(64)),
56
+ /coding policy contains a broad filesystem root/);
57
+ });
58
+ });
59
+ test('R135 rejects Autonomous profiles targeting roots other than the approved scope',async()=>{
60
+ await fixture(async({scratch,original,autonomous})=>{
61
+ const forged={...autonomous,profiles:{out:{...autonomous.profiles.quick,root_id:'downloads'}}};
62
+ assert.throws(()=>deriveIsolatedAutonomousScope({manualCodingPolicy:original,autonomousPolicy:forged,
63
+ scopeRootId:'core',isolatedStateRoot:scratch}),/profile.*outside/);
64
+ });
65
+ });
66
+ test('R135 rejects missing command referenced by approved profile',async()=>{
67
+ await fixture(async({scratch,original,autonomous})=>{
68
+ const forged={...autonomous,profiles:{quick:{...autonomous.profiles.quick,command_id:'not_allowlisted'}}};
69
+ assert.throws(()=>deriveIsolatedAutonomousScope({manualCodingPolicy:original,autonomousPolicy:forged,
70
+ scopeRootId:'core',isolatedStateRoot:scratch}),/command.*missing/);
71
+ });
72
+ });
73
+ test('R135 refuses missing, redirected, and unsafe project root',async()=>{
74
+ await fixture(async({scratch,original,autonomous,base})=>{
75
+ original.roots.core.path=path.join(base,'not-present');
76
+ assert.throws(()=>deriveIsolatedAutonomousScope({manualCodingPolicy:original,autonomousPolicy:autonomous,
77
+ scopeRootId:'core',isolatedStateRoot:scratch}),/real project directory/);
78
+ });
79
+ });
80
+ test('R135 does not accept an isolated state ancestor of an existing manual lease',async()=>{
81
+ await fixture(async({scratch,original,autonomous,base})=>{
82
+ original.lease_file=path.join(base,'runtime','existing-coding-grant.json');
83
+ autonomous.lease_file=path.join(path.dirname(base),'other-autonomous-grant.json');
84
+ assert.throws(()=>deriveIsolatedAutonomousScope({manualCodingPolicy:original,autonomousPolicy:autonomous,
85
+ scopeRootId:'core',isolatedStateRoot:base}),/isolated state root overlaps manual Coding lease/);
86
+ });
87
+ });
88
+ test('R135 does not inherit any existing grant file at the isolated destination',async()=>{
89
+ await fixture(async({scratch,original,autonomous})=>{
90
+ const runtime=path.join(scratch,'runtime');
91
+ await mkdir(runtime);
92
+ await writeFile(path.join(runtime,'coding-grant.json'),'{"legacy":true}\n');
93
+ assert.throws(()=>deriveIsolatedAutonomousScope({manualCodingPolicy:original,autonomousPolicy:autonomous,
94
+ scopeRootId:'core',isolatedStateRoot:scratch}),/isolated grant file already present/);
95
+ });
96
+ });
97
+
98
+ test('R135 refuses using the manual lease root as the isolated runtime root',async()=>{
99
+ await fixture(async({original,autonomous,base})=>{
100
+ assert.throws(()=>deriveIsolatedAutonomousScope({manualCodingPolicy:original,autonomousPolicy:autonomous,
101
+ scopeRootId:'core',isolatedStateRoot:base}),/isolated state root overlaps manual Coding lease/);
102
+ });
103
+ });
@@ -0,0 +1,39 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {mkdtemp,mkdir,rm} from 'node:fs/promises';
4
+ import os from 'node:os';
5
+ import path from 'node:path';
6
+ import {deriveIsolatedAutonomousScope} from '../src/autonomous-scope-r135.mjs';
7
+ const fixture=async fn=>{
8
+ const dir=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r136-command-'));
9
+ try{
10
+ const core=path.join(dir,'core'),state=path.join(dir,'isolated');
11
+ await mkdir(core);await mkdir(state);
12
+ const coding={schema:'deadbyte.coding-policy.v1',enabled:true,lease_file:path.join(dir,'manual','coding-grant.json'),
13
+ evidence_dir:path.join(dir,'manual','evidence'),roots:{core:{path:core,read:true,write:true,exec:true,deny_paths:[]},
14
+ local_c:{path:path.parse(dir).root,read:true,write:true,exec:true,deny_paths:[]}},
15
+ commands:{node_script:{kind:'script',executable:process.execPath,executable_sha256:'a'.repeat(64),
16
+ root_ids:['core','local_c'],prefix_args:[],extensions:['.mjs']}}};
17
+ const autonomous={schema:'deadbyte.autonomous-policy.v1',enabled:true,lease_file:path.join(dir,'manual','autonomous-grant.json'),
18
+ evidence_dir:path.join(dir,'manual','evidence-auto'),coding_policy_sha256:'b'.repeat(64),
19
+ root_ids:['core'],profiles:{quick:{root_id:'core',command_id:'node_script'}},
20
+ planner:{backend:'client_sampling'}};
21
+ await fn({coding,autonomous,state});
22
+ } finally {await rm(dir,{recursive:true,force:true})}
23
+ };
24
+ test('R136 projected command does not retain broad manual root_ids',async()=>{
25
+ await fixture(({coding,autonomous,state})=>{
26
+ const before=structuredClone(coding);
27
+ const result=deriveIsolatedAutonomousScope({manualCodingPolicy:coding,autonomousPolicy:autonomous,
28
+ scopeRootId:'core',isolatedStateRoot:state});
29
+ assert.deepEqual(result.codingPolicy.commands.node_script.root_ids,['core']);
30
+ assert.deepEqual(coding,before);
31
+ });
32
+ });
33
+ test('R136 command with no access to approved scope fails closed',async()=>{
34
+ await fixture(({coding,autonomous,state})=>{
35
+ coding.commands.node_script.root_ids=['local_c'];
36
+ assert.throws(()=>deriveIsolatedAutonomousScope({manualCodingPolicy:coding,autonomousPolicy:autonomous,
37
+ scopeRootId:'core',isolatedStateRoot:state}),/command.*outside approved scope/);
38
+ });
39
+ });
@@ -0,0 +1,89 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {mkdtemp,mkdir,writeFile,readFile,rm} from 'node:fs/promises';
4
+ import {createHash} from 'node:crypto';
5
+ import path from 'node:path';
6
+ import os from 'node:os';
7
+ import {startScopedObserver} from '../src/scoped-observer-launcher-r136.mjs';
8
+ import {deriveIsolatedAutonomousScope} from '../src/autonomous-scope-r135.mjs';
9
+ const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
10
+
11
+ async function prepared(run){
12
+ const temp=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r136-observer-'));
13
+ let observer=null;
14
+ try{
15
+ const project=path.join(temp,'project'),isolated=path.join(temp,'isolated');
16
+ await mkdir(project);await mkdir(isolated);
17
+ const manual={schema:'deadbyte.coding-policy.v1',enabled:true,lease_file:path.join(temp,'manual','coding-grant.json'),
18
+ evidence_dir:path.join(temp,'manual','evidence'),
19
+ roots:{core:{path:project,read:true,write:true,exec:true,deny_paths:[]},
20
+ local_d:{path:path.parse(temp).root,read:true,write:true,exec:true,deny_paths:[]}},
21
+ commands:{node_script:{kind:'script',root_ids:['core','local_d'],executable:process.execPath,
22
+ executable_sha256:'a'.repeat(64),prefix_args:[],extensions:['.mjs']}}};
23
+ const autonomous={schema:'deadbyte.autonomous-policy.v1',enabled:true,
24
+ lease_file:path.join(temp,'manual','autonomous-grant.json'),evidence_dir:path.join(temp,'manual','aevidence'),
25
+ coding_policy_sha256:'f'.repeat(64),root_ids:['core'],
26
+ planner:{backend:'client_sampling'},profiles:{quick:{kind:'command',root_id:'core',command_id:'node_script'}}};
27
+ const projected=deriveIsolatedAutonomousScope({manualCodingPolicy:manual,autonomousPolicy:autonomous,scopeRootId:'core',isolatedStateRoot:isolated});
28
+ const codingFile=path.join(isolated,'coding-policy.json'),autonomousFile=path.join(isolated,'autonomous-policy.json');
29
+ await writeFile(codingFile,projected.codingBytes);
30
+ await writeFile(autonomousFile,projected.autonomousBytes);
31
+ const options={stateRoot:isolated,codingPolicyFile:codingFile,autonomousPolicyFile:autonomousFile,
32
+ codingSha256:projected.coding_sha256,autonomousSha256:projected.autonomous_sha256};
33
+ await run({temp,isolated,options,projected,manual,autonomous,setObserver:v=>observer=v});
34
+ } finally {
35
+ if(observer)await observer.close();
36
+ await rm(temp,{recursive:true,force:true});
37
+ }
38
+ }
39
+ test('R136 observer starts in its own PID disarmed, with no inherited broad Coding policy or ambient secrets',async()=>{
40
+ await prepared(async({options,projected,setObserver})=>{
41
+ const obs=await startScopedObserver({...options, ambientEnv:{DEADBYTE_CODING_POLICY:'C:\\\\evil.json',
42
+ DEADBYTE_STATE_ROOT:'C:\\\\Users\\\\DEADBYTE\\\\.deadbyte-mcp',NODE_OPTIONS:'--inspect',
43
+ OPENAI_API_KEY:'DO_NOT_LEAK'}});
44
+ setObserver(obs);
45
+ const result=obs.ready;
46
+ assert.ok(Number.isInteger(result.pid)&&result.pid>0);
47
+ assert.notEqual(result.pid,process.pid);
48
+ assert.equal(result.status,'DISARMED');
49
+ assert.deepEqual(result.root_ids,['core']);
50
+ assert.deepEqual(result.command_ids,['node_script']);
51
+ assert.equal(result.coding_sha256,projected.coding_sha256);
52
+ assert.equal(result.autonomous_sha256,projected.autonomous_sha256);
53
+ assert.equal(result.ambient_deadbyte_keys,0);
54
+ assert.equal(result.node_options_present,false);
55
+ assert.equal(result.user_token_present,false);
56
+ assert.equal(result.grant_files_present,false);
57
+ });
58
+ });
59
+ test('R136 observer refuses execute, arm and privileged requests instead of invoking any host tool',async()=>{
60
+ await prepared(async({options,setObserver})=>{
61
+ const obs=await startScopedObserver(options);setObserver(obs);
62
+ for(const action of ['execute','arm','write','host_exec','unknown']){
63
+ const reply=await obs.request({op:action,root_id:'core',command_id:'node_script'});
64
+ assert.deepEqual(reply,{status:'DENIED_UNAUTHORIZED',op:action});
65
+ }
66
+ assert.deepEqual(await obs.request({op:'status'}),{status:'DISARMED',root_ids:['core']});
67
+ });
68
+ });
69
+ test('R136 client-controlled IPC envelope fields cannot override request identity',async()=>{
70
+ await prepared(async({options,setObserver})=>{
71
+ const obs=await startScopedObserver(options);setObserver(obs);
72
+ const result=await obs.request({kind:'reply',id:9999,op:'execute'});
73
+ assert.deepEqual(result,{status:'DENIED_UNAUTHORIZED',op:'execute'});
74
+ });
75
+ });
76
+
77
+ test('R136 observer rejects policy byte tampering against SHA-pinned startup',async()=>{
78
+ await prepared(async({options})=>{
79
+ await writeFile(options.codingPolicyFile,Buffer.concat([await readFile(options.codingPolicyFile),Buffer.from(' ')]));
80
+ await assert.rejects(startScopedObserver(options),/policy digest mismatch|observer boot failed/);
81
+ });
82
+ });
83
+ test('R136 observer refuses inherited grant bytes even when policy hashes match',async()=>{
84
+ await prepared(async({options,isolated})=>{
85
+ const dir=path.join(isolated,'runtime');await mkdir(dir,{recursive:true});
86
+ await writeFile(path.join(dir,'coding-grant.json'),Buffer.from('{"armed":true}\n'));
87
+ await assert.rejects(startScopedObserver(options),/grant present|observer boot failed/);
88
+ });
89
+ });
@@ -0,0 +1,111 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {mkdtemp,writeFile,readFile,readdir,rm} from 'node:fs/promises';
4
+ import path from 'node:path';
5
+ import os from 'node:os';
6
+ import {createHash} from 'node:crypto';
7
+ import {createCommanderExtendedRuntime} from '../src/commander-extended-runtime.mjs';
8
+ const sha=b=>createHash('sha256').update(b).digest('hex');
9
+ async function fixture(run){
10
+ const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r137-config-'));
11
+ try{await run({root,file:path.join(root,'commander-config.json')});}
12
+ finally{await rm(root,{recursive:true,force:true});}
13
+ }
14
+ test('R137 recovers bounded display limits from complete JSON prefix, not privileges or telemetry',async()=>{
15
+ await fixture(async({root,file})=>{
16
+ const corrupt=Buffer.from('{"fileReadLineLimit":200,"fileWriteLineLimit":20,"allowedDirectories":["C:\\\\","D:\\\\"],"telemetryEnabled":true,"defaultShell":"cmd.exe","theme":"light","blockedCommands":[],"damaged": [\n','utf8');
17
+ await writeFile(file,corrupt);
18
+ const runtime=createCommanderExtendedRuntime({stateRoot:root});
19
+ const cfg=await runtime.getConfig();
20
+ assert.equal(cfg.config.fileReadLineLimit,200);
21
+ assert.equal(cfg.config.fileWriteLineLimit,20);
22
+ assert.equal(cfg.config.telemetryEnabled,false);
23
+ assert.deepEqual(cfg.config.allowedDirectories,[]);
24
+ assert.equal(cfg.config.theme,undefined);
25
+ assert.equal(cfg.config.defaultShell,process.platform==='win32'?'powershell.exe':(process.env.SHELL||'/bin/sh'));
26
+ assert.equal(cfg.recovery?.status,'recovered');
27
+ assert.deepEqual(cfg.recovery?.salvaged_keys,['fileReadLineLimit','fileWriteLineLimit']);
28
+ const backups=(await readdir(root)).filter(f=>f.startsWith('commander-config.json.corrupt.'));
29
+ assert.equal(backups.length,1);
30
+ assert.equal(sha(await readFile(path.join(root,backups[0]))),sha(corrupt));
31
+ const stored=JSON.parse(await readFile(file,'utf8'));
32
+ assert.equal(stored.fileReadLineLimit,200);
33
+ assert.equal(stored.telemetryEnabled,false);
34
+ const next=await runtime.getConfig();
35
+ assert.equal(next.config_sha256,cfg.config_sha256);
36
+ assert.equal((await readdir(root)).filter(f=>f.startsWith('commander-config.json.corrupt.')).length,1);
37
+ });
38
+ });
39
+ test('R137 totally corrupt or oversized config recovers minimal defaults without inheriting blockedCommands/paths',async()=>{
40
+ await fixture(async({root,file})=>{
41
+ await writeFile(file,'garbled not JSON');
42
+ const config=await createCommanderExtendedRuntime({stateRoot:root}).getConfig();
43
+ assert.equal(config.recovery?.status,'recovered');
44
+ assert.deepEqual(config.recovery?.salvaged_keys,[]);
45
+ assert.deepEqual(config.config.allowedDirectories,[]);
46
+ assert.equal(config.config.telemetryEnabled,false);
47
+ assert.ok(!Object.hasOwn(config.config,'arbitraryAuthority'));
48
+ });
49
+ });
50
+ test('R137 ignores out-of-bounds limits in parseable prefix',async()=>{
51
+ await fixture(async({root,file})=>{
52
+ await writeFile(file,'{"fileReadLineLimit":999999,"fileWriteLineLimit":0,"allowedDirectories":["C:\\\\"],"broken":');
53
+ const config=await createCommanderExtendedRuntime({stateRoot:root}).getConfig();
54
+ assert.equal(config.config.fileReadLineLimit,1000);
55
+ assert.equal(config.config.fileWriteLineLimit,50);
56
+ assert.deepEqual(config.recovery?.salvaged_keys,[]);
57
+ });
58
+ });
59
+ test('R137 parallel configuration reads share one recovery and preserve original backup',async()=>{
60
+ await fixture(async({root,file})=>{
61
+ const raw=Buffer.from('{"fileReadLineLimit":210,"allowedDirectories":["C:\\\\"],"unfinished": [\n');
62
+ await writeFile(file,raw);
63
+ const rt=createCommanderExtendedRuntime({stateRoot:root});
64
+ const [a,b,c]=await Promise.all([rt.getConfig(),rt.getConfig(),rt.getConfig()]);
65
+ assert.deepEqual([a.config_sha256,b.config_sha256,c.config_sha256],[a.config_sha256,a.config_sha256,a.config_sha256]);
66
+ const backups=(await readdir(root)).filter(n=>n.startsWith('commander-config.json.corrupt.'));
67
+ assert.equal(backups.length,1);
68
+ assert.equal(sha(await readFile(path.join(root,backups[0]))),sha(raw));
69
+ });
70
+ });
71
+ test('R137 quoted commas and nested JSON do not spoof a recoverable top-level setting',async()=>{
72
+ await fixture(async({root,file})=>{
73
+ await writeFile(file,'{"description":"x, \\\"fileReadLineLimit\\\": 8","nested":{"fileReadLineLimit":1},"fileReadLineLimit":225,"bad": [');
74
+ const r=await createCommanderExtendedRuntime({stateRoot:root}).getConfig();
75
+ assert.equal(r.config.fileReadLineLimit,225);
76
+ assert.deepEqual(r.recovery?.salvaged_keys,['fileReadLineLimit']);
77
+ });
78
+ });
79
+ test('R137 valid non-object JSON is not trusted as configuration',async()=>{
80
+ await fixture(async({root,file})=>{
81
+ await writeFile(file,'["allowedDirectories","C:\\\\"]');
82
+ const r=await createCommanderExtendedRuntime({stateRoot:root}).getConfig();
83
+ assert.equal(r.recovery?.status,'recovered');
84
+ assert.deepEqual(r.config.allowedDirectories,[]);
85
+ });
86
+ });
87
+
88
+ test('R137 preserves the existing valid config without making recovery backup',async()=>{
89
+ await fixture(async({root,file})=>{
90
+ await writeFile(file,JSON.stringify({theme:'classic',telemetryEnabled:false}));
91
+ const result=await createCommanderExtendedRuntime({stateRoot:root}).getConfig();
92
+ assert.equal(result.config.theme,'classic');
93
+ assert.equal(result.recovery,undefined);
94
+ assert.deepEqual(await readdir(root),['commander-config.json']);
95
+ });
96
+ });
97
+ test('R137 recovered config remains hash-preconditioned for subsequent edits',async()=>{
98
+ await fixture(async({root,file})=>{
99
+ await writeFile(file,'{"fileReadLineLimit":333,"bad":[');
100
+ const runtime=createCommanderExtendedRuntime({stateRoot:root});
101
+ const first=await runtime.getConfig();
102
+ await assert.rejects(runtime.setConfigValue({key:'theme',value:'classic',expected_sha256:'0'.repeat(64)}),/precondition/);
103
+ const done=await runtime.setConfigValue({key:'theme',value:'classic',expected_sha256:first.config_sha256});
104
+ assert.equal(done.status,'committed');
105
+ const fresh=createCommanderExtendedRuntime({stateRoot:root});
106
+ const now=await fresh.getConfig();
107
+ assert.equal(now.config.theme,'classic');
108
+ assert.equal(now.config.fileReadLineLimit,333);
109
+ assert.equal(now.recovery,undefined);
110
+ });
111
+ });
@@ -0,0 +1,56 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {readFile} from 'node:fs/promises';
4
+ import {createHash} from 'node:crypto';
5
+ import {pathToFileURL} from 'node:url';
6
+ import path from 'node:path';
7
+ import {createCommanderWireAdapter} from '../src/commander-wire-adapter-r47.mjs';
8
+ import {registerCommanderExtendedBridge} from '../src/commander-extended-bridge-r47.mjs';
9
+
10
+ const base='D:\\Projects\\deadbyte-mcp\\references';
11
+ const fixtures=[
12
+ {version:'0.2.52',relative:'desktop-commander v0.2.52/dist/tools/schemas.js',sha256:'f342345e34e48769dabaefe1b932f09d41e2e207b422f7794a15ee50ffa8f140',tools:27},
13
+ {version:'0.3.0',relative:'desktop-commander v0.3.0/dist/tools/schemas.js',sha256:'7d4c62e2099d757d8fba68011cfe25d3088426f56c0b77d5b8fa3edb4ec49c2c',tools:26},
14
+ {version:'0.3.1-alpha.2',relative:'desktop-commander-0.3.1-alpha.2/static/dist/tools/schemas.js',sha256:'6a290497b29f9dc5f43d66008ea54fcf0c302edea5612af519ef52ab3816d29e',tools:27}
15
+ ];
16
+ const known={
17
+ get_config:{},set_config_value:{key:'theme',value:'classic'},read_file:{path:'x'},read_multiple_files:{paths:['x']},
18
+ write_file:{path:'x',content:'v'},write_pdf:{path:'x',content:'# x'},create_directory:{path:'x'},
19
+ list_directory:{path:'x'},move_file:{source:'a',destination:'b'},start_search:{path:'.',pattern:'x'},
20
+ get_more_search_results:{sessionId:'s'},stop_search:{sessionId:'s'},list_searches:{},get_file_info:{path:'x'},
21
+ edit_block:{file_path:'x',old_string:'a',new_string:'b'},start_process:{command:'echo x',timeout_ms:10},
22
+ read_process_output:{pid:1},interact_with_process:{pid:1,input:'x'},force_terminate:{pid:1},list_sessions:{},
23
+ list_processes:{},kill_process:{pid:1},get_usage_stats:{},get_recent_tool_calls:{},
24
+ give_feedback_to_desktop_commander:{},get_prompts:{action:'get_prompt',promptId:'x'}
25
+ };
26
+ const sha=s=>createHash('sha256').update(s).digest('hex');
27
+ const unwrap=o=>{while(o?._def?.schema)o=o._def.schema;return o};
28
+ function candidate(){
29
+ const v={...createCommanderWireAdapter({}).schemas};
30
+ registerCommanderExtendedBridge({registerTool(name,def){v[name]=def.inputSchema;}},{extendedRuntime:{}});
31
+ return v;
32
+ }
33
+ async function reference(f){
34
+ const bytes=await readFile(path.join(base,f.relative));
35
+ assert.equal(sha(bytes),f.sha256,'reference source SHA drift: '+f.version);
36
+ const zod=pathToFileURL(path.resolve('node_modules/zod/v3/index.js')).href;
37
+ const source=bytes.toString('utf8').replace('from "zod"','from '+JSON.stringify(zod));
38
+ return (await import('data:text/javascript;base64,'+Buffer.from(source).toString('base64'))).toolArgSchemas;
39
+ }
40
+ for(const fixture of fixtures){
41
+ test('R137 pinned Desktop Commander '+fixture.version+' public tool schemas remain compatible',async()=>{
42
+ const r=await reference(fixture),c=candidate();
43
+ assert.equal(Object.keys(r).length,fixture.tools);
44
+ if(fixture.version==='0.3.0')assert.equal(Object.hasOwn(r,'get_prompts'),false);
45
+ for(const [name,refSchema] of Object.entries(r)){
46
+ // track_ui_event is a deliberately hidden UI dispatch, not a public MCP tool.
47
+ if(name==='track_ui_event')continue;
48
+ assert.ok(c[name],'DEADBYTE missing '+name);
49
+ assert.deepEqual(Object.keys(unwrap(c[name]).shape).sort(),Object.keys(unwrap(refSchema).shape).sort(),name+' property names');
50
+ const expected=refSchema.safeParse({...known[name],__future_extra:'strip'});
51
+ const actual=c[name].safeParse({...known[name],__future_extra:'strip'});
52
+ assert.equal(actual.success,expected.success,name+' input acceptance');
53
+ if(actual.success)assert.deepEqual(actual.data,expected.data,name+' normalized defaults');
54
+ }
55
+ });
56
+ }
@@ -0,0 +1,42 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {createCommanderExternalProcessRuntime} from '../src/commander-external-process-r48.mjs';
4
+
5
+ const snapshot='a'.repeat(64),stamp='2026-10-21T11:00:00.000Z';
6
+ const row=(pid)=>({pid,parent_pid:1,name:'test'+pid+'.exe',ownership:'external',
7
+ creation_time_utc:stamp,executable_path:null,command_line:null});
8
+ const page=(items,cursor=null,identity=snapshot)=>({status:'ok',snapshot_id:identity,observed_at_utc:stamp,
9
+ processes:items,next_cursor:cursor,receipt_id:'b'.repeat(24)});
10
+ function fixture(sequence){
11
+ let index=0;
12
+ const observationRuntime={async processList(){return sequence[Math.min(index++,sequence.length-1)];}};
13
+ return {runtime:createCommanderExternalProcessRuntime({observationRuntime}),calls:()=>index};
14
+ }
15
+ test('R138 rejects a repeated external process cursor instead of polling forever',async()=>{
16
+ const f=fixture([page([row(1)],'repeat'),page([row(2)],'repeat')]);
17
+ await assert.rejects(f.runtime.list(),/cursor.*repeat|pagination.*cycle/i);
18
+ assert.equal(f.calls(),2);
19
+ });
20
+ test('R138 rejects duplicate PID across pages instead of creating ambiguous kill target',async()=>{
21
+ const f=fixture([page([row(42)],'next'),page([row(42)],null)]);
22
+ await assert.rejects(f.runtime.list(),/duplicate.*PID/i);
23
+ assert.equal(f.calls(),2);
24
+ });
25
+ test('R138 rejects contradictory observation timestamps across a single snapshot',async()=>{
26
+ const f=fixture([page([row(1)],'next'),{...page([row(2)]),observed_at_utc:'2026-10-21T12:00:00.000Z'}]);
27
+ await assert.rejects(f.runtime.list(),/observation time.*changed|timestamp.*changed/i);
28
+ });
29
+ test('R138 rejects invalid missing snapshot identity and unbounded cursor',async()=>{
30
+ const f=fixture([{...page([row(1)]),snapshot_id:null}]);
31
+ await assert.rejects(f.runtime.list(),/snapshot.*identity/i);
32
+ const oversized=fixture([page([row(1)],'x'.repeat(12000))]);
33
+ await assert.rejects(oversized.runtime.list(),/cursor.*invalid/i);
34
+ });
35
+ test('R138 normal two-page process observation preserves ordered identities and receipts',async()=>{
36
+ const f=fixture([page([row(1)],'next'),page([row(2)])]);
37
+ const r=await f.runtime.list();
38
+ assert.deepEqual(r.processes.map(x=>x.pid),[1,2]);
39
+ assert.equal(r.snapshot_id,snapshot);
40
+ assert.deepEqual(r.receipt_ids,['b'.repeat(24)]);
41
+ assert.equal(f.calls(),2);
42
+ });
@@ -0,0 +1,24 @@
1
+ import test from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import {createCommanderWireAdapter} from '../src/commander-wire-adapter-r47.mjs';
4
+ test('R138 Commander sessions show PID, profile, root, and exit outcome in one line',async()=>{
5
+ const sessions=[
6
+ {session_id:'a'.repeat(64),child_pid:21138,state:'running',exit_code:null,profile_id:'powershell',root_id:'core',stream_head:17},
7
+ {session_id:'b'.repeat(64),child_pid:22138,state:'exited',exit_code:7,profile_id:'node',root_id:'build',stream_head:20}
8
+ ];
9
+ const a=createCommanderWireAdapter({processRuntime:{async list(){return {sessions}}}});
10
+ const r=await a.handlers.list_sessions({});
11
+ assert.equal(r.isError,undefined);
12
+ assert.deepEqual(r.structuredContent.sessions,sessions);
13
+ assert.match(r.content[0].text,/PID=21138/);
14
+ assert.match(r.content[0].text,/PID=22138/);
15
+ assert.match(r.content[0].text,/exit=7/);
16
+ assert.match(r.content[0].text,/profile=node/);
17
+ assert.match(r.content[0].text,/root=build/);
18
+ });
19
+ test('R138 no sessions returns a readable empty summary',async()=>{
20
+ const a=createCommanderWireAdapter({processRuntime:{async list(){return {sessions:[]}}}});
21
+ const r=await a.handlers.list_sessions({});
22
+ assert.match(r.content[0].text,/No managed sessions/);
23
+ assert.deepEqual(r.structuredContent.sessions,[]);
24
+ });