deadbyte-mcp 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (121) hide show
  1. package/MANIFEST.SHA256 +119 -91
  2. package/README.txt +16 -11
  3. package/bench/fixtures/corpus.json +32 -13
  4. package/bench/fixtures/r36/case-map.json +8 -0
  5. package/bin/WORKER-REGISTRY.txt +3 -3
  6. package/bin/appcontainer-stage.exe +0 -0
  7. package/bin/appcontainer-stage.obj +0 -0
  8. package/bin/bootstrap-advapi32.exe +0 -0
  9. package/bin/bootstrap-advapi32.obj +0 -0
  10. package/bin/bootstrap-exitcode.exe +0 -0
  11. package/bin/bootstrap-exitcode.obj +0 -0
  12. package/bin/bootstrap-kernel32.exe +0 -0
  13. package/bin/bootstrap-kernel32.obj +0 -0
  14. package/bin/child-control-probe.exe +0 -0
  15. package/bin/child-control-probe.obj +0 -0
  16. package/bin/child-control-stage.exe +0 -0
  17. package/bin/child-control-stage.obj +0 -0
  18. package/bin/contained-reverse-worker.exe +0 -0
  19. package/bin/contained-reverse-worker.obj +0 -0
  20. package/bin/contained-transform-worker.exe +0 -0
  21. package/bin/contained-transform-worker.obj +0 -0
  22. package/bin/containment-probe.exe +0 -0
  23. package/bin/containment-probe.obj +0 -0
  24. package/bin/deadbyte-contain.exe +0 -0
  25. package/bin/deadbyte-contain.obj +0 -0
  26. package/bin/deadbyte-exec.exe +0 -0
  27. package/bin/deadbyte-exec.obj +0 -0
  28. package/bin/deadbyte-process-host.exe +0 -0
  29. package/bin/deadbyte-process-host.obj +0 -0
  30. package/bin/deadbyte-tunnel-host.exe +0 -0
  31. package/bin/deadbyte-tunnel-host.obj +0 -0
  32. package/controller/README.TXT +8 -6
  33. package/controller/deadbyte-controller.ps1 +48 -2
  34. package/controller/deadbyte-process-policy.json +5 -5
  35. package/docs/ARCHITECTURE.md +1 -1
  36. package/docs/R36-CAPABILITY-EVIDENCE.md +43 -0
  37. package/docs/superpowers/plans/2026-09-18-r36-zero-loss-autonomy.md +739 -0
  38. package/docs/superpowers/specs/2026-09-18-r36-zero-loss-autonomy-design.md +640 -0
  39. package/package.json +1 -1
  40. package/proof/CONTAINMENT-BUILD.txt +6 -6
  41. package/scripts/deferred-slot-operation.mjs +53 -15
  42. package/scripts/final-closure-verify.mjs +88 -39
  43. package/scripts/final-closure.mjs +63 -56
  44. package/scripts/gate-windows.ps1 +3 -3
  45. package/scripts/release-parity-tests.ps1 +9 -0
  46. package/scripts/release-parity.mjs +149 -139
  47. package/scripts/windows-gate-evidence.mjs +5 -5
  48. package/src/autonomous-context-engine.mjs +2 -1
  49. package/src/autonomous-mcp-tools.mjs +5 -1
  50. package/src/autonomous-output-contracts.mjs +4 -4
  51. package/src/autonomous-planner-contracts.mjs +36 -1
  52. package/src/autonomous-planner.mjs +25 -3
  53. package/src/autonomous-runtime.mjs +191 -21
  54. package/src/capability-benchmark-runner.mjs +86 -1
  55. package/src/capability-benchmark.mjs +45 -0
  56. package/src/capability-ledger.mjs +158 -0
  57. package/src/coding-mcp-tools.mjs +31 -17
  58. package/src/coding-output-contracts.mjs +48 -10
  59. package/src/coding-plane.mjs +45 -9
  60. package/src/coding-search.mjs +130 -47
  61. package/src/compact-gateway-mcp-tools.mjs +128 -0
  62. package/src/compact-gateway-output-contracts.mjs +16 -0
  63. package/src/deadbyte-cli.mjs +51 -28
  64. package/src/machine-fs-smoke-client.mjs +1 -1
  65. package/src/machine-fs.mjs +51 -8
  66. package/src/mcp-server.mjs +32 -9
  67. package/src/native-diff-v2.mjs +337 -0
  68. package/src/native-diff.mjs +50 -2
  69. package/src/observation-smoke-client.mjs +1 -1
  70. package/src/operator-surface.mjs +7 -1
  71. package/src/process-runtime.mjs +98 -11
  72. package/src/process-smoke-client.mjs +11 -3
  73. package/src/r36-compact-disarmed-probe.mjs +50 -0
  74. package/src/r36-full-surface-probe.mjs +56 -0
  75. package/src/remote-live-log.mjs +76 -0
  76. package/src/remote-mcp-autonomous-smoke-client.mjs +7 -3
  77. package/src/remote-mcp-coding-smoke-client.mjs +1 -1
  78. package/src/remote-mcp-r36-parity-client.mjs +175 -0
  79. package/src/remote-mcp-smoke-client.mjs +112 -56
  80. package/src/runtime-update.mjs +51 -1
  81. package/src/search-cursor.mjs +45 -0
  82. package/src/semantic-code.mjs +72 -5
  83. package/src/semantic-lsp-backend.mjs +39 -3
  84. package/src/version.mjs +1 -1
  85. package/test/autonomous-capability-r36.test.mjs +151 -0
  86. package/test/autonomous-runtime.test.mjs +2 -2
  87. package/test/capability-benchmark-r36.test.mjs +107 -0
  88. package/test/capability-benchmark-semantic-r36.test.mjs +52 -0
  89. package/test/capability-claims-r36.test.mjs +23 -0
  90. package/test/capability-ledger-r36.test.mjs +102 -0
  91. package/test/coding-catalog-consistency.test.mjs +2 -2
  92. package/test/coding-plane.test.mjs +2 -2
  93. package/test/coding-runtime.test.mjs +16 -0
  94. package/test/coding-search-r36.test.mjs +90 -0
  95. package/test/compact-catalog-r36.test.mjs +37 -0
  96. package/test/compact-gateway-r36.test.mjs +66 -0
  97. package/test/contained.test.mjs +1 -1
  98. package/test/core.test.mjs +1 -1
  99. package/test/deferred-slot-operation.test.mjs +9 -0
  100. package/test/fixtures/lsp-framed-server.mjs +2 -0
  101. package/test/helpers/autonomous-r34-fixture.mjs +5 -3
  102. package/test/multi-file-read.test.mjs +3 -0
  103. package/test/native-diff-topology-r36.test.mjs +105 -0
  104. package/test/package-boundary.test.mjs +6 -0
  105. package/test/process-longrun-r36.test.mjs +82 -0
  106. package/test/process-release-gate.test.mjs +9 -0
  107. package/test/production-docs.test.mjs +3 -3
  108. package/test/prompts-resources.test.mjs +7 -1
  109. package/test/r33-closeout-regression.test.mjs +4 -3
  110. package/test/r33-finalization.test.mjs +14 -9
  111. package/test/r36-finalization.test.mjs +104 -0
  112. package/test/r36-release-identity.test.mjs +52 -0
  113. package/test/release-version.test.mjs +18 -15
  114. package/test/remote-live-log-r36.test.mjs +37 -0
  115. package/test/remote-live-log-recovery-r36.test.mjs +41 -0
  116. package/test/remote-r24-catalog.test.mjs +13 -0
  117. package/test/remote-session-cli.test.mjs +40 -30
  118. package/test/runtime-self-update.test.mjs +58 -1
  119. package/test/semantic-lsp-backend.test.mjs +9 -0
  120. package/test/semantic-r36-rename.test.mjs +82 -0
  121. package/deadbyte-mcp-0.8.9.tgz +0 -0
@@ -0,0 +1,128 @@
1
+ import * as z from 'zod/v4';
2
+ import { compactGatewayOutputSchema, compactGatewayResult } from './compact-gateway-output-contracts.mjs';
3
+
4
+ const id=z.string().regex(/^[A-Za-z0-9._-]{1,64}$/);
5
+ const rel=z.string().min(1).max(2048);
6
+ const rel512=z.string().min(1).max(512);
7
+ const hex64=z.string().regex(/^[0-9a-f]{64}$/);
8
+ const cursor=z.string().max(4096).nullable().default(null);
9
+ const nonneg=z.number().int().nonnegative();
10
+ const symbolName=z.string().regex(/^[A-Za-z_$][A-Za-z0-9_$]{0,127}$/);
11
+
12
+ export const codingInspectInputSchema=z.discriminatedUnion('op',[
13
+ z.strictObject({op:z.literal('stat'),root_id:id,path:rel512.default('.'),hash:z.boolean().default(false)}),
14
+ z.strictObject({op:z.literal('search'),root_id:id,path:rel512.default('.'),pattern:z.string().min(1).max(256),target:z.enum(['content','path']).default('content'),mode:z.enum(['literal','regex']).default('literal'),case_sensitive:z.boolean().default(false),max_results:z.number().int().min(1).max(1000).default(200),max_file_bytes:z.number().int().min(1).max(4*1024*1024).default(262144),max_scan_bytes:z.number().int().min(1).max(64*1024*1024).default(4*1024*1024),page_size:z.number().int().min(1).max(500).default(100),cursor}),
15
+ z.strictObject({op:z.literal('files_read'),root_id:id,files:z.array(z.strictObject({path:rel512,encoding:z.enum(['utf8','base64']).default('utf8')})).min(1).max(32),max_total_bytes:z.number().int().min(1).max(2097152).default(1048576)}),
16
+ z.strictObject({op:z.literal('symbol_outline'),root_id:id,path:rel512,max_symbols:z.number().int().min(1).max(500).default(200)}),
17
+ z.strictObject({op:z.literal('symbol_definition'),root_id:id,path:rel512,line:nonneg,column:nonneg,max_results:z.number().int().min(1).max(200).default(50)}),
18
+ z.strictObject({op:z.literal('symbol_references'),root_id:id,path:rel512,line:nonneg,column:nonneg,max_results:z.number().int().min(1).max(500).default(200)}),
19
+ z.strictObject({op:z.literal('symbol_diagnostics'),root_id:id,path:rel512,max_results:z.number().int().min(1).max(500).default(200)}),
20
+ z.strictObject({op:z.literal('symbol_implementations'),root_id:id,path:rel512,line:nonneg,column:nonneg,max_results:z.number().int().min(1).max(500).default(200)}),
21
+ z.strictObject({op:z.literal('symbol_rename_preview'),root_id:id,path:rel512,line:nonneg,column:nonneg,new_name:symbolName})
22
+ ]);
23
+
24
+ export const machineFsGatewayInputSchema=z.discriminatedUnion('op',[
25
+ z.strictObject({op:z.literal('stat'),root_id:id,path:rel.default('.'),hash:z.boolean().default(false)}),
26
+ 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)}),
27
+ z.strictObject({op:z.literal('read'),root_id:id,path:rel,offset:nonneg.default(0),max_bytes:z.number().int().min(1).max(4*1024*1024).default(65536),hash_file:z.boolean().default(false)}),
28
+ 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})$/)}),
29
+ 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)}),
30
+ z.strictObject({op:z.literal('mkdir'),root_id:id,path:rel}),
31
+ z.strictObject({op:z.literal('move'),root_id:id,source_path:rel,destination_path:rel,expected_source_identity:hex64}),
32
+ z.strictObject({op:z.literal('delete'),root_id:id,path:rel,expected_source_identity:hex64})
33
+ ]);
34
+
35
+ export const processSessionGatewayInputSchema=z.discriminatedUnion('op',[
36
+ z.strictObject({op:z.literal('start'),profile_id:id,root_id:id,cwd:rel.default('.'),args:z.array(z.string().max(8192)).max(64).default([])}),
37
+ z.strictObject({op:z.literal('read'),session_id:hex64,offset:nonneg.default(0),max_bytes:z.number().int().min(1).max(262144).default(65536)}),
38
+ z.strictObject({op:z.literal('status'),session_id:hex64}),
39
+ z.strictObject({op:z.literal('list')}),
40
+ z.strictObject({op:z.literal('action'),session_id:hex64,action_id:id}),
41
+ z.strictObject({op:z.literal('terminate'),session_id:hex64})
42
+ ]);
43
+
44
+ export const machineObserveInputSchema=z.discriminatedUnion('op',[
45
+ z.strictObject({op:z.literal('machine_list')}),
46
+ z.strictObject({op:z.literal('machine_status')}),
47
+ z.strictObject({op:z.literal('machine_ping'),nonce:z.string().min(1).max(256)}),
48
+ z.strictObject({op:z.literal('search_start'),root_id:id,path:rel512.default('.'),pattern:z.string().min(1).max(256),case_sensitive:z.boolean().default(false),max_results:z.number().int().min(1).max(1000).default(200),max_files:z.number().int().min(1).max(10000).default(2000),max_bytes:z.number().int().min(1).max(64*1024*1024).default(4*1024*1024),max_file_bytes:z.number().int().min(1).max(4*1024*1024).default(262144)}),
49
+ z.strictObject({op:z.literal('search_page'),search_id:hex64,limit:z.number().int().min(1).max(500).default(100),cursor:z.string().max(512).nullable().default(null)}),
50
+ z.strictObject({op:z.literal('search_status'),search_id:hex64}),
51
+ z.strictObject({op:z.literal('search_cancel'),search_id:hex64}),
52
+ z.strictObject({op:z.literal('process_list'),limit:z.number().int().min(1).max(256).default(100),include_external:z.boolean().default(false),cursor:z.string().max(512).nullable().default(null)}),
53
+ z.strictObject({op:z.literal('system_status')})
54
+ ]);
55
+
56
+ const capabilityManifestInputSchema=z.strictObject({});
57
+
58
+ function unavailable(op,name){return compactGatewayResult({status:'unavailable',op,error:`${name} runtime unavailable`},true);}
59
+ async function invoke(op,runtime,name,call){
60
+ if(!runtime) return unavailable(op,name);
61
+ try{return compactGatewayResult({status:'ok',op,result:await call(runtime)},false);}
62
+ catch(error){return compactGatewayResult({status:'denied',op,error:String(error)},true);}
63
+ }
64
+
65
+ async function codingInspect(args,codingRuntime,semanticRuntime){
66
+ switch(args.op){
67
+ case 'stat': return invoke(args.op,codingRuntime,'coding',r=>r.stat({rootId:args.root_id,relativePath:args.path,hash:args.hash}));
68
+ case 'search': return invoke(args.op,codingRuntime,'coding',r=>r.search({rootId:args.root_id,path:args.path,pattern:args.pattern,target:args.target,mode:args.mode,caseSensitive:args.case_sensitive,maxResults:args.max_results,maxFileBytes:args.max_file_bytes,maxScanBytes:args.max_scan_bytes,pageSize:args.page_size,cursor:args.cursor}));
69
+ case 'files_read': return invoke(args.op,codingRuntime,'coding',r=>r.filesRead({rootId:args.root_id,files:args.files,maxTotalBytes:args.max_total_bytes}));
70
+ case 'symbol_outline': return invoke(args.op,semanticRuntime,'semantic',r=>r.outline({rootId:args.root_id,relativePath:args.path,maxSymbols:args.max_symbols}));
71
+ case 'symbol_definition': return invoke(args.op,semanticRuntime,'semantic',r=>r.definition({rootId:args.root_id,relativePath:args.path,line:args.line,column:args.column,maxResults:args.max_results}));
72
+ case 'symbol_references': return invoke(args.op,semanticRuntime,'semantic',r=>r.references({rootId:args.root_id,relativePath:args.path,line:args.line,column:args.column,maxResults:args.max_results}));
73
+ case 'symbol_diagnostics': return invoke(args.op,semanticRuntime,'semantic',r=>r.diagnostics({rootId:args.root_id,relativePath:args.path,maxResults:args.max_results}));
74
+ case 'symbol_implementations': return invoke(args.op,semanticRuntime,'semantic',r=>{if(typeof r.implementations!=='function') throw new Error('semantic implementations unavailable');return r.implementations({rootId:args.root_id,relativePath:args.path,line:args.line,column:args.column,maxResults:args.max_results});});
75
+ case 'symbol_rename_preview': return invoke(args.op,semanticRuntime,'semantic',r=>{if(typeof r.renamePreview!=='function') throw new Error('semantic rename preview unavailable');return r.renamePreview({rootId:args.root_id,relativePath:args.path,line:args.line,column:args.column,newName:args.new_name});});
76
+ }
77
+ }
78
+
79
+ async function machineFs(args,runtime){
80
+ const map={
81
+ stat:r=>r.stat({rootId:args.root_id,relativePath:args.path,hash:args.hash}),
82
+ list:r=>r.list({rootId:args.root_id,relativePath:args.path,cursor:args.cursor,limit:args.limit,hashFiles:args.hash_files}),
83
+ read:r=>r.read({rootId:args.root_id,relativePath:args.path,offset:args.offset,maxBytes:args.max_bytes,hashFile:args.hash_file}),
84
+ write:r=>r.write({rootId:args.root_id,relativePath:args.path,content:args.content,encoding:args.encoding,expectedSha256:args.expected_sha256}),
85
+ edit_exact:r=>r.editExact({rootId:args.root_id,relativePath:args.path,expectedSha256:args.expected_sha256,oldString:args.old_string,newString:args.new_string,expectedReplacements:args.expected_replacements}),
86
+ mkdir:r=>r.mkdir({rootId:args.root_id,relativePath:args.path}),
87
+ move:r=>r.move({rootId:args.root_id,sourcePath:args.source_path,destinationPath:args.destination_path,expectedSourceIdentity:args.expected_source_identity}),
88
+ delete:r=>r.delete({rootId:args.root_id,relativePath:args.path,expectedSourceIdentity:args.expected_source_identity})
89
+ };
90
+ return invoke(args.op,runtime,'machine_fs',map[args.op]);
91
+ }
92
+
93
+ async function processSession(args,runtime){
94
+ const map={
95
+ start:r=>r.start({profileId:args.profile_id,rootId:args.root_id,cwd:args.cwd,args:args.args}),
96
+ read:r=>r.read({sessionId:args.session_id,offset:args.offset,maxBytes:args.max_bytes}),
97
+ status:r=>r.status({sessionId:args.session_id}),
98
+ list:r=>r.list(),
99
+ action:r=>r.action({sessionId:args.session_id,actionId:args.action_id}),
100
+ terminate:r=>r.terminate({sessionId:args.session_id})
101
+ };
102
+ return invoke(args.op,runtime,'process',map[args.op]);
103
+ }
104
+
105
+ async function machineObserve(args,machineRuntime,observationRuntime){
106
+ if(args.op==='machine_list') return invoke(args.op,machineRuntime,'machine',r=>r.list());
107
+ if(args.op==='machine_status') return invoke(args.op,machineRuntime,'machine',r=>r.status());
108
+ if(args.op==='machine_ping') return invoke(args.op,machineRuntime,'machine',r=>r.ping({nonce:args.nonce}));
109
+ const map={
110
+ search_start:r=>r.searchStart({rootId:args.root_id,relativePath:args.path,pattern:args.pattern,caseSensitive:args.case_sensitive,maxResults:args.max_results,maxFiles:args.max_files,maxBytes:args.max_bytes,maxFileBytes:args.max_file_bytes}),
111
+ search_page:r=>r.searchPage({searchId:args.search_id,limit:args.limit,cursor:args.cursor}),
112
+ search_status:r=>r.searchStatus({searchId:args.search_id}),
113
+ search_cancel:r=>r.searchCancel({searchId:args.search_id}),
114
+ process_list:r=>r.processList({limit:args.limit,includeExternal:args.include_external,cursor:args.cursor}),
115
+ system_status:r=>r.systemStatus()
116
+ };
117
+ return invoke(args.op,observationRuntime,'observation',map[args.op]);
118
+ }
119
+
120
+ export function registerCompactGatewayTools(server,{profile,ledger,codingRuntime,semanticRuntime,machineFsRuntime,processRuntime,observationRuntime,machineRuntime}){
121
+ if(!server) throw new Error('compact gateway registration requires server');
122
+ if(profile!=='compact') return;
123
+ server.registerTool('capability_manifest',{description:'Read the canonical R36 capability ledger and active compact profile.',inputSchema:capabilityManifestInputSchema,outputSchema:compactGatewayOutputSchema},async()=>compactGatewayResult({status:'ok',op:'manifest',result:{schema:'deadbyte.capability-manifest.v1',profile,ledger_sha256:ledger?.ledger_sha256??null,capabilities:ledger?.entries??[]}},false));
124
+ server.registerTool('coding_inspect',{description:'Typed compact coding inspection and semantic navigation gateway. No arbitrary tool dispatch.',inputSchema:codingInspectInputSchema,outputSchema:compactGatewayOutputSchema},args=>codingInspect(args,codingRuntime,semanticRuntime));
125
+ server.registerTool('machine_fs',{description:'Typed compact machine filesystem gateway preserving root policy and mutation preconditions.',inputSchema:machineFsGatewayInputSchema,outputSchema:compactGatewayOutputSchema},args=>machineFs(args,machineFsRuntime));
126
+ server.registerTool('process_session',{description:'Typed compact DEADBYTE-owned process session gateway. No raw stdin or PID authority.',inputSchema:processSessionGatewayInputSchema,outputSchema:compactGatewayOutputSchema},args=>processSession(args,processRuntime));
127
+ server.registerTool('machine_observe',{description:'Typed compact machine identity and read-only observation gateway. Revoke is intentionally excluded.',inputSchema:machineObserveInputSchema,outputSchema:compactGatewayOutputSchema},args=>machineObserve(args,machineRuntime,observationRuntime));
128
+ }
@@ -0,0 +1,16 @@
1
+ import * as z from 'zod/v4';
2
+ import { structuredToolResult } from './output-contracts.mjs';
3
+
4
+ export const compactGatewayOutputSchema=z.strictObject({
5
+ status:z.enum(['ok','denied','failed','unavailable']),
6
+ op:z.string().min(1).max(64),
7
+ result:z.json().optional(),
8
+ error:z.string().max(4096).optional()
9
+ }).superRefine((value,ctx)=>{
10
+ if(value.status==='ok'&&value.result===undefined) ctx.addIssue({code:'custom',path:['result'],message:'result is required for status=ok'});
11
+ if(value.status!=='ok'&&value.error===undefined) ctx.addIssue({code:'custom',path:['error'],message:'error is required for non-ok status'});
12
+ });
13
+
14
+ export function compactGatewayResult(value,isError=false){
15
+ return structuredToolResult(compactGatewayOutputSchema,value,isError);
16
+ }
@@ -9,18 +9,19 @@ import { fileURLToPath } from 'node:url';
9
9
  import { defaultPublicKeyPath } from './trust.mjs';
10
10
  import { verifyAuditChain } from './audit-verify.mjs';
11
11
  import { openRemoteResultJournal, parseRemoteResultCursor } from './remote-result-journal.mjs';
12
+ import { createLiveActivityTracker, formatCompactAuditEvent, formatRemoteLifecycle } from './remote-live-log.mjs';
12
13
 
13
14
  const REMOTE_COMMANDS=new Set([
14
15
  'menu','start','resume','park','stop','restart','status','url','test','fulltest','toggle','clean','machinetest',
15
16
  'armprocess','disarmprocess','processstatus','armhost','disarmhost','hoststatus','hosttest',
16
17
  'armcoding','disarmcoding','codingstatus','codingtest','armautonomous','disarmautonomous','autonomousstatus','autonomoustest'
17
18
  ]);
18
- const SESSION_START=['start','armprocess','armcoding','armautonomous','armhost'];
19
+ const SESSION_START=['start','armprocess','armcoding','armautonomous'];
19
20
  const SESSION_STATUS=[
20
21
  ['processstatus',/^Process plane\s*:\s*ARMED\b/m],
21
22
  ['codingstatus',/^Coding plane\s*:\s*ARMED\b/m],
22
23
  ['autonomousstatus',/^Autonomous\s*:\s*ARMED\b/m],
23
- ['hoststatus',/^Host plane\s*:\s*ARMED\b/m]
24
+ ['hoststatus',/^Host plane\s*:\s*DISARMED\b/m]
24
25
  ];
25
26
  const SESSION_CLEANUP=['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park'];
26
27
  const SUPERVISOR_COMMANDS=Object.freeze({
@@ -77,16 +78,12 @@ async function listLogFiles(root){
77
78
  }
78
79
  return files;
79
80
  }
80
- function formatLogLine(file,line,{verbose=false}={}){
81
+ function formatLogLine(file,line,{verbose=false,activityTracker=null}={}){
81
82
  if(!line) return null;
82
83
  if(/^segment-\d{8}\.jsonl$/.test(path.basename(file))){
83
84
  try{
84
85
  const event=JSON.parse(line);
85
- if(!verbose){
86
- if(event.event_type!=='tool.result') return null;
87
- const tool=typeof event.tool==='string'&&event.tool?event.tool:'tool';
88
- return `${event.outcome?.is_error===true?'[ERR]':'[OK]'} ${tool}`;
89
- }
86
+ if(!verbose) return activityTracker?activityTracker.observe(event):formatCompactAuditEvent(event);
90
87
  const seq=Number.isInteger(event.seq)?`#${event.seq}`:'#?';
91
88
  const request=typeof event.request_id==='string'?` ${event.request_id.slice(0,8)}`:'';
92
89
  const tool=typeof event.tool==='string'?` ${event.tool}`:'';
@@ -147,25 +144,29 @@ async function readAppend(file,offset){
147
144
  try{await handle.read(buffer,0,length,start);}finally{await handle.close();}
148
145
  return {offset:info.size,text:buffer.toString('utf8')};
149
146
  }
150
- async function tailRemoteLogs(root,signal,{verbose=false,journal=null}={}){
147
+ async function snapshotRemoteLogOffsets(root){
151
148
  const offsets=new Map();
152
149
  for(const file of await listLogFiles(root)){
153
150
  try{offsets.set(file,(await stat(file)).size);}catch{}
154
151
  }
152
+ return offsets;
153
+ }
154
+ async function tailRemoteLogs(root,signal,{verbose=false,journal=null,offsets=null,activityTracker=null}={}){
155
155
  process.stdout.write(verbose
156
156
  ?'📜 [LOG] Live logs active. Press Ctrl+C to disconnect and revoke authority.\n'
157
- :'[LOG] Live tool results. Ctrl+C disconnects and revokes authority.\n');
157
+ :'[LOG] Live activity. Ctrl+C disconnects and revokes authority.\n');
158
+ const activeOffsets=offsets??await snapshotRemoteLogOffsets(root);
158
159
  while(!signal.aborted){
159
160
  for(const file of await listLogFiles(root)){
160
- const prior=offsets.has(file)?offsets.get(file):0;
161
+ const prior=activeOffsets.has(file)?activeOffsets.get(file):0;
161
162
  const next=await readAppend(file,prior);
162
- offsets.set(file,next.offset);
163
+ activeOffsets.set(file,next.offset);
163
164
  for(const line of next.text.split(/\r?\n/)){
164
165
  const terminal=auditTerminalResult(file,line);
165
166
  let recorded=null;
166
167
  if(terminal&&journal) recorded=await journal.recordTerminal(terminal);
167
168
  if(recorded?.duplicate&&!verbose) continue;
168
- const formatted=formatLogLine(file,line,{verbose});
169
+ const formatted=formatLogLine(file,line,{verbose,activityTracker});
169
170
  if(!formatted) continue;
170
171
  if(!verbose&&recorded) process.stdout.write(`${formatted} [cursor ${recorded.cursor}]\n`);
171
172
  else process.stdout.write(`${formatted}\n`);
@@ -266,39 +267,61 @@ async function runRemoteSession({verbose=false,resumeCursor=null}={}){
266
267
  const resultJournal=await openRemoteResultJournal({
267
268
  filePath:remoteResultJournalPath(ctx.root,marker.result_session_id),sessionId:marker.result_session_id,maxEntries:2048
268
269
  });
270
+ const activityTracker=createLiveActivityTracker();
269
271
  const aborter=new AbortController();
270
272
  const abort=()=>aborter.abort();
271
273
  const watchStdin=!process.stdin.isTTY;
272
274
  process.once('SIGINT',abort);process.once('SIGTERM',abort);
273
275
  if(watchStdin){process.stdin.once('end',abort);process.stdin.once('close',abort);process.stdin.resume();}
274
276
  let ready=false;
277
+ let logTask=null;
275
278
  try{
276
- if(verbose){
277
- process.stdout.write('DEADBYTE MCP DEVICE SESSION\n');
278
- process.stdout.write('[INFO] Starting local + remote runtime...\n');
279
- for(const command of SESSION_START) invokeController(ctx,command);
280
- process.stdout.write('🛡️ [AUTHORITY] Verifying runtime planes...\n');
281
- }else{
282
- process.stdout.write('DEADBYTE MCP\n');
283
- const started=[];
284
- for(const command of SESSION_START) started.push(invokeController(ctx,command,{capture:true,echoCaptured:false}));
279
+ if(verbose) process.stdout.write('DEADBYTE MCP DEVICE SESSION\n');
280
+ else process.stdout.write('DEADBYTE MCP\n');
281
+ process.stdout.write(`${formatRemoteLifecycle('device_start')}\n`);
282
+ process.stdout.write(`${formatRemoteLifecycle(resumeCursor!==null?'session_restored':'session_new')}\n`);
283
+ const logOffsets=await snapshotRemoteLogOffsets(ctx.root);
284
+ logTask=tailRemoteLogs(ctx.root,aborter.signal,{verbose,journal:resultJournal,offsets:logOffsets,activityTracker});
285
+ if(verbose) process.stdout.write('[INFO] Starting local + remote runtime...\n');
286
+ else process.stdout.write('[BOOT] Starting local + remote runtime...\n');
287
+ const started=[];
288
+ for(const command of SESSION_START){
289
+ if(!verbose){
290
+ if(command==='start') process.stdout.write('[BOOT] Starting bridge/runtime...\n');
291
+ else process.stdout.write(`🔐 [AUTH] Arming ${command.slice(3)}...\n`);
292
+ }
293
+ const controllerResult=invokeController(ctx,command,verbose?{}:{capture:true,echoCaptured:false});
294
+ started.push(controllerResult);
295
+ if(command==='start'){
296
+ process.stdout.write(`${formatRemoteLifecycle('bridge_connected')}\n`);
297
+ process.stdout.write(`${formatRemoteLifecycle('cloud_connected')}\n`);
298
+ }
299
+ }
300
+ if(!verbose){
285
301
  const startText=started[0]?.stdout||'';
286
302
  const url=startText.match(/^URL\s*:\s*(\S+)/m)?.[1]||'';
287
303
  process.stdout.write('[OK] ONLINE\n');
304
+ process.stdout.write(`${formatRemoteLifecycle('ready')}\n`);
288
305
  if(url) process.stdout.write(`URL: ${url}\n`);
289
- }
306
+ process.stdout.write('🔐 [AUTH] Verifying process, coding, autonomous; host must stay DISARMED...\n');
307
+ }else process.stdout.write('🛡️ [AUTHORITY] Verifying runtime planes; host must stay DISARMED...\n');
290
308
  for(const [command,pattern] of SESSION_STATUS){
291
309
  const result=invokeController(ctx,command,{capture:true,echoCaptured:verbose});
292
- if(!pattern.test(result.stdout)) throw new Error(`remote session authority verification failed: ${command} did not report ARMED`);
310
+ if(!pattern.test(result.stdout)) throw new Error(`remote session authority verification failed: ${command} state mismatch`);
293
311
  }
294
312
  ready=true;
295
- if(verbose) process.stdout.write('[DEVICE] DEADBYTE MCP online; all authority planes ARMED.\n');
296
- else process.stdout.write('[OK] Authority ARMED: process, coding, autonomous, host\n');
297
- await tailRemoteLogs(ctx.root,aborter.signal,{verbose,journal:resultJournal});
313
+ if(verbose) process.stdout.write('[DEVICE] DEADBYTE MCP online; process/coding/autonomous ARMED; host DISARMED.\n');
314
+ else process.stdout.write('🔐 [AUTH] ARMED: process, coding, autonomous | host DISARMED\n');
315
+ await logTask;
298
316
  }finally{
317
+ const wasAborted=aborter.signal.aborted;
318
+ aborter.abort();
319
+ if(logTask) await logTask.catch(()=>{});
320
+ if(!verbose){for(const line of activityTracker.reconcileInterrupted('session_end')) process.stdout.write(`${line}\n`);}
299
321
  process.removeListener('SIGINT',abort);process.removeListener('SIGTERM',abort);
300
322
  if(watchStdin){process.stdin.removeListener('end',abort);process.stdin.removeListener('close',abort);process.stdin.pause();}
301
- if(ready||!aborter.signal.aborted) process.stdout.write(verbose?'[INFO] Closing remote device session and revoking authority...\n':'[INFO] Disconnecting; revoking authority...\n');
323
+ process.stdout.write(`${formatRemoteLifecycle('cleanup')}\n`);
324
+ if(ready||!wasAborted) process.stdout.write(verbose?'[INFO] Closing remote device session and revoking authority...\n':'[INFO] Disconnecting; revoking authority...\n');
302
325
  await cleanupRemoteSession(ctx,{verbose});
303
326
  await releaseRemoteSession(ctx,marker);
304
327
  }
@@ -60,7 +60,7 @@ const baseTools = ['contained_transform','evidence_verify','file_read','proof_ex
60
60
  const codingTools = [
61
61
  'coding_benchmark_run','coding_command_run','coding_file_read','coding_file_write','coding_files_read',
62
62
  'coding_receipt_verify','coding_search','coding_session_status','coding_stat',
63
- 'coding_symbol_definition','coding_symbol_outline','coding_symbol_references','coding_symbol_replace',
63
+ 'coding_symbol_definition','coding_symbol_diagnostics','coding_symbol_implementations','coding_symbol_outline','coding_symbol_references','coding_symbol_rename_preview','coding_symbol_replace',
64
64
  'coding_task_approve','coding_task_cancel','coding_task_events','coding_task_run',
65
65
  'coding_task_status','coding_task_submit','coding_task_verify','coding_text_replace','coding_tree'
66
66
  ];
@@ -168,9 +168,10 @@ function decodeCursor(cursor) {
168
168
 
169
169
  function encodeCursor(name) { return Buffer.from(name, 'utf8').toString('base64url'); }
170
170
 
171
- async function signReceipt(policy, signingKeyPath, grant, operation, requestSha256, body) {
171
+ async function signReceipt(policy, signingKeyPath, grant, operation, requestSha256, body, requestedReceiptId = null) {
172
172
  await fsMkdir(path.join(policy.evidence_dir, 'machine-fs'), { recursive: true });
173
- const receiptId = randomBytes(12).toString('hex');
173
+ const receiptId = requestedReceiptId ?? randomBytes(12).toString('hex');
174
+ if (!RECEIPT_ID_RE.test(receiptId)) throw new Error('machine fs receipt id must be 24 lowercase hex characters');
174
175
  const core = {
175
176
  schema: MACHINE_FS_RECEIPT_SCHEMA, receipt_id: receiptId,
176
177
  policy_sha256: policy.policy_sha256, grant_instance_nonce: grant.instance_nonce,
@@ -311,7 +312,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
311
312
  };
312
313
  }
313
314
 
314
- async function writePath({ rootId, relativePath, content, encoding = 'utf8', expectedSha256 }) {
315
+ async function writePath({ rootId, relativePath, content, encoding = 'utf8', expectedSha256, receiptId = null }) {
315
316
  const grant = await assertCodingArmed(policy, rootId);
316
317
  const target = await resolveTarget(policy, grant, rootId, relativePath, 'write');
317
318
  const bytes = decodeContent(content, encoding);
@@ -325,7 +326,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
325
326
  const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_write', request, {
326
327
  root_id: rootId, path: target.relative, started_at_utc: started, completed_at_utc: nowUtc(),
327
328
  before_sha256: before.sha256, after_sha256: after.sha256, bytes: after.bytes
328
- });
329
+ }, receiptId);
329
330
  return {
330
331
  status: 'committed', root_id: rootId, path: target.relative,
331
332
  previous_sha256: before.sha256, sha256: after.sha256, bytes: after.bytes,
@@ -368,7 +369,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
368
369
  receipt_id: signed.receipt.receipt_id, receipt_sha256: signed.receipt.receipt_sha256, request_sha256: request
369
370
  };
370
371
  }
371
- async function mkdirPath({ rootId, relativePath }) {
372
+ async function mkdirPath({ rootId, relativePath, receiptId = null }) {
372
373
  const grant = await assertCodingArmed(policy, rootId);
373
374
  const target = await resolveTarget(policy, grant, rootId, relativePath, 'write');
374
375
  try { await lstat(target.lexical); throw new Error('machine fs mkdir precondition mismatch: expected absent'); }
@@ -382,7 +383,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
382
383
  const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_mkdir', request, {
383
384
  root_id: rootId, path: target.relative, started_at_utc: started, completed_at_utc: nowUtc(),
384
385
  before_identity_sha256: null, after_identity_sha256: identity.identity_sha256
385
- });
386
+ }, receiptId);
386
387
  return {
387
388
  status: 'committed', root_id: rootId, path: target.relative, identity_sha256: identity.identity_sha256,
388
389
  receipt_id: signed.receipt.receipt_id, receipt_sha256: signed.receipt.receipt_sha256, request_sha256: request
@@ -392,7 +393,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
392
393
  throw error;
393
394
  }
394
395
  }
395
- async function movePath({ rootId, sourcePath, destinationPath, expectedSourceIdentity }) {
396
+ async function movePath({ rootId, sourcePath, destinationPath, expectedSourceIdentity, receiptId = null }) {
396
397
  if (!SHA256_RE.test(expectedSourceIdentity ?? '')) throw new Error('machine fs expected_source_identity must be lowercase SHA-256');
397
398
  const grant = await assertCodingArmed(policy, rootId);
398
399
  const source = await resolveExisting(policy, grant, rootId, sourcePath, 'write', false);
@@ -415,7 +416,7 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
415
416
  const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_move', request, {
416
417
  root_id: rootId, source_path: source.relative, destination_path: destination.relative,
417
418
  started_at_utc: started, completed_at_utc: nowUtc(), source_identity_sha256: expectedSourceIdentity
418
- });
419
+ }, receiptId);
419
420
  return {
420
421
  status: 'committed', root_id: rootId, source_path: source.relative, destination_path: destination.relative,
421
422
  identity_sha256: expectedSourceIdentity, receipt_id: signed.receipt.receipt_id,
@@ -460,6 +461,46 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
460
461
  }
461
462
  }
462
463
 
464
+ async function statePath({ rootId, relativePath }) {
465
+ try {
466
+ const value = await statPath({ rootId, relativePath, hash: true });
467
+ return { exists: true, root_id: rootId, path: value.path, kind: value.kind, bytes: value.bytes,
468
+ sha256: value.sha256, identity_sha256: value.identity_sha256 };
469
+ } catch (error) {
470
+ if (error?.code === 'ENOENT') return { exists: false, root_id: rootId, path: relativePath, kind: null, bytes: 0, sha256: null, identity_sha256: null };
471
+ throw error;
472
+ }
473
+ }
474
+
475
+ async function removeEmptyDir({ rootId, relativePath, expectedSourceIdentity, receiptId = null }) {
476
+ if (!SHA256_RE.test(expectedSourceIdentity ?? '')) throw new Error('machine fs expected_source_identity must be lowercase SHA-256');
477
+ const grant = await assertCodingArmed(policy, rootId);
478
+ const source = await resolveExisting(policy, grant, rootId, relativePath, 'write', false);
479
+ const before = await objectIdentity(source.resolved);
480
+ if (before.kind !== 'directory' || before.entries.length !== 0) throw new Error('machine fs rmdir requires an empty directory');
481
+ if (before.identity_sha256 !== expectedSourceIdentity) throw new Error(`machine fs source identity mismatch: expected ${expectedSourceIdentity}, found ${before.identity_sha256}`);
482
+ const request = requestSha('machine_fs_rmdir_empty', { root_id: rootId, path: source.relative, expected_source_identity: expectedSourceIdentity });
483
+ const started = nowUtc();
484
+ const race = await objectIdentity(source.resolved);
485
+ if (race.kind !== 'directory' || race.entries.length !== 0 || race.identity_sha256 !== expectedSourceIdentity) {
486
+ throw new Error('machine fs rmdir precondition changed before commit');
487
+ }
488
+ await rmdir(source.lexical);
489
+ try {
490
+ try { await lstat(source.lexical); throw new Error('machine fs rmdir post-commit path still exists'); }
491
+ catch (error) { if (error?.code !== 'ENOENT') throw error; }
492
+ const signed = await signReceipt(policy, signingKeyPath, grant, 'machine_fs_rmdir_empty', request, {
493
+ root_id: rootId, path: source.relative, started_at_utc: started, completed_at_utc: nowUtc(),
494
+ before_identity_sha256: expectedSourceIdentity, after_identity_sha256: null
495
+ }, receiptId);
496
+ return { status: 'committed', root_id: rootId, path: source.relative, identity_sha256: expectedSourceIdentity,
497
+ receipt_id: signed.receipt.receipt_id, receipt_sha256: signed.receipt.receipt_sha256, request_sha256: request };
498
+ } catch (error) {
499
+ await fsMkdir(source.lexical, { recursive: false }).catch(() => {});
500
+ throw error;
501
+ }
502
+ }
503
+
463
504
  return Object.freeze({
464
505
  policy,
465
506
  stat: statPath,
@@ -470,6 +511,8 @@ export function createMachineFsRuntime({ policy, signingKeyPath, verifyKeyPath }
470
511
  move: movePath,
471
512
  mkdir: mkdirPath,
472
513
  delete: deletePath,
514
+ state: statePath,
515
+ removeEmptyDir,
473
516
  verifyReceipt: receiptId => verifyMachineFsReceiptFile({ policy, verifyKeyPath, receiptId })
474
517
  });
475
518
  }
@@ -39,6 +39,8 @@ import { registerAutonomousTools } from './autonomous-mcp-tools.mjs';
39
39
  import { createToolAudit, installToolAudit } from './tool-audit.mjs';
40
40
  import { createAuditContextProvider } from './audit-context.mjs';
41
41
  import { registerOperatorSurface } from './operator-surface.mjs';
42
+ import { capabilityProfileFromEnv, COMPACT_SURFACE_TOOL_LIMIT, R36_CAPABILITY_LEDGER } from './capability-ledger.mjs';
43
+ import { registerCompactGatewayTools } from './compact-gateway-mcp-tools.mjs';
42
44
  import {
43
45
  containedTransformOutputSchema,
44
46
  evidenceVerifyOutputSchema,
@@ -58,6 +60,7 @@ const verifyKeyPath = process.env.DEADBYTE_VERIFY_KEY ?? defaultPublicKeyPath();
58
60
  const auditRuntimeMode = process.env.DEADBYTE_AUDIT_RUNTIME ?? '0';
59
61
  if (!['0','1'].includes(auditRuntimeMode)) throw new Error('DEADBYTE_AUDIT_RUNTIME must be 0 or 1');
60
62
  const runtimeStateRoot = path.resolve(process.env.DEADBYTE_STATE_ROOT || path.join(os.homedir(),'.deadbyte-mcp'));
63
+ const surfaceProfile = capabilityProfileFromEnv(process.env);
61
64
  const localPrivilegedPolicyPath = path.join(packageRoot, 'controller', 'deadbyte-host-policy.json');
62
65
  let privilegedPolicyPath = process.env.DEADBYTE_PRIVILEGED_POLICY ?? '';
63
66
  if (!privilegedPolicyPath) {
@@ -106,7 +109,7 @@ const semanticLspBinding = semanticConfigBindingFromEnv(process.env);
106
109
  const semanticLsp = codingRuntime && semanticLspBinding
107
110
  ? await loadSemanticLspBackends({ ...semanticLspBinding, codingRuntime })
108
111
  : { backends: [], required_ids: [] };
109
- const semanticRuntime = codingRuntime ? createSemanticCodeRuntime({ codingRuntime, backends: semanticLsp.backends }) : null;
112
+ let semanticRuntime = null;
110
113
  const machineFsRuntimeMode = process.env.DEADBYTE_MACHINE_FS_RUNTIME ?? '0';
111
114
  if (!['0','1'].includes(machineFsRuntimeMode)) throw new Error('DEADBYTE_MACHINE_FS_RUNTIME must be 0 or 1');
112
115
  if (machineFsRuntimeMode === '1' && !codingPolicy) throw new Error('DEADBYTE_MACHINE_FS_RUNTIME=1 requires DEADBYTE_CODING_RUNTIME=1');
@@ -137,9 +140,10 @@ if (autonomousRuntimeMode === '1' && !autonomousPolicyPath) {
137
140
  }
138
141
  if (autonomousRuntimeMode === '1' && !autonomousPolicyPath) throw new Error('DEADBYTE_AUTONOMOUS_RUNTIME=1 requires an autonomous policy');
139
142
  const autonomousPolicy = autonomousRuntimeMode === '1' ? await loadAutonomousPolicy(autonomousPolicyPath,codingPolicy) : null;
140
- const nativeDiffRuntime = autonomousPolicy ? createNativeDiffRuntime({ policy:autonomousPolicy,codingRuntime,signingKeyPath,verifyKeyPath }) : null;
143
+ const nativeDiffRuntime = autonomousPolicy ? createNativeDiffRuntime({ policy:autonomousPolicy,codingRuntime,machineFsRuntime,signingKeyPath,verifyKeyPath }) : null;
144
+ semanticRuntime = codingRuntime ? createSemanticCodeRuntime({ codingRuntime, backends: semanticLsp.backends, nativeDiffRuntime }) : null;
141
145
  const autonomousRuntime = autonomousPolicy ? createAutonomousRuntime({ policy:autonomousPolicy,codingRuntime,nativeDiffRuntime,
142
- machineFsRuntime,observationRuntime,processRuntime,signingKeyPath,verifyKeyPath }) : null;
146
+ machineFsRuntime,observationRuntime,processRuntime,semanticRuntime,signingKeyPath,verifyKeyPath }) : null;
143
147
  const autonomousSupervisor = autonomousRuntime && autonomousPolicy.planner.backend === 'openai_compatible' &&
144
148
  autonomousSupervisorMode === 'in_process'
145
149
  ? startAutonomousSupervisor({ runtime: autonomousRuntime, policy: autonomousPolicy })
@@ -169,11 +173,22 @@ function textResult(schema, object, isError = false) {
169
173
  return structuredToolResult(schema, object, isError);
170
174
  }
171
175
 
176
+ const COMPACT_CODING_DIRECT_TOOLS=new Set([
177
+ 'coding_session_status','coding_tree','coding_symbol_replace','coding_file_read','coding_file_write',
178
+ 'coding_text_replace','coding_command_run','coding_benchmark_run','coding_receipt_verify',
179
+ 'coding_task_submit','coding_task_run','coding_task_status','coding_task_events','coding_task_cancel',
180
+ 'coding_task_approve','coding_task_verify'
181
+ ]);
182
+ function filteredToolServer(server,allowed){
183
+ return {registerTool(name,...args){if(allowed.has(name)) return server.registerTool(name,...args);}};
184
+ }
185
+
172
186
  serveStdio(() => {
173
187
  const server = new McpServer({ name: 'deadbyte-mcp', version: DEADBYTE_VERSION });
174
- registerOperatorSurface(server,{packageRoot});
188
+ registerOperatorSurface(server,{packageRoot,surfaceProfile,compactToolLimit:COMPACT_SURFACE_TOOL_LIMIT});
175
189
  if (toolAudit) installToolAudit(server,toolAudit);
176
190
 
191
+ if (surfaceProfile === 'full') {
177
192
  server.registerTool(
178
193
  'workspace_open',
179
194
  {
@@ -289,6 +304,8 @@ serveStdio(() => {
289
304
  }
290
305
  );
291
306
 
307
+ }
308
+
292
309
  server.registerTool(
293
310
  'evidence_verify',
294
311
  {
@@ -319,23 +336,24 @@ serveStdio(() => {
319
336
  });
320
337
  }
321
338
 
322
- if (agentRuntime) {
339
+ if (agentRuntime && surfaceProfile === 'full') {
323
340
  registerAgentTools(server, { runtime: agentRuntime, workspacePathFromId });
324
341
  }
325
342
 
326
- if (processRuntime) {
343
+ if (processRuntime && surfaceProfile === 'full') {
327
344
  registerProcessTools(server, { runtime: processRuntime });
328
345
  }
329
346
 
330
347
  if (codingRuntime && codingTaskRuntime && semanticRuntime) {
331
- registerCodingTools(server, { codingRuntime, taskRuntime: codingTaskRuntime, semanticRuntime });
348
+ const codingServer=surfaceProfile==='full'?server:filteredToolServer(server,COMPACT_CODING_DIRECT_TOOLS);
349
+ registerCodingTools(codingServer, { codingRuntime, taskRuntime: codingTaskRuntime, semanticRuntime });
332
350
  }
333
351
 
334
- if (machineFsRuntime) {
352
+ if (machineFsRuntime && surfaceProfile === 'full') {
335
353
  registerMachineFsTools(server, { runtime: machineFsRuntime });
336
354
  }
337
355
 
338
- if (observationRuntime) {
356
+ if (observationRuntime && surfaceProfile === 'full') {
339
357
  registerObservationTools(server, { runtime: observationRuntime });
340
358
  }
341
359
 
@@ -343,6 +361,11 @@ serveStdio(() => {
343
361
  registerAutonomousTools(server, { autonomousRuntime, nativeDiffRuntime });
344
362
  }
345
363
 
364
+ registerCompactGatewayTools(server,{
365
+ profile:surfaceProfile,ledger:R36_CAPABILITY_LEDGER,codingRuntime,semanticRuntime,machineFsRuntime,
366
+ processRuntime,observationRuntime,machineRuntime
367
+ });
368
+
346
369
  if (hostPolicy) {
347
370
  server.registerTool(
348
371
  'host_file_read',