deadbyte-mcp 0.9.0 → 0.11.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 (136) hide show
  1. package/MANIFEST.SHA256 +134 -92
  2. package/README.txt +19 -15
  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-r36.mjs +113 -0
  43. package/scripts/final-closure-verify-r36.mjs +208 -0
  44. package/scripts/final-closure-verify.mjs +88 -39
  45. package/scripts/final-closure.mjs +63 -56
  46. package/scripts/gate-windows-r36.ps1 +42 -0
  47. package/scripts/gate-windows.ps1 +3 -3
  48. package/scripts/release-parity-r36.mjs +200 -0
  49. package/scripts/release-parity-tests.ps1 +9 -0
  50. package/scripts/release-parity.mjs +149 -139
  51. package/scripts/windows-gate-evidence-r36.mjs +52 -0
  52. package/scripts/windows-gate-evidence.mjs +5 -5
  53. package/src/agent-memory-plane.mjs +98 -0
  54. package/src/autonomous-context-engine.mjs +2 -1
  55. package/src/autonomous-mcp-tools.mjs +5 -1
  56. package/src/autonomous-output-contracts.mjs +9 -6
  57. package/src/autonomous-planner-contracts.mjs +36 -1
  58. package/src/autonomous-planner.mjs +25 -3
  59. package/src/autonomous-runtime.mjs +337 -43
  60. package/src/autonomous-timeout-recovery.mjs +27 -0
  61. package/src/capability-benchmark-runner.mjs +86 -1
  62. package/src/capability-benchmark.mjs +45 -0
  63. package/src/capability-ledger.mjs +158 -0
  64. package/src/coding-mcp-tools.mjs +31 -17
  65. package/src/coding-output-contracts.mjs +48 -10
  66. package/src/coding-plane.mjs +45 -9
  67. package/src/coding-search.mjs +130 -47
  68. package/src/compact-gateway-mcp-tools.mjs +128 -0
  69. package/src/compact-gateway-output-contracts.mjs +16 -0
  70. package/src/deadbyte-cli.mjs +62 -78
  71. package/src/effect-ledger.mjs +47 -0
  72. package/src/machine-fs-smoke-client.mjs +1 -1
  73. package/src/machine-fs.mjs +51 -8
  74. package/src/mcp-server.mjs +32 -9
  75. package/src/native-diff-v2.mjs +337 -0
  76. package/src/native-diff.mjs +50 -2
  77. package/src/observation-lease.mjs +32 -0
  78. package/src/observation-smoke-client.mjs +1 -1
  79. package/src/operator-surface.mjs +7 -1
  80. package/src/process-runtime.mjs +98 -11
  81. package/src/process-smoke-client.mjs +11 -3
  82. package/src/r36-compact-disarmed-probe.mjs +50 -0
  83. package/src/r36-full-surface-probe.mjs +56 -0
  84. package/src/remote-live-log.mjs +135 -0
  85. package/src/remote-mcp-autonomous-smoke-client.mjs +22 -12
  86. package/src/remote-mcp-coding-smoke-client.mjs +1 -1
  87. package/src/remote-mcp-r36-parity-client.mjs +175 -0
  88. package/src/remote-mcp-smoke-client.mjs +112 -56
  89. package/src/runtime-update.mjs +51 -1
  90. package/src/search-cursor.mjs +45 -0
  91. package/src/semantic-code.mjs +72 -5
  92. package/src/semantic-lsp-backend.mjs +39 -3
  93. package/src/version.mjs +1 -1
  94. package/src/worker-scheduler.mjs +53 -0
  95. package/test/autonomous-capability-r36.test.mjs +151 -0
  96. package/test/autonomous-output-contract.test.mjs +1 -1
  97. package/test/autonomous-runtime.test.mjs +2 -2
  98. package/test/capability-benchmark-r36.test.mjs +107 -0
  99. package/test/capability-benchmark-semantic-r36.test.mjs +52 -0
  100. package/test/capability-claims-r36.test.mjs +23 -0
  101. package/test/capability-ledger-r36.test.mjs +102 -0
  102. package/test/coding-catalog-consistency.test.mjs +2 -2
  103. package/test/coding-plane.test.mjs +2 -2
  104. package/test/coding-runtime.test.mjs +16 -0
  105. package/test/coding-search-r36.test.mjs +90 -0
  106. package/test/compact-catalog-r36.test.mjs +37 -0
  107. package/test/compact-gateway-r36.test.mjs +66 -0
  108. package/test/contained.test.mjs +1 -1
  109. package/test/core.test.mjs +1 -1
  110. package/test/deferred-slot-operation.test.mjs +9 -0
  111. package/test/fixtures/lsp-framed-server.mjs +2 -0
  112. package/test/helpers/autonomous-r34-fixture.mjs +5 -3
  113. package/test/multi-file-read.test.mjs +3 -0
  114. package/test/native-diff-topology-r36.test.mjs +105 -0
  115. package/test/package-boundary.test.mjs +6 -0
  116. package/test/process-longrun-r36.test.mjs +82 -0
  117. package/test/process-release-gate.test.mjs +9 -0
  118. package/test/production-docs.test.mjs +5 -5
  119. package/test/prompts-resources.test.mjs +7 -1
  120. package/test/r33-closeout-regression.test.mjs +4 -3
  121. package/test/r33-finalization.test.mjs +14 -9
  122. package/test/r36-finalization.test.mjs +104 -0
  123. package/test/r36-release-identity.test.mjs +45 -0
  124. package/test/r37-agent-fabric.test.mjs +92 -0
  125. package/test/r37-autonomous-timeout-recovery.test.mjs +60 -0
  126. package/test/r37-finalization.test.mjs +74 -0
  127. package/test/release-version.test.mjs +42 -33
  128. package/test/remote-live-log-r36.test.mjs +37 -0
  129. package/test/remote-live-log-r37.test.mjs +47 -0
  130. package/test/remote-live-log-recovery-r36.test.mjs +41 -0
  131. package/test/remote-r24-catalog.test.mjs +13 -0
  132. package/test/remote-session-cli.test.mjs +53 -66
  133. package/test/runtime-self-update.test.mjs +58 -1
  134. package/test/semantic-lsp-backend.test.mjs +9 -0
  135. package/test/semantic-r36-rename.test.mjs +82 -0
  136. package/deadbyte-mcp-0.8.9.tgz +0 -0
@@ -0,0 +1,27 @@
1
+ const HEX64=/^[0-9a-f]{64}$/;
2
+
3
+ export function classifyAutonomousTimeoutRecovery(status,{beforeJournalHead}={}){
4
+ if(!status||typeof status!=='object'||Array.isArray(status)) throw new Error('autonomous timeout status invalid');
5
+ if(!HEX64.test(beforeJournalHead??'')) throw new Error('autonomous timeout before journal head invalid');
6
+ if(status.status!=='ok') throw new Error('autonomous timeout status not ok');
7
+ if(!HEX64.test(status.journal_head_sha256??'')) throw new Error('autonomous timeout journal head invalid');
8
+ if(status.state==='succeeded') return Object.freeze({kind:'completed',state:'succeeded',journal_head_sha256:status.journal_head_sha256});
9
+ if(status.state==='cancelled'||status.state==='paused'){
10
+ return Object.freeze({kind:'terminal_failure',state:status.state,reason:status.reason??null,journal_head_sha256:status.journal_head_sha256});
11
+ }
12
+ if(status.state!=='pending'&&status.state!=='running') throw new Error(`autonomous timeout unexpected state: ${status.state}`);
13
+ if(status.run_busy===true){
14
+ return Object.freeze({kind:'wait',state:status.state,reason:'server_run_in_flight',journal_head_sha256:status.journal_head_sha256});
15
+ }
16
+ if(status.run_busy!==false) throw new Error('autonomous timeout run-lock state unavailable');
17
+ if(status.pending_request!==null&&status.pending_request!==undefined){
18
+ return Object.freeze({kind:'wait',state:status.state,reason:'planner_request_in_flight',journal_head_sha256:status.journal_head_sha256});
19
+ }
20
+ if(status.pending_decision!==null&&status.pending_decision!==undefined){
21
+ return Object.freeze({kind:'wait',state:status.state,reason:'decision_in_flight',journal_head_sha256:status.journal_head_sha256});
22
+ }
23
+ if(status.journal_head_sha256===beforeJournalHead){
24
+ return Object.freeze({kind:'wait',state:status.state,reason:'no_durable_progress',journal_head_sha256:status.journal_head_sha256});
25
+ }
26
+ return Object.freeze({kind:'resumable',state:status.state,reason:'durable_cycle_completed',journal_head_sha256:status.journal_head_sha256});
27
+ }
@@ -4,7 +4,7 @@ import { readdir, readFile, stat } from 'node:fs/promises';
4
4
  import path from 'node:path';
5
5
  import { fileURLToPath } from 'node:url';
6
6
  import { canonicalJson } from './canonical-json.mjs';
7
- import { buildCapabilityBenchmark } from './capability-benchmark.mjs';
7
+ import { buildCapabilityBenchmark, buildR36CapabilityBenchmark } from './capability-benchmark.mjs';
8
8
 
9
9
  const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
10
10
  const TEST_TIMEOUT_MS=180_000;
@@ -106,3 +106,88 @@ export async function runCapabilityBenchmark({rootUrl,definitions=benchmarkCaseD
106
106
  }
107
107
  return buildCapabilityBenchmark({suite_id:'r35-offline-v1',cases});
108
108
  }
109
+
110
+ export const R36_BENCHMARK_CASE_IDS=Object.freeze([
111
+ 'repository_tree_exploration','literal_content_search','regex_content_search','filename_path_search',
112
+ 'deterministic_search_paging_cancel','bounded_multi_file_read','rich_stat_reparse_handling','stale_edit_race_rejection',
113
+ 'transactional_multi_file_native_diff','topology_mkdir_move_delete_rollback','semantic_typescript_navigation',
114
+ 'semantic_python_navigation','semantic_rust_navigation','semantic_cpp_navigation','diagnostics_normalization',
115
+ 'implementation_lookup','cross_file_rename_transaction','long_process_lifecycle','policy_defined_process_action',
116
+ 'process_crash_reconciliation','autonomous_failing_test_repair','autonomous_search_semantic_patch_test',
117
+ 'release_gate_finish_without_evidence_refusal','provider_bridge_interruption_recovery','remote_result_replay_deduplication',
118
+ 'compact_connector_capability_closure','live_log_request_before_result','live_log_redaction',
119
+ 'forged_stale_receipt_rejection','rollback_r35_restore_r36'
120
+ ]);
121
+
122
+ const r36Def=(case_id,purpose,test_files,fixture_files,{test_name_pattern=null,pass_witness=null,round_trips=2,stale_rejected=false,recovery_success=true,release_gate_result='not_applicable'}={})=>Object.freeze({
123
+ case_id,purpose,test_files:Object.freeze([...test_files]),fixture_files:Object.freeze([...fixture_files]),
124
+ ...(test_name_pattern?{test_name_pattern}:{}),...(pass_witness?{pass_witness}:{}),round_trips,stale_rejected,recovery_success,
125
+ capability_reachable:true,evidence_verified:true,release_gate_result
126
+ });
127
+
128
+ const R36_DEFINITIONS=Object.freeze([
129
+ r36Def('repository_tree_exploration','repository tree exploration',['test/coding-plane.test.mjs'],['test/coding-plane.test.mjs'],{round_trips:1}),
130
+ r36Def('literal_content_search','literal content search',['test/coding-search-r36.test.mjs'],['test/coding-search-r36.test.mjs'],{test_name_pattern:'R36 regex search returns multiple matches',pass_witness:'R36 regex search returns multiple matches',round_trips:2}),
131
+ r36Def('regex_content_search','regex content search',['test/coding-search-r36.test.mjs'],['test/coding-search-r36.test.mjs'],{test_name_pattern:'R36 regex search returns multiple matches',pass_witness:'R36 regex search returns multiple matches',round_trips:2}),
132
+ r36Def('filename_path_search','filename/path search',['test/coding-search-r36.test.mjs'],['test/coding-search-r36.test.mjs'],{test_name_pattern:'R36 path search does not decode',pass_witness:'R36 path search does not decode',round_trips:2}),
133
+ r36Def('deterministic_search_paging_cancel','deterministic paging/cancel',['test/coding-search-r36.test.mjs','test/observation-runtime.test.mjs'],['test/coding-search-r36.test.mjs','test/observation-runtime.test.mjs'],{round_trips:4}),
134
+ r36Def('bounded_multi_file_read','bounded multi-file read',['test/multi-file-read.test.mjs'],['test/multi-file-read.test.mjs'],{round_trips:1}),
135
+ r36Def('rich_stat_reparse_handling','rich stat and reparse denial',['test/coding-runtime.test.mjs','test/native-diff-topology-r36.test.mjs'],['test/coding-runtime.test.mjs','test/native-diff-topology-r36.test.mjs'],{test_name_pattern:'(?:R36 coding stat exposes|R36 Native Diff V2 denies topology through reparse)',round_trips:3,stale_rejected:true}),
136
+ r36Def('stale_edit_race_rejection','stale-edit race rejection',['test/coding-runtime.test.mjs','test/native-diff-topology-r36.test.mjs'],['test/coding-runtime.test.mjs','test/native-diff-topology-r36.test.mjs'],{test_name_pattern:'(?:rejects mutation when lease is absent or precondition is stale|rejects stale move identity)',round_trips:3,stale_rejected:true}),
137
+ r36Def('transactional_multi_file_native_diff','transactional multi-file Native Diff',['test/native-diff.test.mjs'],['test/native-diff.test.mjs'],{test_name_pattern:'native diff commits exact preconditioned edits',pass_witness:'native diff commits exact preconditioned edits',round_trips:4,stale_rejected:true}),
138
+ r36Def('topology_mkdir_move_delete_rollback','topology transaction and rollback',['test/native-diff-topology-r36.test.mjs'],['test/native-diff-topology-r36.test.mjs'],{round_trips:5,stale_rejected:true}),
139
+ r36Def('semantic_typescript_navigation','TypeScript symbol navigation',['test/semantic-code.test.mjs'],['test/semantic-code.test.mjs','test/fixtures/semantic/typescript'],{round_trips:4,stale_rejected:true}),
140
+ r36Def('semantic_python_navigation','Python symbol navigation through hermetic LSP adapter',['test/capability-benchmark-semantic-r36.test.mjs'],['test/capability-benchmark-semantic-r36.test.mjs','test/fixtures/lsp-framed-server.mjs'],{test_name_pattern:'R36 benchmark Python symbol navigation',pass_witness:'R36 benchmark Python symbol navigation',round_trips:4}),
141
+ r36Def('semantic_rust_navigation','Rust symbol navigation through hermetic LSP adapter',['test/capability-benchmark-semantic-r36.test.mjs'],['test/capability-benchmark-semantic-r36.test.mjs','test/fixtures/lsp-framed-server.mjs'],{test_name_pattern:'R36 benchmark Rust symbol navigation',pass_witness:'R36 benchmark Rust symbol navigation',round_trips:4}),
142
+ r36Def('semantic_cpp_navigation','C/C++ symbol navigation through hermetic LSP adapter',['test/capability-benchmark-semantic-r36.test.mjs'],['test/capability-benchmark-semantic-r36.test.mjs','test/fixtures/lsp-framed-server.mjs'],{test_name_pattern:'R36 benchmark Cpp symbol navigation',pass_witness:'R36 benchmark Cpp symbol navigation',round_trips:4}),
143
+ r36Def('diagnostics_normalization','diagnostics normalization',['test/semantic-r36-rename.test.mjs'],['test/semantic-r36-rename.test.mjs'],{test_name_pattern:'R36 TypeScript diagnostics carry',pass_witness:'R36 TypeScript diagnostics carry',round_trips:2}),
144
+ r36Def('implementation_lookup','implementation lookup',['test/semantic-r36-rename.test.mjs'],['test/semantic-r36-rename.test.mjs'],{test_name_pattern:'R36 TypeScript implementations normalize',pass_witness:'R36 TypeScript implementations normalize',round_trips:2}),
145
+ r36Def('cross_file_rename_transaction','cross-file rename through Native Diff',['test/semantic-r36-rename.test.mjs'],['test/semantic-r36-rename.test.mjs'],{test_name_pattern:'R36 cross-file rename preview',pass_witness:'R36 cross-file rename preview',round_trips:5,stale_rejected:true}),
146
+ r36Def('long_process_lifecycle','long process start/output/status/terminate',['test/process-longrun-r36.test.mjs','test/process-runtime.test.mjs'],['test/process-longrun-r36.test.mjs','test/process-runtime.test.mjs'],{test_name_pattern:'(?:R36 long process returns before exit|R31 runtime lists, reports and terminates)',round_trips:6,recovery_success:true}),
147
+ r36Def('policy_defined_process_action','policy-defined named process action',['test/process-runtime.test.mjs'],['test/process-runtime.test.mjs'],{test_name_pattern:'R32 runtime executes one policy-defined named action',pass_witness:'R32 runtime executes one policy-defined named action',round_trips:3}),
148
+ r36Def('process_crash_reconciliation','terminal process journal/output recovery',['test/process-longrun-r36.test.mjs'],['test/process-longrun-r36.test.mjs'],{test_name_pattern:'R36 terminal process session is recovered',pass_witness:'R36 terminal process session is recovered',round_trips:4,recovery_success:true}),
149
+ r36Def('autonomous_failing_test_repair','autonomous failing-test critic/repair/release',['test/autonomous-r34-e2e.test.mjs','test/autonomous-loop-v2.test.mjs'],['test/autonomous-r34-e2e.test.mjs','test/autonomous-loop-v2.test.mjs','test/helpers/autonomous-r34-fixture.mjs'],{test_name_pattern:'(?:multi-step fail replan repair finish|failed VERIFY enters CRITIC|REPAIR must change)',round_trips:8,stale_rejected:true,release_gate_result:'passed'}),
150
+ r36Def('autonomous_search_semantic_patch_test','capability-aware planner inspection/mutation loop',['test/autonomous-capability-r36.test.mjs','test/semantic-r36-rename.test.mjs','test/autonomous-r34-e2e.test.mjs'],['test/autonomous-capability-r36.test.mjs','test/semantic-r36-rename.test.mjs','test/autonomous-r34-e2e.test.mjs','test/helpers/autonomous-r34-fixture.mjs'],{test_name_pattern:'(?:planner parses first-class capability actions|typed native_diff_apply|cross-file rename preview|multi-step fail replan repair finish)',round_trips:8,stale_rejected:true,release_gate_result:'passed'}),
151
+ r36Def('release_gate_finish_without_evidence_refusal','finish claim cannot bypass objective release evidence',['test/autonomous-r34-e2e.test.mjs'],['test/autonomous-r34-e2e.test.mjs'],{test_name_pattern:'R34 finish is blocked while the active plan is incomplete',pass_witness:'R34 finish is blocked while the active plan is incomplete',round_trips:3,release_gate_result:'blocked'}),
152
+ r36Def('provider_bridge_interruption_recovery','provider circuit and remote-session interruption recovery',['test/provider-circuit.test.mjs','test/remote-session-cli.test.mjs'],['test/provider-circuit.test.mjs','test/remote-session-cli.test.mjs'],{test_name_pattern:'(?:OPEN becomes HALF_OPEN|bare remote recovers a stale crashed session)',round_trips:4,recovery_success:true}),
153
+ r36Def('remote_result_replay_deduplication','remote result replay/dedupe',['test/remote-result-journal.test.mjs','test/remote-session-cli.test.mjs'],['test/remote-result-journal.test.mjs','test/remote-session-cli.test.mjs'],{test_name_pattern:'(?:remote result journal is monotonic|remote --resume replays only terminal results)',round_trips:4,recovery_success:true}),
154
+ r36Def('compact_connector_capability_closure','compact connector <=42 with production capability closure',['test/compact-catalog-r36.test.mjs','test/capability-ledger-r36.test.mjs'],['test/compact-catalog-r36.test.mjs','test/capability-ledger-r36.test.mjs'],{test_name_pattern:'(?:real compact stdio catalog stays <=42|compact closure covers every production non-host capability)',round_trips:2}),
155
+ r36Def('live_log_request_before_result','live activity request-before-result ordering',['test/remote-live-log-recovery-r36.test.mjs'],['test/remote-live-log-recovery-r36.test.mjs','src/remote-live-log.mjs'],{test_name_pattern:'R36 live activity tracker prints RUN before terminal result',pass_witness:'R36 live activity tracker prints RUN before terminal result',round_trips:2,recovery_success:true}),
156
+ r36Def('live_log_redaction','live activity secret/payload redaction',['test/remote-live-log-r36.test.mjs','test/remote-session-cli.test.mjs'],['test/remote-live-log-r36.test.mjs','test/remote-session-cli.test.mjs','src/remote-live-log.mjs'],{test_name_pattern:'compact live activity shows request context without payload or secret values',pass_witness:'compact live activity shows request context without payload or secret values',round_trips:1}),
157
+ r36Def('forged_stale_receipt_rejection','forged/stale receipt and precondition rejection',['test/autonomous-r34-e2e.test.mjs','test/coding-plane-adversarial.test.mjs'],['test/autonomous-r34-e2e.test.mjs','test/coding-plane-adversarial.test.mjs'],{test_name_pattern:'(?:forged profile receipt substitution|signed autonomous journal tamper|coding task adopts a signed command receipt)',round_trips:4,stale_rejected:true,recovery_success:true}),
158
+ r36Def('rollback_r35_restore_r36','hermetic signed predecessor rollback and exact slot restore mechanism',['test/runtime-self-update.test.mjs','test/release-slot.test.mjs'],['test/runtime-self-update.test.mjs','test/release-slot.test.mjs'],{test_name_pattern:'(?:R31 explicit rollback restores the exact signed prior pointer|release slot materialization copies only manifest-bound files)',round_trips:5,recovery_success:true})
159
+ ]);
160
+
161
+ export function r36BenchmarkCaseDefinitions(){
162
+ return R36_DEFINITIONS.map(item=>({...structuredClone(item),fixture_files:['bench/fixtures/corpus.json','bench/fixtures/r36/case-map.json',...item.fixture_files]}));
163
+ }
164
+
165
+ function hasPassingWitness(stdout,witness){
166
+ if(!witness) return true;
167
+ const text=Buffer.isBuffer(stdout)?stdout.toString('utf8'):String(stdout??'');
168
+ return text.split(/\r?\n/).some(line=>line.includes(witness)&&!/\bSKIP\b/i.test(line)&&/(?:✔|\bok\b)/i.test(line));
169
+ }
170
+
171
+ export async function runR36CapabilityBenchmark({rootUrl,definitions=r36BenchmarkCaseDefinitions(),env={},timeoutMs=TEST_TIMEOUT_MS}={}){
172
+ const root=typeof rootUrl==='string'?path.resolve(rootUrl):fileURLToPath(rootUrl??new URL('../',import.meta.url));
173
+ if(!Array.isArray(definitions)||definitions.length<1) throw new Error('R36 benchmark definitions invalid');
174
+ if(!Number.isInteger(timeoutMs)||timeoutMs<1000||timeoutMs>600000) throw new Error('R36 benchmark timeout invalid');
175
+ const cases=[];
176
+ for(const definition of definitions){
177
+ const fixture_sha256=await fixtureIdentityForCase({rootUrl:root,definition});
178
+ let result;
179
+ try{result=await runNodeTest({root,definition,env,timeoutMs});}
180
+ catch(error){result={exit_code:null,timed_out:false,error:String(error),stdout:Buffer.alloc(0),stderr:Buffer.alloc(0),bytes:0,elapsed_ms:0};}
181
+ const witnessOk=hasPassingWitness(result.stdout,definition.pass_witness??null);
182
+ const correct=result.exit_code===0&&!result.timed_out&&!result.error&&witnessOk;
183
+ const evidence={schema:'deadbyte.r36-benchmark-case-evidence.v1',case_id:definition.case_id,exit_code:result.exit_code,
184
+ timed_out:result.timed_out===true,signal:result.signal??null,error:result.error??null,pass_witness:definition.pass_witness??null,
185
+ pass_witness_observed:witnessOk,stdout_sha256:sha256(result.stdout??Buffer.alloc(0)),stderr_sha256:sha256(result.stderr??Buffer.alloc(0))};
186
+ cases.push({case_id:definition.case_id,fixture_sha256,correct,round_trips:definition.round_trips,
187
+ bytes_returned:result.bytes??0,elapsed_ms:result.elapsed_ms??0,stale_rejected:correct&&definition.stale_rejected===true,
188
+ recovery_success:correct&&definition.recovery_success===true,duplicate_side_effects:correct?0:1,
189
+ capability_reachable:correct&&definition.capability_reachable===true,evidence_verified:correct&&definition.evidence_verified===true,
190
+ release_gate_result:correct?definition.release_gate_result:'blocked',evidence_sha256:sha256(Buffer.from(canonicalJson(evidence),'utf8'))});
191
+ }
192
+ return buildR36CapabilityBenchmark({suite_id:'r36-production-coding-v1',cases});
193
+ }
@@ -2,6 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import { canonicalJson } from './canonical-json.mjs';
3
3
 
4
4
  export const CAPABILITY_BENCHMARK_SCHEMA='deadbyte.r35-capability-benchmark.v1';
5
+ export const R36_CAPABILITY_BENCHMARK_SCHEMA='deadbyte.r36-capability-benchmark.v1';
5
6
  const HEX64=/^[0-9a-f]{64}$/;
6
7
  const CASE_ID=/^[A-Za-z0-9._-]{1,96}$/;
7
8
  const SUITE_ID=/^[A-Za-z0-9._-]{1,96}$/;
@@ -48,3 +49,47 @@ export function buildCapabilityBenchmark({suite_id:rawSuiteId,cases:rawCases}={}
48
49
  observation_sha256:sha256(observation)
49
50
  });
50
51
  }
52
+
53
+ const R36_RELEASE_GATE_RESULTS=new Set(['passed','blocked','not_applicable']);
54
+ export function normalizeR36BenchmarkCase(raw){
55
+ const base=normalizeBenchmarkCase(raw);
56
+ if(typeof raw.capability_reachable!=='boolean') throw new Error('benchmark capability_reachable invalid');
57
+ if(typeof raw.evidence_verified!=='boolean') throw new Error('benchmark evidence_verified invalid');
58
+ if(typeof raw.release_gate_result!=='string'||!R36_RELEASE_GATE_RESULTS.has(raw.release_gate_result)) throw new Error('benchmark release_gate_result invalid');
59
+ return Object.freeze({...base,
60
+ capability_reachable:raw.capability_reachable,
61
+ evidence_verified:raw.evidence_verified,
62
+ release_gate_result:raw.release_gate_result
63
+ });
64
+ }
65
+
66
+ export function buildR36CapabilityBenchmark({suite_id:rawSuiteId,cases:rawCases}={}){
67
+ if(typeof rawSuiteId!=='string'||!SUITE_ID.test(rawSuiteId)) throw new Error('benchmark suite_id invalid');
68
+ if(!Array.isArray(rawCases)||rawCases.length<1||rawCases.length>128) throw new Error('benchmark cases invalid');
69
+ const cases=rawCases.map(normalizeR36BenchmarkCase).sort((a,b)=>a.case_id.localeCompare(b.case_id));
70
+ const seen=new Set();
71
+ for(const item of cases){if(seen.has(item.case_id)) throw new Error(`duplicate case '${item.case_id}'`);seen.add(item.case_id);}
72
+ const fixtureIdentity={schema:'deadbyte.r36-capability-fixtures.v1',suite_id:rawSuiteId,
73
+ fixtures:cases.map(item=>({case_id:item.case_id,fixture_sha256:item.fixture_sha256}))};
74
+ const fixture_identity_sha256=sha256(fixtureIdentity);
75
+ const observation={schema:R36_CAPABILITY_BENCHMARK_SCHEMA,suite_id:rawSuiteId,fixture_identity_sha256,cases};
76
+ const capability_closure=cases.every(item=>item.capability_reachable);
77
+ const evidence_closure=cases.every(item=>item.evidence_verified);
78
+ const verdictIdentity={
79
+ schema:'deadbyte.r36-capability-verdict.v1',suite_id:rawSuiteId,fixture_identity_sha256,
80
+ cases:cases.map(item=>({
81
+ case_id:item.case_id,fixture_sha256:item.fixture_sha256,correct:item.correct,
82
+ stale_rejected:item.stale_rejected,recovery_success:item.recovery_success,
83
+ duplicate_side_effects:item.duplicate_side_effects,capability_reachable:item.capability_reachable,
84
+ evidence_verified:item.evidence_verified,release_gate_result:item.release_gate_result
85
+ }))
86
+ };
87
+ return Object.freeze({
88
+ ...observation,
89
+ capability_closure,
90
+ evidence_closure,
91
+ overall_correct:cases.every(item=>item.correct)&&capability_closure&&evidence_closure,
92
+ verdict_identity_sha256:sha256(verdictIdentity),
93
+ observation_sha256:sha256(observation)
94
+ });
95
+ }
@@ -0,0 +1,158 @@
1
+ import { createHash } from 'node:crypto';
2
+
3
+ export const CAPABILITY_LEDGER_SCHEMA='deadbyte.capability-ledger.v1';
4
+ const AUTHORITIES=new Set(['none','process','coding','autonomous','host']);
5
+ const PROFILE_ENV='DEADBYTE_CAPABILITY_PROFILE';
6
+ const COMPACT_TOOL_LIMIT=42;
7
+
8
+ function sha256(text){return createHash('sha256').update(text,'utf8').digest('hex');}
9
+ function canonicalJson(value){
10
+ if(value===null||typeof value!=='object') return JSON.stringify(value);
11
+ if(Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`;
12
+ return `{${Object.keys(value).sort((a,b)=>a.localeCompare(b,'en')).map(key=>`${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(',')}}`;
13
+ }
14
+ function nonEmpty(value,label){if(typeof value!=='string'||value.length<1) throw new Error(`${label} must be non-empty`); return value;}
15
+ function nullableRoute(value,label){if(value===null) return null; return nonEmpty(value,label);}
16
+ function normalizedEntry(raw){
17
+ if(!raw||typeof raw!=='object'||Array.isArray(raw)) throw new Error('capability entry must be an object');
18
+ const authority=nonEmpty(raw.authority,'capability authority');
19
+ if(!AUTHORITIES.has(authority)) throw new Error(`unknown capability authority: ${authority}`);
20
+ const entry={
21
+ id:nonEmpty(raw.id,'capability id'),
22
+ full_tool:nonEmpty(raw.full_tool,'capability full_tool'),
23
+ compact_tool:nullableRoute(raw.compact_tool??null,'capability compact_tool'),
24
+ compact_op:nullableRoute(raw.compact_op??null,'capability compact_op'),
25
+ runtime_flag:raw.runtime_flag===null?null:nonEmpty(raw.runtime_flag,'capability runtime_flag'),
26
+ authority,
27
+ mutating:raw.mutating===true,
28
+ receipt_class:raw.receipt_class===null?null:nonEmpty(raw.receipt_class,'capability receipt_class'),
29
+ production:raw.production===true,
30
+ host_only:raw.host_only===true
31
+ };
32
+ if((entry.compact_tool===null)!==(entry.compact_op===null)) throw new Error(`capability ${entry.id} compact route requires both tool and op`);
33
+ if(entry.host_only&&entry.authority!=='host') throw new Error(`capability ${entry.id} host_only requires host authority`);
34
+ return Object.freeze(entry);
35
+ }
36
+
37
+ export function createCapabilityLedger(entries){
38
+ if(!Array.isArray(entries)) throw new Error('capability entries must be an array');
39
+ const seen=new Set();
40
+ const normalized=entries.map(normalizedEntry);
41
+ for(const item of normalized){
42
+ if(seen.has(item.id)) throw new Error(`duplicate capability id: ${item.id}`);
43
+ seen.add(item.id);
44
+ }
45
+ normalized.sort((a,b)=>a.id.localeCompare(b.id,'en'));
46
+ const frozenEntries=Object.freeze(normalized.slice());
47
+ const body={schema:CAPABILITY_LEDGER_SCHEMA,entries:frozenEntries};
48
+ return Object.freeze({...body,ledger_sha256:sha256(canonicalJson(body))});
49
+ }
50
+
51
+ export function capabilityProfileFromEnv(env=process.env){
52
+ const value=env?.[PROFILE_ENV]??'full';
53
+ if(value!=='full'&&value!=='compact') throw new Error(`${PROFILE_ENV} must be full or compact`);
54
+ return value;
55
+ }
56
+
57
+ function toolNames(snapshot,label){
58
+ if(!snapshot||typeof snapshot!=='object'||!Array.isArray(snapshot.tools)) throw new Error(`${label} tool surface snapshot invalid`);
59
+ const names=snapshot.tools.map(tool=>tool?.name);
60
+ if(names.some(name=>typeof name!=='string'||name.length<1)) throw new Error(`${label} tool surface contains invalid name`);
61
+ return new Set(names);
62
+ }
63
+
64
+ export function assertCapabilityClosure({ledger,fullToolSnapshot,compactToolSnapshot}){
65
+ if(!ledger||ledger.schema!==CAPABILITY_LEDGER_SCHEMA||!Array.isArray(ledger.entries)) throw new Error('capability ledger invalid');
66
+ const full=toolNames(fullToolSnapshot,'full');
67
+ const compact=toolNames(compactToolSnapshot,'compact');
68
+ if(compact.size>COMPACT_TOOL_LIMIT) throw new Error(`compact surface exceeds ${COMPACT_TOOL_LIMIT}-tool limit: ${compact.size}`);
69
+ for(const capability of ledger.entries){
70
+ if(!full.has(capability.full_tool)) throw new Error(`capability ${capability.id} full tool missing: ${capability.full_tool}`);
71
+ if(capability.production&&!capability.host_only){
72
+ if(!capability.compact_tool||!capability.compact_op) throw new Error(`capability ${capability.id} compact route missing`);
73
+ if(!compact.has(capability.compact_tool)) throw new Error(`capability ${capability.id} compact tool missing: ${capability.compact_tool}`);
74
+ }
75
+ }
76
+ return true;
77
+ }
78
+
79
+ const direct=(id,tool,runtime_flag,authority,{mutating=false,receipt_class='direct',production=true,host_only=false}={})=>({id,full_tool:tool,compact_tool:tool,compact_op:'direct',runtime_flag,authority,mutating,receipt_class,production,host_only});
80
+ const gateway=(id,full_tool,compact_tool,compact_op,runtime_flag,authority,{mutating=false,receipt_class='direct',production=true}={})=>({id,full_tool,compact_tool,compact_op,runtime_flag,authority,mutating,receipt_class,production,host_only:false});
81
+
82
+ export const R36_CAPABILITY_ENTRIES=Object.freeze([
83
+ direct('evidence.verify','evidence_verify',null,'none',{receipt_class:'verification'}),
84
+ gateway('machine.list','machine_list','machine_observe','machine_list','DEADBYTE_MACHINE_RUNTIME','none',{receipt_class:'machine'}),
85
+ gateway('machine.status','machine_status','machine_observe','machine_status','DEADBYTE_MACHINE_RUNTIME','none',{receipt_class:'machine'}),
86
+ gateway('machine.ping','machine_ping','machine_observe','machine_ping','DEADBYTE_MACHINE_RUNTIME','none',{receipt_class:'machine'}),
87
+ direct('machine.revoke','machine_revoke','DEADBYTE_MACHINE_RUNTIME','host',{mutating:true,receipt_class:'machine',production:false,host_only:true}),
88
+
89
+ gateway('process.start','process_session_start','process_session','start','DEADBYTE_PROCESS_RUNTIME','process',{mutating:true,receipt_class:'process'}),
90
+ gateway('process.read','process_session_read','process_session','read','DEADBYTE_PROCESS_RUNTIME','process',{receipt_class:'process'}),
91
+ gateway('process.status','process_session_status','process_session','status','DEADBYTE_PROCESS_RUNTIME','process',{receipt_class:'process'}),
92
+ gateway('process.list','process_session_list','process_session','list','DEADBYTE_PROCESS_RUNTIME','process',{receipt_class:'process'}),
93
+ gateway('process.action','process_session_action','process_session','action','DEADBYTE_PROCESS_RUNTIME','process',{mutating:true,receipt_class:'process'}),
94
+ gateway('process.terminate','process_session_terminate','process_session','terminate','DEADBYTE_PROCESS_RUNTIME','process',{mutating:true,receipt_class:'process'}),
95
+
96
+ direct('coding.session_status','coding_session_status','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'coding'}),
97
+ direct('coding.tree','coding_tree','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'coding'}),
98
+ gateway('coding.stat','coding_stat','coding_inspect','stat','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'coding'}),
99
+ gateway('coding.search','coding_search','coding_inspect','search','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'coding'}),
100
+ gateway('coding.files_read','coding_files_read','coding_inspect','files_read','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'coding'}),
101
+ gateway('semantic.outline','coding_symbol_outline','coding_inspect','symbol_outline','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'semantic'}),
102
+ gateway('semantic.definition','coding_symbol_definition','coding_inspect','symbol_definition','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'semantic'}),
103
+ gateway('semantic.references','coding_symbol_references','coding_inspect','symbol_references','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'semantic'}),
104
+ gateway('semantic.diagnostics','coding_symbol_diagnostics','coding_inspect','symbol_diagnostics','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'semantic'}),
105
+ gateway('semantic.implementations','coding_symbol_implementations','coding_inspect','symbol_implementations','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'semantic'}),
106
+ gateway('semantic.rename_preview','coding_symbol_rename_preview','coding_inspect','symbol_rename_preview','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{receipt_class:'native_diff'}),
107
+ direct('semantic.replace','coding_symbol_replace','DEADBYTE_CODING_RUNTIME','coding',{mutating:true,receipt_class:'coding'}),
108
+ direct('coding.file_read','coding_file_read','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'coding'}),
109
+ direct('coding.file_write','coding_file_write','DEADBYTE_CODING_RUNTIME','coding',{mutating:true,receipt_class:'coding'}),
110
+ direct('coding.text_replace','coding_text_replace','DEADBYTE_CODING_RUNTIME','coding',{mutating:true,receipt_class:'coding'}),
111
+ direct('coding.command_run','coding_command_run','DEADBYTE_CODING_RUNTIME','coding',{mutating:true,receipt_class:'coding'}),
112
+ direct('coding.benchmark_run','coding_benchmark_run','DEADBYTE_CODING_RUNTIME','coding',{mutating:true,receipt_class:'coding'}),
113
+ direct('coding.receipt_verify','coding_receipt_verify','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'verification'}),
114
+ direct('coding.task_submit','coding_task_submit','DEADBYTE_CODING_RUNTIME','coding',{mutating:true,receipt_class:'task'}),
115
+ direct('coding.task_run','coding_task_run','DEADBYTE_CODING_RUNTIME','coding',{mutating:true,receipt_class:'task'}),
116
+ direct('coding.task_status','coding_task_status','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'task'}),
117
+ direct('coding.task_events','coding_task_events','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'task'}),
118
+ direct('coding.task_cancel','coding_task_cancel','DEADBYTE_CODING_RUNTIME','coding',{mutating:true,receipt_class:'task'}),
119
+ direct('coding.task_approve','coding_task_approve','DEADBYTE_CODING_RUNTIME','coding',{mutating:true,receipt_class:'task'}),
120
+ direct('coding.task_verify','coding_task_verify','DEADBYTE_CODING_RUNTIME','coding',{receipt_class:'verification'}),
121
+
122
+ gateway('machine_fs.stat','machine_fs_stat','machine_fs','stat','DEADBYTE_MACHINE_FS_RUNTIME','coding',{receipt_class:'machine_fs'}),
123
+ gateway('machine_fs.list','machine_fs_list','machine_fs','list','DEADBYTE_MACHINE_FS_RUNTIME','coding',{receipt_class:'machine_fs'}),
124
+ gateway('machine_fs.read','machine_fs_read','machine_fs','read','DEADBYTE_MACHINE_FS_RUNTIME','coding',{receipt_class:'machine_fs'}),
125
+ gateway('machine_fs.write','machine_fs_write','machine_fs','write','DEADBYTE_MACHINE_FS_RUNTIME','coding',{mutating:true,receipt_class:'machine_fs'}),
126
+ gateway('machine_fs.edit_exact','machine_fs_edit_exact','machine_fs','edit_exact','DEADBYTE_MACHINE_FS_RUNTIME','coding',{mutating:true,receipt_class:'machine_fs'}),
127
+ gateway('machine_fs.mkdir','machine_fs_mkdir','machine_fs','mkdir','DEADBYTE_MACHINE_FS_RUNTIME','coding',{mutating:true,receipt_class:'machine_fs'}),
128
+ gateway('machine_fs.move','machine_fs_move','machine_fs','move','DEADBYTE_MACHINE_FS_RUNTIME','coding',{mutating:true,receipt_class:'machine_fs'}),
129
+ gateway('machine_fs.delete','machine_fs_delete','machine_fs','delete','DEADBYTE_MACHINE_FS_RUNTIME','coding',{mutating:true,receipt_class:'machine_fs'}),
130
+
131
+ gateway('observation.search_start','machine_search_start','machine_observe','search_start','DEADBYTE_OBSERVATION_RUNTIME','none',{receipt_class:'observation'}),
132
+ gateway('observation.search_page','machine_search_page','machine_observe','search_page','DEADBYTE_OBSERVATION_RUNTIME','none',{receipt_class:'observation'}),
133
+ gateway('observation.search_status','machine_search_status','machine_observe','search_status','DEADBYTE_OBSERVATION_RUNTIME','none',{receipt_class:'observation'}),
134
+ gateway('observation.search_cancel','machine_search_cancel','machine_observe','search_cancel','DEADBYTE_OBSERVATION_RUNTIME','none',{receipt_class:'observation'}),
135
+ gateway('observation.process_list','machine_process_list','machine_observe','process_list','DEADBYTE_OBSERVATION_RUNTIME','none',{receipt_class:'observation'}),
136
+ gateway('observation.system_status','machine_system_status','machine_observe','system_status','DEADBYTE_OBSERVATION_RUNTIME','none',{receipt_class:'observation'}),
137
+
138
+ direct('autonomous.session_status','autonomous_session_status','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{receipt_class:'autonomous'}),
139
+ direct('native_diff.preview','native_diff_preview','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'native_diff'}),
140
+ direct('native_diff.apply','native_diff_apply','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'native_diff'}),
141
+ direct('native_diff.verify','native_diff_verify','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{receipt_class:'verification'}),
142
+ direct('autonomous.goal_submit','autonomous_goal_submit','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'autonomous'}),
143
+ direct('autonomous.goal_run','autonomous_goal_run','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'autonomous'}),
144
+ direct('autonomous.goal_status','autonomous_goal_status','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{receipt_class:'autonomous'}),
145
+ direct('autonomous.goal_events','autonomous_goal_events','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{receipt_class:'autonomous'}),
146
+ direct('autonomous.goal_cancel','autonomous_goal_cancel','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'autonomous'}),
147
+ direct('autonomous.goal_approve','autonomous_goal_approve','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'autonomous'}),
148
+ direct('autonomous.goal_verify','autonomous_goal_verify','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{receipt_class:'verification'}),
149
+ direct('autonomous.release_gate','autonomous_release_gate','DEADBYTE_AUTONOMOUS_RUNTIME','autonomous',{mutating:true,receipt_class:'release'}),
150
+
151
+ direct('host.file_read','host_file_read','DEADBYTE_PRIVILEGED_POLICY','host',{receipt_class:'host',production:false,host_only:true}),
152
+ direct('host.file_write','host_file_write','DEADBYTE_PRIVILEGED_POLICY','host',{mutating:true,receipt_class:'host',production:false,host_only:true}),
153
+ direct('host.exec','host_exec','DEADBYTE_PRIVILEGED_POLICY','host',{mutating:true,receipt_class:'host',production:false,host_only:true})
154
+ ]);
155
+ export const R36_CAPABILITY_LEDGER=createCapabilityLedger(R36_CAPABILITY_ENTRIES);
156
+
157
+ export const CAPABILITY_PROFILE_ENV=PROFILE_ENV;
158
+ export const COMPACT_SURFACE_TOOL_LIMIT=COMPACT_TOOL_LIMIT;
@@ -4,7 +4,8 @@ import {
4
4
  codingBenchmarkRunOutputSchema, codingCommandRunOutputSchema,
5
5
  codingFileReadOutputSchema, codingFilesReadOutputSchema, codingFileWriteOutputSchema,
6
6
  codingReceiptVerifyOutputSchema, codingSearchOutputSchema, codingSessionStatusOutputSchema, codingStatOutputSchema,
7
- codingSymbolOutlineOutputSchema, codingSymbolDefinitionOutputSchema, codingSymbolReferencesOutputSchema, codingSymbolReplaceOutputSchema,
7
+ codingSymbolOutlineOutputSchema, codingSymbolDefinitionOutputSchema, codingSymbolReferencesOutputSchema,
8
+ codingSymbolDiagnosticsOutputSchema, codingSymbolImplementationsOutputSchema, codingSymbolRenamePreviewOutputSchema, codingSymbolReplaceOutputSchema,
8
9
  codingTaskApproveOutputSchema, codingTaskCancelOutputSchema,
9
10
  codingTaskEventsOutputSchema, codingTaskRunOutputSchema,
10
11
  codingTaskStatusOutputSchema, codingTaskSubmitOutputSchema,
@@ -67,13 +68,16 @@ export function registerCodingTools(server, { codingRuntime, taskRuntime, semant
67
68
  }, async ({ root_id, path, hash }) => { try { return result(codingStatOutputSchema, await codingRuntime.stat({ rootId: root_id, relativePath: path, hash })); } catch (error) { return fail(codingStatOutputSchema, error); } });
68
69
 
69
70
  server.registerTool('coding_search', {
70
- description: 'Deterministic literal content search using the existing coding tree/read authority.',
71
+ description: 'Deterministic bounded content/path search with literal or regex mode, signed cursor paging, and observed file identities.',
71
72
  inputSchema: z.strictObject({ root_id: rootId, path: relPath.default('.'), pattern: z.string().min(1).max(256),
72
- mode: z.literal('literal').default('literal'), case_sensitive: z.boolean().default(false),
73
- max_results: z.number().int().min(1).max(1000).default(200), max_file_bytes: z.number().int().min(1).max(4194304).default(262144) }),
73
+ target: z.enum(['content','path']).default('content'), mode: z.enum(['literal','regex']).default('literal'), case_sensitive: z.boolean().default(false),
74
+ max_results: z.number().int().min(1).max(1000).default(200), max_file_bytes: z.number().int().min(1).max(4194304).default(262144),
75
+ max_scan_bytes: z.number().int().min(1).max(67108864).default(4194304), page_size: z.number().int().min(1).max(500).default(100),
76
+ cursor: z.string().max(8192).nullable().default(null) }),
74
77
  outputSchema: codingSearchOutputSchema
75
- }, async ({ root_id, path, pattern, mode, case_sensitive, max_results, max_file_bytes }) => {
76
- try { return result(codingSearchOutputSchema, await codingRuntime.search({ rootId: root_id, path, pattern, mode, caseSensitive: case_sensitive, maxResults: max_results, maxFileBytes: max_file_bytes })); }
78
+ }, async ({ root_id, path, pattern, target, mode, case_sensitive, max_results, max_file_bytes, max_scan_bytes, page_size, cursor }) => {
79
+ try { return result(codingSearchOutputSchema, await codingRuntime.search({ rootId: root_id, path, pattern, target, mode, caseSensitive: case_sensitive,
80
+ maxResults: max_results, maxFileBytes: max_file_bytes, maxScanBytes: max_scan_bytes, pageSize: page_size, cursor })); }
77
81
  catch (error) { return fail(codingSearchOutputSchema, error); }
78
82
  });
79
83
 
@@ -95,6 +99,24 @@ export function registerCodingTools(server, { codingRuntime, taskRuntime, semant
95
99
  outputSchema: codingSymbolReferencesOutputSchema
96
100
  }, async ({ root_id, path, line, column, max_results }) => { try { return result(codingSymbolReferencesOutputSchema, await semanticRuntime.references({ rootId: root_id, relativePath: path, line, column, maxResults: max_results })); } catch (error) { return fail(codingSymbolReferencesOutputSchema, error); } });
97
101
 
102
+ server.registerTool('coding_symbol_diagnostics', {
103
+ description: 'Return bounded normalized semantic diagnostics with target and result identities.',
104
+ inputSchema: z.strictObject({ root_id: rootId, path: relPath, max_results: z.number().int().min(1).max(500).default(200) }),
105
+ outputSchema: codingSymbolDiagnosticsOutputSchema
106
+ }, async ({ root_id, path, max_results }) => { try { const value=await semanticRuntime.diagnostics({ rootId:root_id, relativePath:path, maxResults:max_results }); return result(codingSymbolDiagnosticsOutputSchema,value,value.status==='failed'); } catch(error){ return fail(codingSymbolDiagnosticsOutputSchema,error); } });
107
+
108
+ server.registerTool('coding_symbol_implementations', {
109
+ description: 'Resolve bounded semantic implementations at a zero-based line/column. Unsupported backends report an explicit typed status.',
110
+ inputSchema: z.strictObject({ root_id:rootId, path:relPath, line:z.number().int().min(0), column:z.number().int().min(0), max_results:z.number().int().min(1).max(500).default(200) }),
111
+ outputSchema: codingSymbolImplementationsOutputSchema
112
+ }, async ({ root_id, path, line, column, max_results }) => { try { const value=await semanticRuntime.implementations({rootId:root_id,relativePath:path,line,column,maxResults:max_results}); return result(codingSymbolImplementationsOutputSchema,value,false); } catch(error){ return fail(codingSymbolImplementationsOutputSchema,error); } });
113
+
114
+ server.registerTool('coding_symbol_rename_preview', {
115
+ description: 'Preview one semantic rename as a content-addressed Native Diff. This tool never mutates source bytes.',
116
+ inputSchema: z.strictObject({ root_id:rootId, path:relPath, line:z.number().int().min(0), column:z.number().int().min(0), new_name:z.string().regex(/^[A-Za-z_$][A-Za-z0-9_$]{0,127}$/) }),
117
+ outputSchema: codingSymbolRenamePreviewOutputSchema
118
+ }, async ({ root_id, path, line, column, new_name }) => { try { const value=await semanticRuntime.renamePreview({rootId:root_id,relativePath:path,line,column,newName:new_name}); return result(codingSymbolRenamePreviewOutputSchema,value,false); } catch(error){ return fail(codingSymbolRenamePreviewOutputSchema,error); } });
119
+
98
120
  server.registerTool('coding_symbol_replace', {
99
121
  description: 'Replace one current JS/TS symbol body by symbol_id under exact file SHA-256 precondition. The commit reuses the coding plane signed surgical-edit receipt path.',
100
122
  inputSchema: z.strictObject({ root_id: rootId, path: relPath, symbol_id: hex64, new_body: z.string().max(524288), expected_sha256: hex64 }),
@@ -102,21 +124,13 @@ export function registerCodingTools(server, { codingRuntime, taskRuntime, semant
102
124
  }, async ({ root_id, path, symbol_id, new_body, expected_sha256 }) => { try { return result(codingSymbolReplaceOutputSchema, await semanticRuntime.replaceSymbol({ rootId: root_id, relativePath: path, symbolId: symbol_id, newBody: new_body, expectedSha256: expected_sha256 })); } catch (error) { return fail(codingSymbolReplaceOutputSchema, error); } });
103
125
 
104
126
  server.registerTool('coding_files_read', {
105
- description: 'Read up to 32 bounded files in one request using the same coding-policy lease and deny-path checks as coding_file_read.',
127
+ description: 'Read up to 32 bounded files under one coding lease and return an aggregate observation identity over ordered file metadata.',
106
128
  inputSchema: z.strictObject({ root_id: rootId, files: z.array(z.strictObject({ path: relPath, encoding: z.enum(['utf8','base64']).default('utf8') })).min(1).max(32),
107
129
  max_total_bytes: z.number().int().min(1).max(2097152).default(1048576) }),
108
130
  outputSchema: codingFilesReadOutputSchema
109
131
  }, async ({ root_id, files, max_total_bytes }) => {
110
- try {
111
- const values=[]; let total=0;
112
- for(const item of files){
113
- const read=await codingRuntime.fileRead({rootId:root_id,relativePath:item.path,encoding:item.encoding});
114
- total+=read.bytes;
115
- if(total>max_total_bytes) throw new Error(`coding multi-read exceeds ${max_total_bytes} byte total limit`);
116
- values.push({path:item.path,encoding:item.encoding,bytes:read.bytes,sha256:read.sha256,content:read.content});
117
- }
118
- return result(codingFilesReadOutputSchema,{status:'ok',root_id,total_bytes:total,files:values});
119
- } catch(error){ return fail(codingFilesReadOutputSchema,error); }
132
+ try { return result(codingFilesReadOutputSchema,await codingRuntime.filesRead({rootId:root_id,files,maxTotalBytes:max_total_bytes})); }
133
+ catch(error){ return fail(codingFilesReadOutputSchema,error); }
120
134
  });
121
135
 
122
136
  server.registerTool('coding_file_read', {
@@ -70,18 +70,25 @@ export const codingTreeOutputSchema = statusContract({
70
70
  export const codingStatOutputSchema = statusContract({
71
71
  statuses: ['ok', 'failed'],
72
72
  shape: { root_id: z.string().min(1).max(64).optional(), path: z.string().min(1).max(512).optional(),
73
- type: z.enum(['file','directory','symlink','other']).optional(), bytes: z.number().int().min(0).optional(),
74
- mtime_utc: z.string().min(1).optional(), sha256: hex64.nullable().optional() },
75
- successStatuses: ['ok'], successRequired: ['root_id','path','type','bytes','mtime_utc','sha256']
73
+ normalized_path: z.string().min(1).max(512).optional(), type: z.enum(['file','directory','symlink','other']).optional(),
74
+ bytes: z.number().int().min(0).optional(), mtime_utc: z.string().min(1).optional(), sha256: hex64.nullable().optional(),
75
+ reparse_state: z.enum(['none','symlink']).optional(), object_identity_sha256: hex64.optional(),
76
+ policy_root_id: z.string().min(1).max(64).optional(), observation_sha256: hex64.optional() },
77
+ successStatuses: ['ok'], successRequired: ['root_id','path','normalized_path','type','bytes','mtime_utc','sha256','reparse_state','object_identity_sha256','policy_root_id','observation_sha256']
76
78
  });
77
79
  export const codingSearchOutputSchema = statusContract({
78
80
  statuses: ['ok', 'failed'],
79
81
  shape: { root_id: z.string().min(1).max(64).optional(), path: z.string().min(1).max(512).optional(),
80
- pattern: z.string().min(1).max(256).optional(), mode: z.literal('literal').optional(), case_sensitive: z.boolean().optional(),
81
- matches: z.array(z.strictObject({ path: z.string().min(1).max(512), line: z.number().int().min(1),
82
- column: z.number().int().min(1), preview: z.string().max(512) })).max(1000).optional(),
83
- files_scanned: z.number().int().min(0).optional(), bytes_scanned: z.number().int().min(0).optional(), truncated: z.boolean().optional() },
84
- successStatuses: ['ok'], successRequired: ['root_id','path','pattern','mode','case_sensitive','matches','files_scanned','bytes_scanned','truncated']
82
+ pattern: z.string().min(1).max(256).optional(), target: z.enum(['content','path']).optional(),
83
+ mode: z.enum(['literal','regex']).optional(), case_sensitive: z.boolean().optional(),
84
+ matches: z.array(z.strictObject({ path: z.string().min(1).max(512), line: z.number().int().min(1).nullable(),
85
+ column: z.number().int().min(1).nullable(), preview: z.string().max(512), file_sha256: hex64.nullable() })).max(500).optional(),
86
+ files_scanned: z.number().int().min(0).optional(), bytes_scanned: z.number().int().min(0).optional(),
87
+ binary_files_skipped: z.number().int().min(0).optional(), truncated: z.boolean().optional(),
88
+ truncation_reason: z.enum(['tree_limit','scan_byte_limit','max_results']).nullable().optional(),
89
+ query_sha256: hex64.optional(), snapshot_sha256: hex64.optional(), page_sha256: hex64.optional(),
90
+ next_cursor: z.string().max(8192).nullable().optional() },
91
+ successStatuses: ['ok'], successRequired: ['root_id','path','pattern','target','mode','case_sensitive','matches','files_scanned','bytes_scanned','binary_files_skipped','truncated','truncation_reason','query_sha256','snapshot_sha256','page_sha256','next_cursor']
85
92
  });
86
93
  const semanticLocationSchema = z.strictObject({
87
94
  path: z.string().min(1).max(512), name: z.string().max(256), kind: z.string().min(1).max(64),
@@ -113,6 +120,36 @@ export const codingSymbolReferencesOutputSchema = statusContract({
113
120
  locations: z.array(semanticLocationSchema).max(500).optional(), truncated: z.boolean().optional() },
114
121
  successStatuses: ['ok'], successRequired: ['root_id','path','line','column','engine','locations','truncated']
115
122
  });
123
+ export const codingSymbolDiagnosticsOutputSchema = z.strictObject({
124
+ status:z.enum(['ok','unsupported','failed']), error:z.string().optional(), capability:z.string().max(64).optional(),
125
+ root_id:z.string().min(1).max(64).optional(), path:z.string().min(1).max(512).optional(), file_sha256:hex64.optional(),
126
+ engine:z.string().min(1).max(128).optional(), diagnostics:z.array(z.strictObject({message:z.string().max(4096),code:z.string().max(256),severity:z.string().min(1).max(64),location:semanticLocationSchema.optional()})).max(500).optional(),
127
+ truncated:z.boolean().optional(), result_sha256:hex64.optional()
128
+ }).superRefine((value,ctx)=>{
129
+ if(value.status==='failed'){requireFields(value,ctx,['error']);return;}
130
+ if(value.status==='unsupported'){requireFields(value,ctx,['capability','engine']);return;}
131
+ requireFields(value,ctx,['root_id','path','file_sha256','engine','diagnostics','truncated','result_sha256']);
132
+ });
133
+ export const codingSymbolImplementationsOutputSchema = z.strictObject({
134
+ status:z.enum(['ok','unsupported','failed']), error:z.string().optional(), capability:z.string().max(64).optional(),
135
+ root_id:z.string().min(1).max(64).optional(), path:z.string().min(1).max(512).optional(), line:z.number().int().min(0).optional(), column:z.number().int().min(0).optional(),
136
+ file_sha256:hex64.optional(), engine:z.string().min(1).max(128).optional(), locations:z.array(semanticLocationSchema).max(500).optional(),
137
+ truncated:z.boolean().optional(), result_sha256:hex64.optional()
138
+ }).superRefine((value,ctx)=>{
139
+ if(value.status==='failed'){requireFields(value,ctx,['error']);return;}
140
+ if(value.status==='unsupported'){requireFields(value,ctx,['capability','engine']);return;}
141
+ requireFields(value,ctx,['root_id','path','line','column','file_sha256','engine','locations','truncated','result_sha256']);
142
+ });
143
+ export const codingSymbolRenamePreviewOutputSchema = z.strictObject({
144
+ status:z.enum(['ready','unsupported','failed']), error:z.string().optional(), capability:z.string().max(64).optional(), engine:z.string().min(1).max(128).optional(),
145
+ diff_id:hex64.optional(), affected_files:z.number().int().min(1).max(32).optional(), edit_count:z.number().int().min(1).optional(), backend:z.string().min(1).max(128).optional(),
146
+ preimages:z.array(z.strictObject({path:z.string().min(1).max(512),sha256:hex64})).max(32).optional()
147
+ }).superRefine((value,ctx)=>{
148
+ if(value.status==='failed'){requireFields(value,ctx,['error']);return;}
149
+ if(value.status==='unsupported'){requireFields(value,ctx,['capability','engine']);return;}
150
+ requireFields(value,ctx,['diff_id','affected_files','edit_count','backend','preimages']);
151
+ });
152
+
116
153
  export const codingSymbolReplaceOutputSchema = statusContract({
117
154
  statuses: ['committed','failed'],
118
155
  shape: { root_id: z.string().min(1).max(64).optional(), path: z.string().min(1).max(512).optional(), previous_sha256: hex64.optional(),
@@ -125,8 +162,9 @@ export const codingSymbolReplaceOutputSchema = statusContract({
125
162
  export const codingFilesReadOutputSchema = statusContract({
126
163
  statuses: ['ok','failed'],
127
164
  shape: { root_id: z.string().min(1).max(64).optional(), total_bytes: z.number().int().min(0).optional(),
128
- files: z.array(z.strictObject({ path: z.string().min(1).max(512), encoding: z.enum(['utf8','base64']), bytes: z.number().int().min(0), sha256: hex64, content: z.string() })).max(32).optional() },
129
- successStatuses: ['ok'], successRequired: ['root_id','total_bytes','files']
165
+ files: z.array(z.strictObject({ path: z.string().min(1).max(512), encoding: z.enum(['utf8','base64']), bytes: z.number().int().min(0), sha256: hex64, content: z.string() })).max(32).optional(),
166
+ observation_sha256: hex64.optional() },
167
+ successStatuses: ['ok'], successRequired: ['root_id','total_bytes','files','observation_sha256']
130
168
  });
131
169
  export const codingFileReadOutputSchema = statusContract({
132
170
  statuses: ['ok', 'failed'],