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,52 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { mkdir, open, readFile } from 'node:fs/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+
7
+ const here=path.dirname(fileURLToPath(import.meta.url));
8
+ const root=path.resolve(here,'..');
9
+ const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
10
+ const marker='DEADBYTE V0.10.0 / R36 WINDOWS BATCH GATE: PASS';
11
+ function insist(ok,message){if(!ok) throw new Error(message);}
12
+
13
+ export async function writeWindowsGateEvidence({
14
+ candidateRoot=root,
15
+ stateRoot=path.resolve(process.env.DEADBYTE_STATE_ROOT||path.join(os.homedir(),'.deadbyte-mcp')),
16
+ clock=()=>new Date()
17
+ }={}){
18
+ const candidate=path.resolve(candidateRoot);
19
+ const manifestBytes=await readFile(path.join(candidate,'MANIFEST.SHA256'));
20
+ const manifestSha256=sha256(manifestBytes);
21
+ const pkg=JSON.parse(await readFile(path.join(candidate,'package.json'),'utf8'));
22
+ insist(pkg.version==='0.10.0',`Windows gate evidence requires V0.10.0, found ${pkg.version}`);
23
+ const completed=clock();
24
+ insist(completed instanceof Date&&!Number.isNaN(completed.getTime()),'Windows gate evidence clock invalid');
25
+ const evidence={
26
+ schema:'deadbyte.r36-windows-gate.v1',status:'passed',exit_code:0,version:'0.10.0',
27
+ marker,completed_at_utc:completed.toISOString(),manifest_sha256:manifestSha256
28
+ };
29
+ const bytes=Buffer.from(`${JSON.stringify(evidence,null,2)}\n`,'utf8');
30
+ const dir=path.join(path.resolve(stateRoot),'evidence','release');
31
+ await mkdir(dir,{recursive:true});
32
+ const file=path.join(dir,`r36-windows-gate-${manifestSha256.slice(0,16)}.json`);
33
+ try{
34
+ const handle=await open(file,'wx',0o600);
35
+ try{await handle.writeFile(bytes);await handle.sync();}finally{await handle.close();}
36
+ return {status:'written',path:file,sha256:sha256(bytes),manifest_sha256:manifestSha256};
37
+ }catch(error){
38
+ if(error?.code!=='EEXIST') throw error;
39
+ const existingBytes=await readFile(file);
40
+ const existing=JSON.parse(existingBytes.toString('utf8'));
41
+ insist(existing.schema===evidence.schema&&existing.status==='passed'&&existing.exit_code===0,'existing Windows gate evidence invalid');
42
+ insist(existing.version==='0.10.0'&&existing.marker===marker&&existing.manifest_sha256===manifestSha256,'existing Windows gate evidence binding mismatch');
43
+ return {status:'existing',path:file,sha256:sha256(existingBytes),manifest_sha256:manifestSha256};
44
+ }
45
+ }
46
+
47
+ const invoked=process.argv[1]&&path.resolve(process.argv[1])===fileURLToPath(import.meta.url);
48
+ if(invoked){
49
+ writeWindowsGateEvidence()
50
+ .then(result=>console.log(JSON.stringify(result)))
51
+ .catch(error=>{console.error(error instanceof Error?error.stack:String(error));process.exitCode=1;});
52
+ }
@@ -7,7 +7,7 @@ import { fileURLToPath } from 'node:url';
7
7
  const here=path.dirname(fileURLToPath(import.meta.url));
8
8
  const root=path.resolve(here,'..');
9
9
  const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
10
- const marker='DEADBYTE V0.9.0 / R35 WINDOWS BATCH GATE: PASS';
10
+ const marker='DEADBYTE V0.11.0 / R37 WINDOWS BATCH GATE: PASS';
11
11
  function insist(ok,message){if(!ok) throw new Error(message);}
12
12
 
13
13
  export async function writeWindowsGateEvidence({
@@ -19,17 +19,17 @@ export async function writeWindowsGateEvidence({
19
19
  const manifestBytes=await readFile(path.join(candidate,'MANIFEST.SHA256'));
20
20
  const manifestSha256=sha256(manifestBytes);
21
21
  const pkg=JSON.parse(await readFile(path.join(candidate,'package.json'),'utf8'));
22
- insist(pkg.version==='0.9.0',`Windows gate evidence requires V0.9.0, found ${pkg.version}`);
22
+ insist(pkg.version==='0.11.0',`Windows gate evidence requires V0.11.0, found ${pkg.version}`);
23
23
  const completed=clock();
24
24
  insist(completed instanceof Date&&!Number.isNaN(completed.getTime()),'Windows gate evidence clock invalid');
25
25
  const evidence={
26
- schema:'deadbyte.r35-windows-gate.v1',status:'passed',exit_code:0,version:'0.9.0',
26
+ schema:'deadbyte.r37-windows-gate.v1',status:'passed',exit_code:0,version:'0.11.0',
27
27
  marker,completed_at_utc:completed.toISOString(),manifest_sha256:manifestSha256
28
28
  };
29
29
  const bytes=Buffer.from(`${JSON.stringify(evidence,null,2)}\n`,'utf8');
30
30
  const dir=path.join(path.resolve(stateRoot),'evidence','release');
31
31
  await mkdir(dir,{recursive:true});
32
- const file=path.join(dir,`r35-windows-gate-${manifestSha256.slice(0,16)}.json`);
32
+ const file=path.join(dir,`r37-windows-gate-${manifestSha256.slice(0,16)}.json`);
33
33
  try{
34
34
  const handle=await open(file,'wx',0o600);
35
35
  try{await handle.writeFile(bytes);await handle.sync();}finally{await handle.close();}
@@ -39,7 +39,7 @@ export async function writeWindowsGateEvidence({
39
39
  const existingBytes=await readFile(file);
40
40
  const existing=JSON.parse(existingBytes.toString('utf8'));
41
41
  insist(existing.schema===evidence.schema&&existing.status==='passed'&&existing.exit_code===0,'existing Windows gate evidence invalid');
42
- insist(existing.version==='0.9.0'&&existing.marker===marker&&existing.manifest_sha256===manifestSha256,'existing Windows gate evidence binding mismatch');
42
+ insist(existing.version==='0.11.0'&&existing.marker===marker&&existing.manifest_sha256===manifestSha256,'existing Windows gate evidence binding mismatch');
43
43
  return {status:'existing',path:file,sha256:sha256(existingBytes),manifest_sha256:manifestSha256};
44
44
  }
45
45
  }
@@ -0,0 +1,98 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { canonicalJson } from './canonical-json.mjs';
3
+
4
+ export const AGENT_MEMORY_SCHEMA='deadbyte.agent-memory.v1';
5
+ const HEX64=/^[0-9a-f]{64}$/;
6
+ const sha=value=>createHash('sha256').update(Buffer.from(canonicalJson(value),'utf8')).digest('hex');
7
+ const uniq=values=>[...new Set(values.filter(v=>typeof v==='string'&&v.length>0))];
8
+
9
+ function tokens(text){return uniq(String(text??'').toLowerCase().split(/[^a-z0-9_.\/-]+/).filter(x=>x.length>1));}
10
+ function compactEvent(event){
11
+ const p=event?.payload&&typeof event.payload==='object'?event.payload:{};
12
+ const safe={seq:event?.seq??null,type:event?.type??'unknown',event_sha256:HEX64.test(event?.event_sha256??'')?event.event_sha256:null};
13
+ for(const key of ['reason','profile_id','mutation_epoch','receipt_sha256','diff_receipt_sha256','action_key']){
14
+ if(p[key]!==undefined) safe[key]=p[key];
15
+ }
16
+ if(Array.isArray(p.paths)) safe.paths=p.paths.filter(x=>typeof x==='string').slice(0,32);
17
+ return safe;
18
+ }
19
+
20
+ export function deriveAgentMemory(events,{maxArchival=96}={}){
21
+ if(!Array.isArray(events)) throw new Error('memory events must be array');
22
+ const acceptance=[],proven=[],rejected=[],blockers=new Set(),files=new Map(),profiles=new Map();
23
+ const archival=[];
24
+ for(const event of events){
25
+ const p=event?.payload&&typeof event.payload==='object'?event.payload:{};
26
+ if(event?.type==='goal_created'&&typeof p.acceptance==='string'&&p.acceptance) acceptance.push(p.acceptance);
27
+ if(event?.type==='profile_completed'&&typeof p.profile_id==='string'){
28
+ profiles.set(p.profile_id,{id:`profile:${p.profile_id}`,kind:'profile',label:p.profile_id,passed:p.passed===true,
29
+ receipt_sha256:HEX64.test(p.receipt_sha256??'')?p.receipt_sha256:null});
30
+ if(p.passed===true){proven.push(`${p.profile_id}:passed`);blockers.delete(`profile:${p.profile_id}`);}
31
+ else blockers.add(`profile:${p.profile_id}`);
32
+ }
33
+ if(event?.type==='native_diff_committed'){
34
+ for(const file of p.paths??[]) if(typeof file==='string'&&file) files.set(file,{id:`file:${file}`,kind:'file',label:file});
35
+ }
36
+ if(event?.type==='planner_rejected'&&typeof p.reason==='string') rejected.push(p.reason);
37
+ if(event?.type==='waiting_entered'&&typeof p.reason==='string') blockers.add(`wait:${p.reason}`);
38
+ if(event?.type==='waiting_resumed'&&typeof p.previous_reason==='string') blockers.delete(`wait:${p.previous_reason}`);
39
+ if(['planner_rejected','profile_completed','native_diff_committed','waiting_entered','waiting_resumed','release_completed'].includes(event?.type)){
40
+ archival.push(compactEvent(event));
41
+ }
42
+ }
43
+ const core={acceptance_constraints:uniq(acceptance),proven_invariants:uniq(proven),
44
+ rejected_approaches:uniq(rejected),unresolved_blockers:[...blockers].sort()};
45
+ const nodes=[
46
+ {id:'goal:current',kind:'goal',label:core.acceptance_constraints.join(' | ')||'current goal'},
47
+ ...[...files.values()].sort((a,b)=>a.id.localeCompare(b.id,'en')),
48
+ ...[...profiles.values()].sort((a,b)=>a.id.localeCompare(b.id,'en')),
49
+ ...core.unresolved_blockers.map(id=>({id:`blocker:${id}`,kind:'blocker',label:id}))
50
+ ];
51
+ const edges=[];
52
+ for(const node of nodes){
53
+ if(node.id==='goal:current') continue;
54
+ edges.push({source:'goal:current',target:node.id,kind:node.kind==='file'?'touches':node.kind==='profile'?'verified_by':'blocked_by'});
55
+ }
56
+ const body={schema:AGENT_MEMORY_SCHEMA,core,archival:archival.slice(-maxArchival),graph:{nodes,edges}};
57
+ return Object.freeze({...body,memory_sha256:sha(body)});
58
+ }
59
+
60
+ function score(value,needles){
61
+ const text=JSON.stringify(value).toLowerCase();
62
+ return needles.reduce((n,t)=>n+(text.includes(t)?1:0),0);
63
+ }
64
+ function ranked(values,needles,limit){
65
+ return values.map(value=>({value,score:score(value,needles)})).filter(x=>x.score>0)
66
+ .sort((a,b)=>b.score-a.score||JSON.stringify(a.value).localeCompare(JSON.stringify(b.value),'en'))
67
+ .slice(0,limit).map(x=>x.value);
68
+ }
69
+ export function queryAgentMemory(memory,{query,mode='local',limit=12}={}){
70
+ if(!memory||memory.schema!==AGENT_MEMORY_SCHEMA) throw new Error('memory snapshot invalid');
71
+ if(!['local','global','drift'].includes(mode)) throw new Error('memory query mode invalid');
72
+ if(!Number.isInteger(limit)||limit<1||limit>128) throw new Error('memory query limit invalid');
73
+ const needles=tokens(query);
74
+ let results=[];
75
+ if(mode==='global'){
76
+ results=[
77
+ {kind:'core',...memory.core},
78
+ {kind:'graph_summary',node_count:memory.graph.nodes.length,edge_count:memory.graph.edges.length,
79
+ node_kinds:Object.fromEntries([...new Set(memory.graph.nodes.map(n=>n.kind))].sort().map(k=>[k,memory.graph.nodes.filter(n=>n.kind===k).length]))}
80
+ ];
81
+ if(needles.length) results=ranked([...results,...memory.archival],needles,limit);
82
+ else results=results.slice(0,limit);
83
+ }else{
84
+ const local=ranked([...memory.graph.nodes,...memory.archival],needles,limit);
85
+ results=[...local];
86
+ if(mode==='drift'){
87
+ const ids=new Set(local.filter(x=>x?.id).map(x=>x.id));
88
+ const neighborIds=new Set();
89
+ for(const edge of memory.graph.edges){
90
+ if(ids.has(edge.source)) neighborIds.add(edge.target);
91
+ if(ids.has(edge.target)) neighborIds.add(edge.source);
92
+ }
93
+ for(const node of memory.graph.nodes) if(neighborIds.has(node.id)&&!results.some(x=>x?.id===node.id)) results.push(node);
94
+ results=results.slice(0,limit);
95
+ }
96
+ }
97
+ return Object.freeze({schema:'deadbyte.agent-memory-query.v1',mode,query:String(query??''),memory_sha256:memory.memory_sha256,results});
98
+ }
@@ -213,7 +213,7 @@ function historicalEvidence({ contexts, observations, loopState }) {
213
213
  };
214
214
  }
215
215
 
216
- export function buildLoopContext({ goal, policy, loopState = {}, tree = [], contexts = [], observations = [], decisions = [], projectMemory = null }) {
216
+ export function buildLoopContext({ goal, policy, loopState = {}, tree = [], contexts = [], observations = [], decisions = [], projectMemory = null, capabilities = null }) {
217
217
  if (!policy?.limits || !Number.isInteger(policy.limits.max_context_bytes)) throw new Error('loop context policy byte limit missing');
218
218
  const relevanceEpoch=Number.isInteger(loopState?.mutation_epoch)&&loopState.mutation_epoch>=0?loopState.mutation_epoch:0;
219
219
  const retainedContexts=normalizeEvidence(contexts,{kind:'context',relevanceEpoch});
@@ -249,6 +249,7 @@ export function buildLoopContext({ goal, policy, loopState = {}, tree = [], cont
249
249
  },
250
250
  historical_evidence:historicalEvidence({contexts:retainedContexts,observations:retainedObservations,loopState}),
251
251
  project_memory:memory,
252
+ capabilities:capabilities===null?null:structuredClone(capabilities),
252
253
  profiles
253
254
  };
254
255
  return compactLoopContext(state,policy.limits.max_context_bytes);
@@ -18,7 +18,11 @@ const replaceOperation = z.strictObject({ kind:z.literal('replace'), path:relPat
18
18
  expected_sha256:hex64, old_string:z.string().min(1).max(262144), new_string:z.string().max(524288),
19
19
  expected_replacements:z.number().int().min(1).max(64).default(1) });
20
20
  const deleteOperation = z.strictObject({ kind:z.literal('delete'), path:relPath, expected_sha256:hex64 });
21
- const nativeOperation = z.union([writeOperation,replaceOperation,deleteOperation]);
21
+ const mkdirOperation = z.strictObject({ kind:z.literal('mkdir'), path:relPath });
22
+ const moveOperation = z.strictObject({ kind:z.literal('move'), source_path:relPath, destination_path:relPath,
23
+ expected_source_identity:hex64, expected_destination_identity:z.union([z.literal('absent'),hex64]).default('absent') });
24
+ const rmdirOperation = z.strictObject({ kind:z.literal('rmdir'), path:relPath, expected_source_identity:hex64 });
25
+ const nativeOperation = z.union([writeOperation,replaceOperation,deleteOperation,mkdirOperation,moveOperation,rmdirOperation]);
22
26
  const plannerResponse = z.strictObject({ request_id:hex64, raw_text:z.string().min(2).max(8*1024*1024),
23
27
  model:z.string().min(1).max(128).default('client-model') });
24
28
  function result(schema,value,isError=false) { return autonomousStructuredResult(schema,value,isError); }
@@ -58,21 +58,21 @@ export const autonomousSessionStatusOutputSchema = statusContract({
58
58
 
59
59
  export const nativeDiffPreviewOutputSchema = statusContract({
60
60
  statuses:['ready','failed'], success:['ready'], required:['diff_id','root_id','operation_count','payload_bytes','paths','operations'],
61
- shape:{ diff_id:hex64.optional(), root_id:z.string().min(1).max(64).optional(), operation_count:z.number().int().min(1).max(32).optional(),
62
- payload_bytes:z.number().int().min(0).optional(), paths:z.array(z.string()).max(32).optional(),
61
+ shape:{ schema:z.enum(['deadbyte.native-diff.v1','deadbyte.native-diff.v2']).optional(), diff_id:hex64.optional(), root_id:z.string().min(1).max(64).optional(), operation_count:z.number().int().min(1).max(32).optional(),
62
+ payload_bytes:z.number().int().min(0).optional(), paths:z.array(z.string()).max(64).optional(),
63
63
  operations:z.array(jsonObject).max(32).optional() }
64
64
  });
65
65
  export const nativeDiffApplyOutputSchema = statusContract({
66
66
  statuses:['committed','existing','failed'], success:['committed','existing'],
67
67
  required:['diff_id','receipt_sha256','operation_count'],
68
68
  shape:{ diff_id:hex64.optional(), receipt_sha256:hex64.optional(), operation_count:z.number().int().min(1).max(32).optional(),
69
- current_state_matches:z.boolean().optional(), coding_receipts:z.array(jsonObject).max(32).optional() }
69
+ current_state_matches:z.boolean().optional(), coding_receipts:z.array(jsonObject).max(32).optional(), operation_receipts:z.array(jsonObject).max(32).optional() }
70
70
  });
71
71
  export const nativeDiffVerifyOutputSchema = z.strictObject({
72
72
  status:z.literal('failed').optional(), error:z.string().optional(), ok:z.boolean().optional(), reason:z.string().optional(),
73
73
  diff_id:hex64.optional(), receipt_sha256:hex64.optional(), signature_valid:z.literal(true).optional(),
74
74
  root_id:z.string().min(1).max(64).optional(), operation_count:z.number().int().min(1).max(32).optional(),
75
- coding_receipts_verified:z.number().int().min(0).max(32).optional(), final_states:z.array(jsonObject).max(32).optional(),
75
+ coding_receipts_verified:z.number().int().min(0).max(32).optional(), operation_receipts_verified:z.number().int().min(0).max(32).optional(), final_states:z.array(jsonObject).max(32).optional(),
76
76
  current_state_matches:z.boolean().optional(), journal_head_sha256:hex64.optional()
77
77
  }).superRefine((value,ctx) => {
78
78
  if (value.status === 'failed') { requireFields(value,ctx,['error']); return; }
@@ -98,9 +98,12 @@ export const autonomousGoalRunOutputSchema = z.strictObject({
98
98
  if (value.status === 'input_required') requireFields(value,ctx,['planner_request']);
99
99
  });
100
100
  export const autonomousGoalStatusOutputSchema = statusContract({
101
- statuses:['ok','failed'], success:['ok'], required:['goal_id','goal_sha256','title','root_id','journal_verified',...Object.keys(derivedShape)],
101
+ statuses:['ok','failed'], success:['ok'], required:['goal_id','goal_sha256','title','root_id','journal_verified',
102
+ 'run_busy','run_owner_pid','run_lock_created_at_utc',...Object.keys(derivedShape)],
102
103
  shape:{ goal_id:goalId.optional(), goal_sha256:hex64.optional(), title:z.string().optional(), root_id:z.string().optional(),
103
- journal_verified:z.literal(true).optional(), loop:publicLoopSchema.optional(), ...runShape }
104
+ journal_verified:z.literal(true).optional(), run_busy:z.boolean().optional(),
105
+ run_owner_pid:z.number().int().min(1).nullable().optional(),
106
+ run_lock_created_at_utc:z.string().nullable().optional(), loop:publicLoopSchema.optional(), ...runShape }
104
107
  });
105
108
  export const autonomousGoalEventsOutputSchema = statusContract({
106
109
  statuses:['ok','failed'], success:['ok'], required:['goal_id','journal_verified','journal_head_sha256','events'],
@@ -89,10 +89,45 @@ const r34PatchOperationSchema = z.discriminatedUnion('kind',[
89
89
  expected_replacements:z.number().int().min(1).max(64).default(1)}),
90
90
  z.strictObject({kind:z.literal('delete'),path:relPath,expected_sha256:z.string().regex(HEX64)})
91
91
  ]);
92
+ const plannerCursor=z.string().max(4096).nullable().default(null);
93
+ const plannerFiles=z.array(z.strictObject({path:relPath,encoding:z.enum(['utf8','base64']).default('utf8')})).min(1).max(32);
94
+ const plannerSemanticPosition={path:relPath,line:z.number().int().min(0),column:z.number().int().min(0)};
95
+ const r36TypedActionSchemas=[
96
+ z.strictObject({kind:z.literal('search'),path:relPath.default('.'),target:z.enum(['content','path']).default('content'),mode:z.enum(['literal','regex']).default('literal'),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_file_bytes:z.number().int().min(1).max(4194304).default(262144),max_scan_bytes:z.number().int().min(1).max(67108864).default(4194304),page_size:z.number().int().min(1).max(500).default(100),cursor:plannerCursor}),
97
+ z.strictObject({kind:z.literal('stat'),path:relPath.default('.'),hash:z.boolean().default(false)}),
98
+ z.strictObject({kind:z.literal('multi_read'),files:plannerFiles,max_total_bytes:z.number().int().min(1).max(2097152).default(1048576)}),
99
+ z.strictObject({kind:z.literal('semantic_outline'),path:relPath,max_symbols:z.number().int().min(1).max(500).default(200)}),
100
+ z.strictObject({kind:z.literal('semantic_definition'),...plannerSemanticPosition,max_results:z.number().int().min(1).max(200).default(50)}),
101
+ z.strictObject({kind:z.literal('semantic_references'),...plannerSemanticPosition,max_results:z.number().int().min(1).max(500).default(200)}),
102
+ z.strictObject({kind:z.literal('semantic_diagnostics'),path:relPath,max_results:z.number().int().min(1).max(500).default(200)}),
103
+ z.strictObject({kind:z.literal('semantic_implementations'),...plannerSemanticPosition,max_results:z.number().int().min(1).max(500).default(200)}),
104
+ z.strictObject({kind:z.literal('semantic_rename_preview'),...plannerSemanticPosition,new_name:z.string().regex(/^[A-Za-z_$][A-Za-z0-9_$]{0,127}$/)}),
105
+ z.strictObject({kind:z.literal('native_diff_apply'),diff_id:z.string().regex(HEX64),expected_operation_count:z.number().int().min(1).max(32)}),
106
+ z.strictObject({kind:z.literal('native_diff_verify'),diff_id:z.string().regex(HEX64)}),
107
+ z.strictObject({kind:z.literal('process_start'),profile_id:z.string().regex(ID),cwd:relPath.default('.'),args:z.array(z.string().max(2048)).max(64).default([])}),
108
+ z.strictObject({kind:z.literal('process_read'),session_id:z.string().regex(HEX64),offset:z.number().int().min(0).default(0),max_bytes:z.number().int().min(1).max(262144).default(65536)}),
109
+ z.strictObject({kind:z.literal('process_status'),session_id:z.string().regex(HEX64)}),
110
+ z.strictObject({kind:z.literal('process_list')}),
111
+ z.strictObject({kind:z.literal('process_action'),session_id:z.string().regex(HEX64),action_id:z.string().regex(ID)}),
112
+ z.strictObject({kind:z.literal('process_terminate'),session_id:z.string().regex(HEX64)}),
113
+ z.strictObject({kind:z.literal('machine_fs_stat'),path:relPath.default('.'),hash:z.boolean().default(false)}),
114
+ z.strictObject({kind:z.literal('machine_fs_list'),path:relPath.default('.'),cursor:plannerCursor,limit:z.number().int().min(1).max(1000).default(100),hash_files:z.boolean().default(false)}),
115
+ z.strictObject({kind:z.literal('machine_fs_read'),path:relPath,offset:z.number().int().min(0).default(0),max_bytes:z.number().int().min(1).max(4194304).default(65536),hash_file:z.boolean().default(false)}),
116
+ z.strictObject({kind:z.literal('machine_fs_mkdir'),path:relPath}),
117
+ z.strictObject({kind:z.literal('machine_fs_move'),source_path:relPath,destination_path:relPath,expected_source_identity:z.string().regex(HEX64)}),
118
+ z.strictObject({kind:z.literal('machine_fs_delete'),path:relPath,expected_source_identity:z.string().regex(HEX64)}),
119
+ z.strictObject({kind:z.literal('observation_search_start'),path:relPath.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(67108864).default(4194304),max_file_bytes:z.number().int().min(1).max(4194304).default(262144)}),
120
+ z.strictObject({kind:z.literal('observation_search_status'),search_id:z.string().regex(HEX64)}),
121
+ z.strictObject({kind:z.literal('observation_search_page'),search_id:z.string().regex(HEX64),cursor:plannerCursor,limit:z.number().int().min(1).max(500).default(100)}),
122
+ z.strictObject({kind:z.literal('observation_search_cancel'),search_id:z.string().regex(HEX64)}),
123
+ z.strictObject({kind:z.literal('observation_process_list'),include_external:z.boolean().default(false),cursor:plannerCursor,limit:z.number().int().min(1).max(256).default(100)}),
124
+ z.strictObject({kind:z.literal('observation_system_status')})
125
+ ];
92
126
  const r34ActionSchema = z.discriminatedUnion('kind',[
93
127
  z.strictObject({kind:z.literal('patch'),operations:z.array(r34PatchOperationSchema).min(1).max(32)}),
94
128
  z.strictObject({kind:z.literal('run_profile'),profile_id:z.string().regex(ID)}),
95
- z.strictObject({kind:z.literal('delegate'),operation:z.record(z.string(),z.json())})
129
+ z.strictObject({kind:z.literal('delegate'),operation:z.record(z.string(),z.json())}),
130
+ ...r36TypedActionSchemas
96
131
  ]);
97
132
  const r34ReadSchema = z.strictObject({
98
133
  path:relPath,
@@ -119,6 +119,27 @@ function normalizeDelegatedOperation(raw) {
119
119
  }
120
120
  throw new Error('planner delegated operation kind invalid');
121
121
  }
122
+
123
+ function legacyDelegatedToTyped(operation) {
124
+ if (operation.kind === 'machine_stat') return { kind:'machine_fs_stat', path:operation.path, hash:operation.hash };
125
+ if (operation.kind === 'machine_list') return { kind:'machine_fs_list', path:operation.path, cursor:operation.cursor, limit:operation.limit, hash_files:operation.hash_files };
126
+ if (operation.kind === 'machine_read') return { kind:'machine_fs_read', path:operation.path, offset:operation.offset, max_bytes:operation.max_bytes, hash_file:operation.hash };
127
+ return operation;
128
+ }
129
+ function validateR36TypedAction(action) {
130
+ const pathFields=[];
131
+ if (typeof action.path === 'string' && action.path !== '.') pathFields.push(action.path);
132
+ if (typeof action.cwd === 'string' && action.cwd !== '.') pathFields.push(action.cwd);
133
+ if (typeof action.source_path === 'string') pathFields.push(action.source_path);
134
+ if (typeof action.destination_path === 'string') pathFields.push(action.destination_path);
135
+ for (const item of action.files ?? []) if (typeof item?.path === 'string') pathFields.push(item.path);
136
+ for (const candidate of pathFields) validatePortableRelativePath(candidate);
137
+ return action;
138
+ }
139
+ function normalizeR36TypedAction(action) {
140
+ if (action.kind === 'delegate') return validateR36TypedAction(legacyDelegatedToTyped(normalizeDelegatedOperation(action.operation)));
141
+ return validateR36TypedAction(action);
142
+ }
122
143
  function normalizePlan(raw) {
123
144
  strictKeys(raw, ['title','reason','steps'], 'planner plan');
124
145
  const title = text(raw.title, 'planner plan title', 160, 1);
@@ -226,9 +247,9 @@ export function parseR34PlannerDecision(rawText, policy) {
226
247
  return decision;
227
248
  }
228
249
  if (decision.action.kind === 'delegate') {
229
- return { ...decision, action:{ kind:'delegate', operation:normalizeDelegatedOperation(decision.action.operation) } };
250
+ return { ...decision, action:normalizeR36TypedAction(decision.action) };
230
251
  }
231
- throw new Error('R34 planner authority or unsupported action');
252
+ return { ...decision, action:normalizeR36TypedAction(decision.action) };
232
253
  }
233
254
  if (decision.kind === 'step_complete') return decision;
234
255
  if (decision.kind === 'replan') {
@@ -312,7 +333,8 @@ export function buildPlannerPrompt({ goal, policy, view }) {
312
333
  contexts:view.contexts ?? [],
313
334
  observations:view.observations ?? [],
314
335
  decisions:view.recent_decisions ?? [],
315
- projectMemory:view.project_memory ?? null
336
+ projectMemory:view.project_memory ?? null,
337
+ capabilities:view.capabilities ?? null
316
338
  });
317
339
  const stateJson = canonicalJson(state);
318
340
  return [