deadbyte-mcp 0.12.0 → 0.13.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 (55) hide show
  1. package/MANIFEST.SHA256 +54 -36
  2. package/R41-PARENT.json +15 -0
  3. package/README.txt +2 -2
  4. package/bin/appcontainer-stage.obj +0 -0
  5. package/bin/bootstrap-advapi32.obj +0 -0
  6. package/bin/bootstrap-exitcode.obj +0 -0
  7. package/bin/bootstrap-kernel32.obj +0 -0
  8. package/bin/child-control-probe.obj +0 -0
  9. package/bin/child-control-stage.obj +0 -0
  10. package/bin/contained-reverse-worker.obj +0 -0
  11. package/bin/contained-transform-worker.obj +0 -0
  12. package/bin/containment-probe.obj +0 -0
  13. package/bin/deadbyte-contain.obj +0 -0
  14. package/bin/deadbyte-exec.obj +0 -0
  15. package/bin/deadbyte-process-host.obj +0 -0
  16. package/bin/deadbyte-tunnel-host.obj +0 -0
  17. package/controller/README.TXT +1 -1
  18. package/controller/deadbyte-controller.ps1 +1 -1
  19. package/controller/deadbyte-desktop-policy.json +5 -5
  20. package/controller/deadbyte-process-policy.json +4 -4
  21. package/docs/ARCHITECTURE.md +1 -1
  22. package/docs/superpowers/specs/2026-09-20-r41-deterministic-memory-design.md +132 -0
  23. package/package.json +8 -6
  24. package/proof/CONTAINMENT-BUILD.txt +6 -6
  25. package/scripts/build-containment.ps1 +24 -14
  26. package/scripts/build-desktop-r40.ps1 +15 -9
  27. package/scripts/deferred-slot-operation-r41.mjs +127 -0
  28. package/scripts/final-closure-r41.mjs +116 -0
  29. package/scripts/final-closure-verify-r41.mjs +215 -0
  30. package/scripts/gate-windows-r41.ps1 +48 -0
  31. package/scripts/init-desktop-policy-r40.ps1 +10 -4
  32. package/scripts/release-parity-r41.mjs +221 -0
  33. package/scripts/release-parity-tests-r41.ps1 +9 -0
  34. package/scripts/verify-memory-r41.mjs +88 -0
  35. package/scripts/verify-r41-parent.mjs +61 -0
  36. package/scripts/windows-gate-evidence-r41.mjs +53 -0
  37. package/src/autonomous-context-engine.mjs +2 -1
  38. package/src/autonomous-planner.mjs +2 -0
  39. package/src/autonomous-runtime.mjs +28 -9
  40. package/src/mcp-server.mjs +14 -1
  41. package/src/memory-r41.mjs +692 -0
  42. package/src/version.mjs +1 -1
  43. package/test/cli-entrypoint.test.mjs +1 -1
  44. package/test/controller-desktop-r40.test.mjs +2 -1
  45. package/test/core.test.mjs +1 -1
  46. package/test/helpers/autonomous-r34-fixture.mjs +3 -3
  47. package/test/memory-autonomous-integration-r41.test.mjs +31 -0
  48. package/test/memory-history-r41.test.mjs +126 -0
  49. package/test/memory-projections-r41.test.mjs +92 -0
  50. package/test/memory-retrieval-r41.test.mjs +124 -0
  51. package/test/memory-snapshot-r41.test.mjs +106 -0
  52. package/test/r33-closeout-regression.test.mjs +7 -7
  53. package/test/r33-finalization.test.mjs +4 -4
  54. package/test/r41-finalization.test.mjs +38 -0
  55. package/test/release-version.test.mjs +14 -13
@@ -0,0 +1,692 @@
1
+ import { createHash, randomBytes, sign as cryptoSign, verify as cryptoVerify } from 'node:crypto';
2
+ import { mkdir, open, readFile, readdir, rename, rm } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ import { canonicalJson } from './canonical-json.mjs';
5
+
6
+ export const MEMORY_STATE_SCHEMA='deadbyte.memory-state.v1';
7
+ export const MEMORY_SNAPSHOT_SCHEMA='deadbyte.memory-snapshot.v1';
8
+ const EVENT_SCHEMA='deadbyte.autonomous-event.v1';
9
+ const EVENT_DOMAIN=Buffer.from('DEADBYTE-AUTONOMOUS-EVENT-V1\0');
10
+ const GOAL_DOMAIN=Buffer.from('DEADBYTE-AUTONOMOUS-GOAL-V1\0');
11
+ const SNAPSHOT_DOMAIN=Buffer.from('DEADBYTE-MEMORY-SNAPSHOT-V1\0');
12
+ const HEX64=/^[0-9a-f]{64}$/;
13
+ const ZERO='0'.repeat(64);
14
+ const shaBytes=bytes=>createHash('sha256').update(bytes).digest('hex');
15
+ const sha=value=>shaBytes(Buffer.from(canonicalJson(value),'utf8'));
16
+
17
+ function insist(ok,message){if(!ok)throw new Error(message);}
18
+ function object(value,label){insist(value&&typeof value==='object'&&!Array.isArray(value),`${label} invalid`);return value;}
19
+ function hex(value,label){insist(typeof value==='string'&&HEX64.test(value),`${label} invalid`);return value;}
20
+ function canonicalTime(value,label){
21
+ insist(typeof value==='string'&&value.length>=20&&value.length<=64,`${label} invalid`);
22
+ const time=Date.parse(value);insist(Number.isFinite(time),`${label} invalid`);return new Date(time).toISOString();
23
+ }
24
+ function uniqSorted(values){return [...new Set(values.filter(value=>typeof value==='string'&&value.length>0))].sort((a,b)=>a.localeCompare(b,'en'));}
25
+ function reference(event){return Object.freeze({goal_id:event.goal_id,seq:event.seq,event_sha256:event.event_sha256,type:event.type});}
26
+
27
+ export function verifyMemoryGoal(goal,{publicKey,keyId,expectedGoalId=null}={}){
28
+ object(goal,'memory goal envelope');
29
+ const {attestation,...body}=goal;
30
+ const {goal_sha256:claimed,goal_id:goalId,...identity}=body;
31
+ hex(goalId,'memory goal_id');hex(claimed,'memory goal_sha256');
32
+ if(expectedGoalId!==null)insist(goalId===expectedGoalId,'memory goal directory identity mismatch');
33
+ insist(sha(identity)===claimed,'memory goal hash mismatch');
34
+ insist(attestation?.algorithm==='ed25519'&&attestation.key_id===keyId,'memory goal attestation mismatch');
35
+ const signature=Buffer.from(attestation.signature_base64??'','base64');
36
+ insist(signature.length===64&&signature.toString('base64')===attestation.signature_base64,'memory goal signature encoding mismatch');
37
+ insist(cryptoVerify(null,Buffer.concat([GOAL_DOMAIN,Buffer.from(canonicalJson(body),'utf8')]),publicKey,signature),'memory goal signature invalid');
38
+ return goal;
39
+ }
40
+
41
+ export function verifyMemoryJournal(events,{goalId,publicKey,keyId}={}){
42
+ insist(Array.isArray(events),'memory journal events invalid');
43
+ hex(goalId,'memory journal goal_id');
44
+ insist(publicKey,'memory journal public key missing');
45
+ insist(typeof keyId==='string'&&keyId.length>=1&&keyId.length<=128,'memory journal key id invalid');
46
+ let previous=ZERO;
47
+ for(let index=0;index<events.length;index+=1){
48
+ const event=object(events[index],`memory event ${index+1}`);
49
+ const {attestation,...signed}=event;
50
+ const {event_sha256:claimed,...body}=signed;
51
+ insist(body.schema===EVENT_SCHEMA,`memory event ${index+1} schema mismatch`);
52
+ insist(body.goal_id===goalId,`memory event ${index+1} goal mismatch`);
53
+ insist(body.seq===index+1,`memory event ${index+1} sequence mismatch`);
54
+ insist(body.prev_sha256===previous,`memory event ${index+1} predecessor mismatch`);
55
+ canonicalTime(body.created_at_utc,`memory event ${index+1} created_at_utc`);
56
+ insist(typeof body.type==='string'&&body.type.length>=1&&body.type.length<=128,`memory event ${index+1} type invalid`);
57
+ object(body.payload??{},`memory event ${index+1} payload`);
58
+ hex(claimed,`memory event ${index+1} hash`);
59
+ insist(sha(body)===claimed,`memory event ${index+1} hash mismatch`);
60
+ insist(attestation?.algorithm==='ed25519'&&attestation.key_id===keyId,`memory event ${index+1} attestation mismatch`);
61
+ const signature=Buffer.from(attestation.signature_base64??'','base64');
62
+ insist(signature.length===64&&signature.toString('base64')===attestation.signature_base64,`memory event ${index+1} signature encoding mismatch`);
63
+ insist(cryptoVerify(null,Buffer.concat([EVENT_DOMAIN,Buffer.from(canonicalJson(signed),'utf8')]),publicKey,signature),`memory event ${index+1} signature invalid`);
64
+ previous=claimed;
65
+ }
66
+ return Object.freeze({ok:true,event_count:events.length,journal_head_sha256:previous});
67
+ }
68
+
69
+ function initialState(goal){
70
+ object(goal,'memory goal');
71
+ const goalId=hex(goal.goal_id,'memory goal_id');
72
+ return {
73
+ schema:MEMORY_STATE_SCHEMA,goal_id:goalId,goal_sha256:hex(goal.goal_sha256,'memory goal_sha256'),
74
+ last_event_seq:0,journal_head_sha256:ZERO,status:'open',event_refs:[],receipt_refs:[],artifact_refs:[],
75
+ touched_files:[],failed_profiles:[],passed_profiles:[],planner_round:0,last_decision:null
76
+ };
77
+ }
78
+
79
+ function reduceEvent(state,event){
80
+ insist(event.seq===state.last_event_seq+1,'memory reducer sequence mismatch');
81
+ insist(event.prev_sha256===state.journal_head_sha256,'memory reducer predecessor mismatch');
82
+ const payload=event.payload??{};
83
+ state.last_event_seq=event.seq;
84
+ state.journal_head_sha256=event.event_sha256;
85
+ state.event_refs.push(reference(event));
86
+ for(const [key,value] of Object.entries(payload)){
87
+ if((key==='receipt_sha256'||key.endsWith('_receipt_sha256'))&&HEX64.test(value??'')) state.receipt_refs.push(value);
88
+ if((key==='artifact_sha256'||key.endsWith('_artifact_sha256')||key==='output_sha256')&&HEX64.test(value??'')) state.artifact_refs.push(value);
89
+ }
90
+ if(event.type==='planner_decision'){
91
+ state.planner_round=Math.max(state.planner_round,Number.isInteger(payload.planner_round)?payload.planner_round:state.planner_round);
92
+ state.last_decision={event_ref:reference(event),decision:structuredClone(payload.decision??null)};
93
+ }
94
+ if(event.type==='native_diff_committed') for(const file of payload.paths??[]) if(typeof file==='string'&&file.length>0) state.touched_files.push(file);
95
+ if(event.type==='profile_completed'&&typeof payload.profile_id==='string'){
96
+ if(payload.passed===true){state.passed_profiles.push(payload.profile_id);state.failed_profiles=state.failed_profiles.filter(id=>id!==payload.profile_id);}
97
+ else if(payload.passed===false&&!state.failed_profiles.includes(payload.profile_id))state.failed_profiles.push(payload.profile_id);
98
+ }
99
+ if(event.type==='release_completed')state.status='succeeded';
100
+ else if(event.type==='goal_cancelled')state.status='cancelled';
101
+ else if(event.type==='goal_failed')state.status='failed';
102
+ else if(event.type==='goal_paused'&&state.status==='open')state.status='paused';
103
+ else if(event.type==='goal_resumed'&&state.status==='paused')state.status='open';
104
+ state.receipt_refs=uniqSorted(state.receipt_refs);
105
+ state.artifact_refs=uniqSorted(state.artifact_refs);
106
+ state.touched_files=uniqSorted(state.touched_files);
107
+ state.failed_profiles=uniqSorted(state.failed_profiles);
108
+ state.passed_profiles=uniqSorted(state.passed_profiles);
109
+ return state;
110
+ }
111
+
112
+ function validateState(state,goal){
113
+ object(state,'memory state');
114
+ insist(state.schema===MEMORY_STATE_SCHEMA,'memory state schema mismatch');
115
+ insist(state.goal_id===goal.goal_id&&state.goal_sha256===goal.goal_sha256,'memory state goal mismatch');
116
+ insist(Number.isInteger(state.last_event_seq)&&state.last_event_seq>=0,'memory state sequence invalid');
117
+ hex(state.journal_head_sha256,'memory state journal head');
118
+ insist(Array.isArray(state.event_refs)&&state.event_refs.length===state.last_event_seq,'memory state event references invalid');
119
+ return state;
120
+ }
121
+
122
+ export function deriveMemoryState(goal,events,{publicKey,keyId}={}){
123
+ verifyMemoryJournal(events,{goalId:goal?.goal_id,publicKey,keyId});
124
+ const state=initialState(goal);
125
+ for(const event of events)reduceEvent(state,event);
126
+ return Object.freeze(structuredClone(state));
127
+ }
128
+
129
+ function snapshotCore(snapshot){
130
+ const {attestation:_attestation,snapshot_sha256:_snapshotSha,...core}=snapshot??{};
131
+ return core;
132
+ }
133
+
134
+ export function createMemorySnapshot({goal,events,snapshotSequence,sourceReleaseManifest,writerVersion,createdAtUtc,privateKey,publicKey,keyId}={}){
135
+ insist(Number.isInteger(snapshotSequence)&&snapshotSequence>=1,'memory snapshot sequence invalid');
136
+ hex(sourceReleaseManifest,'memory snapshot source release manifest');
137
+ insist(typeof writerVersion==='string'&&/^[0-9]+\.[0-9]+\.[0-9]+(?:-[A-Za-z0-9.-]+)?$/.test(writerVersion),'memory snapshot writer version invalid');
138
+ insist(privateKey&&publicKey,'memory snapshot signing keys missing');
139
+ insist(typeof keyId==='string'&&keyId.length>=1&&keyId.length<=128,'memory snapshot key id invalid');
140
+ const state=deriveMemoryState(goal,events,{publicKey,keyId});
141
+ const core={schema:MEMORY_SNAPSHOT_SCHEMA,schema_version:1,snapshot_sequence:snapshotSequence,
142
+ goal_id:goal.goal_id,last_event_seq:state.last_event_seq,journal_prefix_hash:state.journal_head_sha256,
143
+ state:structuredClone(state),state_hash:sha(state),created_at_utc:canonicalTime(createdAtUtc,'memory snapshot created_at_utc'),
144
+ source_release_manifest:sourceReleaseManifest,writer_version:writerVersion};
145
+ const snapshot_sha256=sha(core);
146
+ const signed={...core,snapshot_sha256};
147
+ const signature_base64=cryptoSign(null,Buffer.concat([SNAPSHOT_DOMAIN,Buffer.from(canonicalJson(signed),'utf8')]),privateKey).toString('base64');
148
+ return Object.freeze({...signed,attestation:Object.freeze({algorithm:'ed25519',key_id:keyId,signature_base64})});
149
+ }
150
+
151
+ export function verifyMemorySnapshot(snapshot,{goal,events,publicKey,keyId,sourceReleaseManifest}={}){
152
+ try{
153
+ object(snapshot,'memory snapshot');object(goal,'memory snapshot goal');
154
+ insist(snapshot.schema===MEMORY_SNAPSHOT_SCHEMA&&snapshot.schema_version===1,'memory snapshot schema mismatch');
155
+ insist(Number.isInteger(snapshot.snapshot_sequence)&&snapshot.snapshot_sequence>=1,'memory snapshot sequence invalid');
156
+ insist(snapshot.goal_id===goal.goal_id,'memory snapshot goal mismatch');
157
+ insist(Number.isInteger(snapshot.last_event_seq)&&snapshot.last_event_seq>=0&&snapshot.last_event_seq<=events.length,'memory snapshot event sequence invalid');
158
+ hex(snapshot.journal_prefix_hash,'memory snapshot journal prefix');
159
+ hex(snapshot.state_hash,'memory snapshot state hash');hex(snapshot.snapshot_sha256,'memory snapshot hash');
160
+ canonicalTime(snapshot.created_at_utc,'memory snapshot created_at_utc');
161
+ insist(snapshot.source_release_manifest===sourceReleaseManifest,'memory snapshot release manifest mismatch');
162
+ insist(typeof snapshot.writer_version==='string'&&snapshot.writer_version.length>=1,'memory snapshot writer version invalid');
163
+ validateState(snapshot.state,goal);
164
+ insist(snapshot.state.last_event_seq===snapshot.last_event_seq&&snapshot.state.journal_head_sha256===snapshot.journal_prefix_hash,'memory snapshot state binding mismatch');
165
+ insist(sha(snapshot.state)===snapshot.state_hash,'memory snapshot state hash mismatch');
166
+ const core=snapshotCore(snapshot);insist(sha(core)===snapshot.snapshot_sha256,'memory snapshot self hash mismatch');
167
+ insist(snapshot.attestation?.algorithm==='ed25519'&&snapshot.attestation.key_id===keyId,'memory snapshot attestation mismatch');
168
+ const signature=Buffer.from(snapshot.attestation.signature_base64??'','base64');
169
+ insist(signature.length===64&&signature.toString('base64')===snapshot.attestation.signature_base64,'memory snapshot signature encoding mismatch');
170
+ insist(cryptoVerify(null,Buffer.concat([SNAPSHOT_DOMAIN,Buffer.from(canonicalJson({...core,snapshot_sha256:snapshot.snapshot_sha256}),'utf8')]),publicKey,signature),'memory snapshot signature invalid');
171
+ verifyMemoryJournal(events,{goalId:goal.goal_id,publicKey,keyId});
172
+ const prefix=events.slice(0,snapshot.last_event_seq);
173
+ const expectedHead=prefix.at(-1)?.event_sha256??ZERO;
174
+ insist(expectedHead===snapshot.journal_prefix_hash,'memory snapshot journal prefix mismatch');
175
+ const expectedState=deriveMemoryState(goal,prefix,{publicKey,keyId});
176
+ insist(canonicalJson(expectedState)===canonicalJson(snapshot.state),'memory snapshot derived state mismatch');
177
+ return Object.freeze({ok:true,snapshot_sha256:snapshot.snapshot_sha256,state_hash:snapshot.state_hash,last_event_seq:snapshot.last_event_seq});
178
+ }catch(error){return Object.freeze({ok:false,reason:String(error?.message??error)});}
179
+ }
180
+
181
+ export function replayFromMemorySnapshot(snapshot,{goal,events,publicKey,keyId,sourceReleaseManifest}={}){
182
+ const proof=verifyMemorySnapshot(snapshot,{goal,events,publicKey,keyId,sourceReleaseManifest});
183
+ insist(proof.ok,`memory snapshot verification failed: ${proof.reason}`);
184
+ const state=structuredClone(snapshot.state);
185
+ for(const event of events.slice(snapshot.last_event_seq))reduceEvent(state,event);
186
+ return Object.freeze(state);
187
+ }
188
+
189
+ export async function writeMemorySnapshot(file,snapshot){
190
+ insist(typeof file==='string'&&path.isAbsolute(file),'memory snapshot path must be absolute');
191
+ insist(snapshot?.schema===MEMORY_SNAPSHOT_SCHEMA,'memory snapshot invalid');
192
+ await mkdir(path.dirname(file),{recursive:true});
193
+ const temp=`${file}.tmp-${process.pid}-${randomBytes(4).toString('hex')}`;
194
+ const handle=await open(temp,'wx',0o600);
195
+ try{await handle.writeFile(`${canonicalJson(snapshot)}\n`,'utf8');await handle.sync();}finally{await handle.close();}
196
+ try{await rename(temp,file);}catch(error){await rm(temp,{force:true}).catch(()=>{});throw error;}
197
+ return Object.freeze({path:file,snapshot_sha256:snapshot.snapshot_sha256,state_hash:snapshot.state_hash});
198
+ }
199
+
200
+ export async function loadMemoryState({snapshotPath,goal,events,publicKey,keyId,sourceReleaseManifest}={}){
201
+ let snapshot;
202
+ try{snapshot=JSON.parse(await readFile(snapshotPath,'utf8'));}
203
+ catch(error){
204
+ const reason=error?.code==='ENOENT'?'missing':`snapshot read failed: ${String(error?.message??error)}`;
205
+ return Object.freeze({mode:'full-replay',snapshot_reason:reason,state:deriveMemoryState(goal,events,{publicKey,keyId})});
206
+ }
207
+ const proof=verifyMemorySnapshot(snapshot,{goal,events,publicKey,keyId,sourceReleaseManifest});
208
+ if(!proof.ok)return Object.freeze({mode:'full-replay',snapshot_reason:proof.reason,state:deriveMemoryState(goal,events,{publicKey,keyId})});
209
+ return Object.freeze({mode:'snapshot-suffix',snapshot_reason:null,snapshot_sha256:snapshot.snapshot_sha256,
210
+ state:replayFromMemorySnapshot(snapshot,{goal,events,publicKey,keyId,sourceReleaseManifest})});
211
+ }
212
+
213
+ function collectNamedHashes(value,matcher,{depth=0,nodes={count:0},out=[]}={}){
214
+ if(depth>10||nodes.count++>10000)return out;
215
+ if(Array.isArray(value)){for(const item of value)collectNamedHashes(item,matcher,{depth:depth+1,nodes,out});return out;}
216
+ if(!value||typeof value!=='object')return out;
217
+ for(const [name,item] of Object.entries(value)){
218
+ if(matcher(name)&&HEX64.test(item??''))out.push(item);
219
+ else collectNamedHashes(item,matcher,{depth:depth+1,nodes,out});
220
+ }
221
+ return out;
222
+ }
223
+ function receiptHashes(payload){return uniqSorted(collectNamedHashes(payload,name=>name==='receipt_sha256'||name.endsWith('_receipt_sha256')));}
224
+ function artifactHashes(payload){return uniqSorted(collectNamedHashes(payload,name=>name==='artifact_sha256'||name.endsWith('_artifact_sha256')||name==='output_sha256'));}
225
+ function referenced(type,payload,event){return Object.freeze({kind:type,event_ref:reference(event),...payload});}
226
+ function validateProjectionInputs(goal,events,options){
227
+ object(goal,'memory projection goal');
228
+ verifyMemoryJournal(events,{goalId:goal.goal_id,publicKey:options?.publicKey,keyId:options?.keyId});
229
+ }
230
+ function projectionProof(derive,value,args,label){
231
+ try{
232
+ const expected=derive(args.goal,args.events,{publicKey:args.publicKey,keyId:args.keyId});
233
+ insist(canonicalJson(expected)===canonicalJson(value),`${label} does not match canonical journal projection`);
234
+ return Object.freeze({ok:true,memory_sha256:value.memory_sha256});
235
+ }catch(error){return Object.freeze({ok:false,reason:String(error?.message??error)});}
236
+ }
237
+
238
+ export function deriveEpisodicMemory(goal,events,{publicKey,keyId}={}){
239
+ validateProjectionInputs(goal,events,{publicKey,keyId});
240
+ const observations=[],decisions=[],actions=[],results=[],verification=[];
241
+ const receipts=[],artifacts=[];
242
+ for(const event of events){
243
+ const payload=event.payload??{};
244
+ receipts.push(...receiptHashes(payload));artifacts.push(...artifactHashes(payload));
245
+ if(event.type==='planner_decision')decisions.push(referenced('decision',{summary:String(payload.decision?.summary??''),action:String(payload.decision?.action??'')},event));
246
+ if(['inspect_completed','profile_completed','delegated_action_completed','desktop_observation','observation_completed'].includes(event.type))
247
+ observations.push(referenced('observation',{event_type:event.type},event));
248
+ if(['native_diff_committed','delegated_action_started','delegated_action_completed','patch_started','patch_committed'].includes(event.type))
249
+ actions.push(referenced('action',{event_type:event.type},event));
250
+ if(['profile_completed','delegated_action_completed','native_diff_committed','goal_failed','release_completed'].includes(event.type))
251
+ results.push(referenced('result',{event_type:event.type,status:payload.passed===true?'passed':payload.passed===false?'failed':null},event));
252
+ if(event.type==='release_completed'||(event.type==='profile_completed'&&payload.passed===true))
253
+ verification.push(referenced('verification',{event_type:event.type},event));
254
+ }
255
+ const terminal=[...events].reverse().find(event=>['release_completed','goal_failed','goal_cancelled'].includes(event.type));
256
+ const outcome=terminal?.type==='release_completed'?'succeeded':terminal?.type==='goal_cancelled'?'cancelled':terminal?.type==='goal_failed'?'failed':'open';
257
+ const head=events.at(-1)?.event_sha256??ZERO;
258
+ const body={schema:'deadbyte.episode.v1',episode_id:sha({schema:'deadbyte.episode-id.v1',goal_id:goal.goal_id,journal_head_sha256:head}),
259
+ goal:{goal_id:goal.goal_id,title:String(goal.title??''),goal:String(goal.goal??''),acceptance:String(goal.acceptance??'')},
260
+ observations,decisions,actions,results,verification,outcome,
261
+ event_range:{first_seq:events.length?1:0,last_seq:events.length,journal_head_sha256:head},
262
+ artifact_refs:uniqSorted(artifacts),receipt_refs:uniqSorted(receipts),
263
+ created_at_utc:events[0]?.created_at_utc??null,closed_at_utc:terminal?.created_at_utc??null};
264
+ return Object.freeze({...body,memory_sha256:sha(body)});
265
+ }
266
+
267
+ export function verifyEpisode(episode,{goal,events,publicKey,keyId}={}){
268
+ return projectionProof(deriveEpisodicMemory,episode,{goal,events,publicKey,keyId},'episode');
269
+ }
270
+
271
+ function validateDecisionEdges(decisions){
272
+ const byId=new Map(decisions.map(item=>[item.decision_id,item]));
273
+ insist(byId.size===decisions.length,'decision memory duplicate id');
274
+ for(const item of decisions){
275
+ if(item.supersedes===null)continue;
276
+ insist(byId.has(item.supersedes),'decision supersedes missing target');
277
+ insist(item.supersedes!==item.decision_id,'decision cannot supersede itself');
278
+ const previous=byId.get(item.supersedes);
279
+ insist(previous.superseded_by===null||previous.superseded_by===item.decision_id,'decision has ambiguous supersession');
280
+ previous.superseded_by=item.decision_id;previous.status='superseded';
281
+ }
282
+ for(const start of decisions){
283
+ const seen=new Set();let cursor=start;
284
+ while(cursor?.supersedes!==null){
285
+ insist(!seen.has(cursor.decision_id),'decision supersession cycle');seen.add(cursor.decision_id);cursor=byId.get(cursor.supersedes);
286
+ }
287
+ }
288
+ }
289
+
290
+ export function deriveDecisionMemory(goal,events,{publicKey,keyId}={}){
291
+ validateProjectionInputs(goal,events,{publicKey,keyId});
292
+ const decisions=[];
293
+ for(const event of events){
294
+ if(event.type!=='planner_decision'&&event.type!=='decision_recorded')continue;
295
+ const payload=event.payload??{};const value=payload.decision??payload;
296
+ const decisionId=sha({schema:'deadbyte.decision-id.v1',goal_id:goal.goal_id,event_sha256:event.event_sha256});
297
+ const supersedes=HEX64.test(value.supersedes??'')?value.supersedes:null;
298
+ decisions.push({decision_id:decisionId,scope:String(value.scope??goal.root_id??goal.goal_id),
299
+ decision:structuredClone(value),reason:String(value.reason??value.summary??''),
300
+ constraints:uniqSorted([goal.acceptance,...(Array.isArray(value.constraints)?value.constraints:[])]),status:'active',
301
+ supersedes,superseded_by:null,source_event_ids:[event.event_sha256],
302
+ receipt_refs:receiptHashes(payload),artifact_refs:artifactHashes(payload),created_at_utc:event.created_at_utc});
303
+ }
304
+ validateDecisionEdges(decisions);
305
+ const body={schema:'deadbyte.decision-memory.v1',goal_id:goal.goal_id,
306
+ journal_head_sha256:events.at(-1)?.event_sha256??ZERO,decisions};
307
+ return Object.freeze({...body,memory_sha256:sha(body)});
308
+ }
309
+
310
+ export function verifyDecisionMemory(memory,{goal,events,publicKey,keyId}={}){
311
+ return projectionProof(deriveDecisionMemory,memory,{goal,events,publicKey,keyId},'decision memory');
312
+ }
313
+
314
+ function incidentFingerprint(payload){
315
+ const text=(value,max=128)=>typeof value==='string'?value.slice(0,max):null;
316
+ const integer=value=>Number.isSafeInteger(value)?value:null;
317
+ const list=(value,max=32)=>uniqSorted(Array.isArray(value)?value.filter(item=>typeof item==='string').map(item=>item.slice(0,256)):[]).slice(0,max);
318
+ return {
319
+ tool:text(payload.tool),operation:text(payload.operation),platform:text(payload.platform),architecture:text(payload.architecture),
320
+ exit_code:integer(payload.exit_code),signal:text(payload.signal),timeout_state:text(payload.timeout_state),
321
+ diagnostic_codes:list(payload.diagnostic_codes),stderr_hash:HEX64.test(payload.stderr_sha256??'')?payload.stderr_sha256:null,
322
+ stdout_hash:HEX64.test(payload.stdout_sha256??'')?payload.stdout_sha256:null,
323
+ top_stack_frames:list(payload.top_stack_frames,16),compiler_identity:text(payload.compiler_identity,256),
324
+ runtime_identity:text(payload.runtime_identity,256),target:text(payload.target,256),profile_id:text(payload.profile_id),
325
+ symbols:list(payload.symbols),artifact_hashes:artifactHashes(payload),
326
+ environment_fingerprint:HEX64.test(payload.environment_fingerprint??'')?payload.environment_fingerprint:null
327
+ };
328
+ }
329
+ function failureEvent(event){
330
+ const payload=event.payload??{};
331
+ return (event.type==='profile_completed'&&payload.passed===false)||event.type==='goal_failed'||event.type.endsWith('_failed');
332
+ }
333
+
334
+ export function deriveIncidentMemory(goal,events,{publicKey,keyId}={}){
335
+ validateProjectionInputs(goal,events,{publicKey,keyId});
336
+ const incidents=[];
337
+ for(let index=0;index<events.length;index+=1){
338
+ const event=events[index];if(!failureEvent(event))continue;
339
+ const payload=event.payload??{};const fingerprint=incidentFingerprint(payload);
340
+ const fingerprintSha=sha({schema:'deadbyte.incident-fingerprint.v1',fingerprint});
341
+ const profile=typeof payload.profile_id==='string'?payload.profile_id:null;
342
+ let resolvedAt=-1;
343
+ if(profile)resolvedAt=events.findIndex((candidate,next)=>next>index&&candidate.type==='profile_completed'&&candidate.payload?.profile_id===profile&&candidate.payload?.passed===true);
344
+ const end=resolvedAt>=0?resolvedAt:events.length-1;
345
+ const window=events.slice(index,end+1);
346
+ const fixes=window.filter(candidate=>candidate.type==='native_diff_committed'||candidate.type==='repair_completed').map(reference);
347
+ const attempts=window.filter(candidate=>candidate.type==='planner_decision'||candidate.type==='profile_completed'||candidate.type==='native_diff_committed').map(reference);
348
+ const root=window.find(candidate=>candidate.type==='critic_classified'||candidate.type==='repair_started');
349
+ const body={incident_id:sha({schema:'deadbyte.incident-id.v1',goal_id:goal.goal_id,fingerprint_sha256:fingerprintSha,first_event_sha256:event.event_sha256}),
350
+ fingerprint_sha256:fingerprintSha,fingerprint,symptoms:[reference(event)],
351
+ root_cause:root?{event_ref:reference(root),detail:String(root.payload?.detail??root.payload?.hypothesis??'')}:null,
352
+ attempts,successful_fix:fixes,event_range:{first_seq:event.seq,last_seq:events[end]?.seq??event.seq},
353
+ receipt_refs:uniqSorted(window.flatMap(candidate=>receiptHashes(candidate.payload??{}))),
354
+ artifact_refs:uniqSorted(window.flatMap(candidate=>artifactHashes(candidate.payload??{}))),
355
+ status:resolvedAt>=0?'resolved':'open'};
356
+ incidents.push(body);
357
+ }
358
+ const body={schema:'deadbyte.incident-memory.v1',goal_id:goal.goal_id,
359
+ journal_head_sha256:events.at(-1)?.event_sha256??ZERO,incidents};
360
+ return Object.freeze({...body,memory_sha256:sha(body)});
361
+ }
362
+
363
+ export function verifyIncidentMemory(memory,{goal,events,publicKey,keyId}={}){
364
+ return projectionProof(deriveIncidentMemory,memory,{goal,events,publicKey,keyId},'incident memory');
365
+ }
366
+
367
+ export function buildMemoryCorpus({goal,events,publicKey,keyId,sourceReleaseManifest}={}){
368
+ hex(sourceReleaseManifest,'memory corpus source release manifest');
369
+ const state=deriveMemoryState(goal,events,{publicKey,keyId});
370
+ const episode=deriveEpisodicMemory(goal,events,{publicKey,keyId});
371
+ const decisions=deriveDecisionMemory(goal,events,{publicKey,keyId});
372
+ const incidents=deriveIncidentMemory(goal,events,{publicKey,keyId});
373
+ const body={schema:'deadbyte.memory-corpus.v1',source_release_manifest:sourceReleaseManifest,
374
+ goal_id:goal.goal_id,journal_head_sha256:state.journal_head_sha256,state,episode,decisions,incidents};
375
+ return Object.freeze({...body,memory_sha256:sha(body)});
376
+ }
377
+
378
+ export function buildMemoryArchive(corpora,{sourceReleaseManifest}={}){
379
+ insist(Array.isArray(corpora),'memory archive corpora invalid');
380
+ hex(sourceReleaseManifest,'memory archive source release manifest');
381
+ const ordered=[...corpora].sort((a,b)=>String(a?.goal_id).localeCompare(String(b?.goal_id),'en'));
382
+ const seen=new Set();
383
+ for(const corpus of ordered){
384
+ object(corpus,'memory archive corpus');hex(corpus.memory_sha256,'memory archive corpus hash');
385
+ insist(corpus.source_release_manifest===sourceReleaseManifest,'memory archive cross-release corpus rejected');
386
+ insist(!seen.has(corpus.goal_id),'memory archive duplicate goal');seen.add(corpus.goal_id);
387
+ }
388
+ const body={schema:'deadbyte.memory-archive.v1',source_release_manifest:sourceReleaseManifest,
389
+ corpus_refs:ordered.map(corpus=>({goal_id:corpus.goal_id,journal_head_sha256:corpus.journal_head_sha256,memory_sha256:corpus.memory_sha256})),
390
+ corpora:ordered.map(corpus=>structuredClone(corpus))};
391
+ return Object.freeze({...body,memory_sha256:sha(body)});
392
+ }
393
+
394
+ function validateCorpus(corpus,{goal,events,publicKey,keyId,sourceReleaseManifest}={}){
395
+ const expected=buildMemoryCorpus({goal,events,publicKey,keyId,sourceReleaseManifest});
396
+ insist(canonicalJson(expected)===canonicalJson(corpus),'memory corpus does not match canonical journal');
397
+ return expected;
398
+ }
399
+ function tokens(value){
400
+ return uniqSorted(String(value??'').toLowerCase().split(/[^a-z0-9_.\/-]+/).filter(token=>token.length>1)).slice(0,4096);
401
+ }
402
+ function addPosting(map,key,id){if(!key)return;const values=map.get(key)??new Set();values.add(id);map.set(key,values);}
403
+ function mapObject(map){return Object.fromEntries([...map.entries()].sort(([a],[b])=>a.localeCompare(b,'en')).map(([key,values])=>[key,[...values].sort((a,b)=>a.localeCompare(b,'en'))]));}
404
+ function sourceIds(record){
405
+ const ids=[];
406
+ const visit=value=>{
407
+ if(Array.isArray(value)){for(const item of value)visit(item);return;}
408
+ if(!value||typeof value!=='object')return;
409
+ if(HEX64.test(value.event_sha256??''))ids.push(value.event_sha256);
410
+ if(value.event_ref)visit(value.event_ref);
411
+ for(const [key,item] of Object.entries(value))if(key!=='event_ref'&&key!=='event_sha256')visit(item);
412
+ };
413
+ visit(record);return uniqSorted(ids);
414
+ }
415
+ function canonicalRecords(corpus){
416
+ const records=new Map();
417
+ if(corpus.schema==='deadbyte.memory-archive.v1'){
418
+ for(const child of corpus.corpora??[]){
419
+ for(const [id,value] of canonicalRecords(child)){
420
+ const existing=records.get(id);
421
+ insist(!existing||canonicalJson(existing)===canonicalJson(value),`memory archive record collision: ${id}`);
422
+ records.set(id,value);
423
+ }
424
+ }
425
+ return records;
426
+ }
427
+ records.set(corpus.episode.episode_id,{kind:'episode',record:corpus.episode});
428
+ for(const item of corpus.decisions.decisions)records.set(item.decision_id,{kind:'decision',record:item});
429
+ for(const item of corpus.incidents.incidents)records.set(item.incident_id,{kind:'incident',record:item});
430
+ for(const item of corpus.state.event_refs)records.set(item.event_sha256,{kind:'event',record:item});
431
+ for(const digest of uniqSorted([...corpus.state.artifact_refs,...corpus.episode.artifact_refs]))records.set(`artifact:${digest}`,{kind:'artifact',record:{artifact_sha256:digest}});
432
+ return records;
433
+ }
434
+
435
+ export function buildRetrievalIndex(corpus,{sourceReleaseManifest}={}){
436
+ object(corpus,'memory retrieval corpus');
437
+ hex(corpus.memory_sha256,'memory retrieval corpus hash');
438
+ insist(corpus.source_release_manifest===sourceReleaseManifest,'memory retrieval release manifest mismatch');
439
+ const tokenIndex=new Map(),symbolIndex=new Map(),artifactIndex=new Map(),incidentIndex=new Map(),decisionIndex=new Map();
440
+ const documents=[];
441
+ for(const [id,{kind,record}] of [...canonicalRecords(corpus).entries()].sort(([a],[b])=>a.localeCompare(b,'en'))){
442
+ const text=canonicalJson(record);const documentTokens=tokens(text);
443
+ const symbols=kind==='incident'?uniqSorted(record.fingerprint?.symbols??[]):[];
444
+ const artifacts=kind==='incident'?uniqSorted(record.artifact_refs??[]):kind==='episode'?uniqSorted(record.artifact_refs??[]):kind==='artifact'?[record.artifact_sha256]:[];
445
+ const source_event_ids=sourceIds(record);
446
+ const doc={id,kind,record_sha256:sha(record),source_event_ids,tokens:documentTokens,symbols,artifact_hashes:artifacts};
447
+ documents.push(doc);
448
+ for(const token of documentTokens)addPosting(tokenIndex,token,id);
449
+ for(const symbol of symbols)addPosting(symbolIndex,symbol,id);
450
+ for(const digest of artifacts)addPosting(artifactIndex,digest,id);
451
+ if(kind==='incident')addPosting(incidentIndex,record.fingerprint_sha256,id);
452
+ if(kind==='decision')addPosting(decisionIndex,record.scope,id);
453
+ }
454
+ const body={schema:'deadbyte.memory-index.v1',source_memory_sha256:corpus.memory_sha256,
455
+ source_release_manifest:sourceReleaseManifest,documents,
456
+ exact_ids:Object.fromEntries(documents.map((doc,index)=>[doc.id,index])),
457
+ token_index:mapObject(tokenIndex),symbol_index:mapObject(symbolIndex),artifact_index:mapObject(artifactIndex),
458
+ decision_index:mapObject(decisionIndex),incident_index:mapObject(incidentIndex)};
459
+ return Object.freeze({...body,index_sha256:sha(body)});
460
+ }
461
+
462
+ export function verifyRetrievalIndex(index,{corpus,sourceReleaseManifest}={}){
463
+ try{
464
+ object(index,'memory index');
465
+ insist(index.source_release_manifest===sourceReleaseManifest,'memory index release manifest mismatch');
466
+ insist(index.source_memory_sha256===corpus?.memory_sha256,'memory index source hash mismatch');
467
+ const expected=buildRetrievalIndex(corpus,{sourceReleaseManifest});
468
+ insist(canonicalJson(expected)===canonicalJson(index),'memory index projection mismatch');
469
+ return Object.freeze({ok:true,index_sha256:index.index_sha256,document_count:index.documents.length});
470
+ }catch(error){return Object.freeze({ok:false,reason:String(error?.message??error)});}
471
+ }
472
+ function posting(index,name,key){const values=index[name]?.[key];return Array.isArray(values)?values:[];}
473
+ export function queryMemoryIndex(index,{id=null,query=null,symbol=null,artifact_sha256=null,decision_scope=null,incident_fingerprint=null,limit=16}={}){
474
+ object(index,'memory query index');
475
+ insist(Number.isInteger(limit)&&limit>=1&&limit<=128,'memory query limit invalid');
476
+ const scores=new Map();const add=(candidate,score)=>scores.set(candidate,(scores.get(candidate)??0)+score);
477
+ if(typeof id==='string'&&Object.hasOwn(index.exact_ids??{},id))add(id,1000);
478
+ for(const token of tokens(query))for(const candidate of posting(index,'token_index',token))add(candidate,10);
479
+ if(typeof symbol==='string')for(const candidate of posting(index,'symbol_index',symbol))add(candidate,100);
480
+ if(HEX64.test(artifact_sha256??''))for(const candidate of posting(index,'artifact_index',artifact_sha256))add(candidate,100);
481
+ if(typeof decision_scope==='string')for(const candidate of posting(index,'decision_index',decision_scope))add(candidate,100);
482
+ if(HEX64.test(incident_fingerprint??''))for(const candidate of posting(index,'incident_index',incident_fingerprint))add(candidate,100);
483
+ const candidate_ids=[...scores.entries()].sort((a,b)=>b[1]-a[1]||a[0].localeCompare(b[0],'en')).slice(0,limit).map(([candidate])=>candidate);
484
+ return Object.freeze({schema:'deadbyte.memory-query.v1',index_sha256:index.index_sha256,candidate_ids});
485
+ }
486
+
487
+ function resolveCandidates(candidateIds,{corpus,index,sourceReleaseManifest}){
488
+ const proof=verifyRetrievalIndex(index,{corpus,sourceReleaseManifest});
489
+ insist(proof.ok,`memory canonical index invalid: ${proof.reason}`);
490
+ insist(Array.isArray(candidateIds)&&candidateIds.length<=128,'memory candidate ids invalid');
491
+ const records=canonicalRecords(corpus),seen=new Set(),resolved=[];
492
+ for(const id of candidateIds){
493
+ insist(typeof id==='string'&&!seen.has(id),'memory canonical candidate duplicate/invalid');seen.add(id);
494
+ const value=records.get(id);insist(value,`memory canonical candidate not found: ${id}`);
495
+ const doc=index.documents[index.exact_ids[id]];
496
+ insist(doc?.record_sha256===sha(value.record),'memory canonical candidate record hash mismatch');
497
+ resolved.push(structuredClone(value.record));
498
+ }
499
+ return resolved;
500
+ }
501
+
502
+ function safeAuthority(value){
503
+ const planes={};
504
+ for(const name of ['process','coding','autonomous','desktop','host']){
505
+ const item=value?.[name];if(!item||typeof item!=='object')continue;
506
+ planes[name]={armed:item.armed===true,reason:String(item.reason??'unknown').slice(0,128)};
507
+ }
508
+ return {observed:planes,authorizes_execution:false};
509
+ }
510
+ function incidentWithSources(item){return {...structuredClone(item),source_event_ids:sourceIds(item)};}
511
+ function decisionWithSources(item){return {...structuredClone(item),source_event_ids:uniqSorted(item.source_event_ids??[])};}
512
+
513
+ export function buildWorkingMemory({goal,events,corpus,index,publicKey,keyId,sourceReleaseManifest,byteBudget=65536,
514
+ currentPlan=null,currentFiles=[],currentSymbols=[],currentAuthority={},historicalArchive=null,historicalIndex=null}={}){
515
+ insist(Number.isInteger(byteBudget)&&byteBudget>=4096&&byteBudget<=4*1024*1024,'working memory byte budget invalid');
516
+ validateCorpus(corpus,{goal,events,publicKey,keyId,sourceReleaseManifest});
517
+ const indexProof=verifyRetrievalIndex(index,{corpus,sourceReleaseManifest});insist(indexProof.ok,`working memory index invalid: ${indexProof.reason}`);
518
+ const eventIds=new Set(events.map(event=>event.event_sha256));
519
+ const files=currentFiles.map(item=>{
520
+ object(item,'working memory file');hex(item.sha256,'working memory file hash');hex(item.source_event_sha256,'working memory file source event');
521
+ insist(eventIds.has(item.source_event_sha256),'working memory file source event missing');
522
+ return {path:String(item.path??''),sha256:item.sha256,source_event_sha256:item.source_event_sha256};
523
+ }).sort((a,b)=>a.path.localeCompare(b.path,'en'));
524
+ const queryText=[goal.title,goal.goal,goal.acceptance,...currentSymbols].filter(Boolean).join(' ');
525
+ const candidates=queryMemoryIndex(index,{query:queryText,limit:64}).candidate_ids;
526
+ const candidateSet=new Set(candidates);
527
+ const relevantDecisions=corpus.decisions.decisions.filter(item=>item.status==='active'||candidateSet.has(item.decision_id)).map(decisionWithSources);
528
+ const relevantIncidents=corpus.incidents.incidents.filter(item=>item.status==='open'||candidateSet.has(item.incident_id)).map(incidentWithSources);
529
+ let historical=[];let historicalArchiveSha256=null;let historicalIndexSha256=null;
530
+ if(historicalArchive!==null||historicalIndex!==null){
531
+ insist(historicalArchive?.schema==='deadbyte.memory-archive.v1','working memory historical archive invalid');
532
+ insist(historicalArchive.source_release_manifest===sourceReleaseManifest,'working memory historical archive release mismatch');
533
+ const rebuilt=buildMemoryArchive(historicalArchive.corpora,{sourceReleaseManifest});
534
+ insist(canonicalJson(rebuilt)===canonicalJson(historicalArchive),'working memory historical archive noncanonical');
535
+ const historyProof=verifyRetrievalIndex(historicalIndex,{corpus:historicalArchive,sourceReleaseManifest});
536
+ insist(historyProof.ok,`working memory historical index invalid: ${historyProof.reason}`);
537
+ const historyIds=queryMemoryIndex(historicalIndex,{query:queryText,limit:16}).candidate_ids;
538
+ historical=resolveCandidates(historyIds,{corpus:historicalArchive,index:historicalIndex,sourceReleaseManifest});
539
+ historicalArchiveSha256=historicalArchive.memory_sha256;historicalIndexSha256=historicalIndex.index_sha256;
540
+ }
541
+ const body={schema:'deadbyte.working-memory.v1',source_release_manifest:sourceReleaseManifest,
542
+ source_memory_sha256:corpus.memory_sha256,source_index_sha256:index.index_sha256,
543
+ journal_head_sha256:events.at(-1)?.event_sha256??ZERO,
544
+ current_goal:{goal_id:goal.goal_id,title:String(goal.title??''),goal:String(goal.goal??''),acceptance:String(goal.acceptance??'')},
545
+ current_plan:structuredClone(currentPlan),current_files:files,current_symbols:uniqSorted(currentSymbols),
546
+ recent_events:events.slice(-32).map(reference),open_failures:relevantIncidents.filter(item=>item.status==='open'),
547
+ known_constraints:uniqSorted([goal.acceptance,...relevantDecisions.flatMap(item=>item.constraints??[])]),
548
+ current_authority:safeAuthority(currentAuthority),relevant_decisions:relevantDecisions,
549
+ relevant_incidents:relevantIncidents,historical_memory:historical,
550
+ historical_archive_sha256:historicalArchiveSha256,historical_index_sha256:historicalIndexSha256,
551
+ active_episode:structuredClone(corpus.episode)};
552
+ const shrink=()=>{
553
+ if(body.recent_events.length>8){body.recent_events.shift();return true;}
554
+ const resolved=body.relevant_incidents.findIndex(item=>item.status!=='open');if(resolved>=0){body.relevant_incidents.splice(resolved,1);return true;}
555
+ if(body.relevant_decisions.length>8){body.relevant_decisions.shift();return true;}
556
+ if(body.historical_memory.length>4){body.historical_memory.pop();return true;}
557
+ if(body.current_files.length>8){body.current_files.shift();return true;}
558
+ if(body.current_symbols.length>16){body.current_symbols.pop();return true;}
559
+ return false;
560
+ };
561
+ while(Buffer.byteLength(canonicalJson(body),'utf8')>byteBudget){insist(shrink(),'working memory exceeds byte budget after deterministic compaction');}
562
+ return Object.freeze({...body,working_memory_sha256:sha(body)});
563
+ }
564
+
565
+ export function verifyWorkingMemory(memory,args={}){
566
+ try{
567
+ insist(memory?.source_release_manifest===args.sourceReleaseManifest,'working memory release mismatch');
568
+ const expected=buildWorkingMemory(args);insist(canonicalJson(expected)===canonicalJson(memory),'working memory stale or noncanonical');
569
+ return Object.freeze({ok:true,working_memory_sha256:memory.working_memory_sha256});
570
+ }catch(error){return Object.freeze({ok:false,reason:String(error?.message??error)});}
571
+ }
572
+
573
+ export function createSemanticMemoryAdapter({enabled=false,retrieveCandidates=null}={}){
574
+ insist(typeof enabled==='boolean','semantic memory enabled invalid');
575
+ if(enabled)insist(typeof retrieveCandidates==='function','semantic memory candidate provider missing');
576
+ return Object.freeze({enabled,async query({query,corpus,index,sourceReleaseManifest,limit=16}={}){
577
+ insist(enabled,'semantic memory is disabled');
578
+ insist(typeof query==='string'&&query.length>=1&&query.length<=4096,'semantic memory query invalid');
579
+ insist(Number.isInteger(limit)&&limit>=1&&limit<=128,'semantic memory limit invalid');
580
+ const raw=await retrieveCandidates({query,limit});
581
+ insist(Array.isArray(raw),'semantic memory candidates invalid');
582
+ const candidate_ids=raw.slice(0,limit);
583
+ const records=resolveCandidates(candidate_ids,{corpus,index,sourceReleaseManifest});
584
+ return Object.freeze({schema:'deadbyte.semantic-memory-result.v1',query,candidate_ids:[...candidate_ids],records,
585
+ source_memory_sha256:corpus.memory_sha256,source_index_sha256:index.index_sha256,canonical_verified:true,authorizes_execution:false});
586
+ }});
587
+ }
588
+
589
+ async function writeProjectionOnce(file,value){
590
+ const bytes=Buffer.from(`${canonicalJson(value)}\n`,'utf8');
591
+ try{
592
+ const existing=await readFile(file);
593
+ insist(existing.equals(bytes),'memory projection path already contains different bytes');
594
+ return {path:file,sha256:shaBytes(existing),existing:true};
595
+ }catch(error){if(error?.code!=='ENOENT')throw error;}
596
+ await mkdir(path.dirname(file),{recursive:true});
597
+ const temp=`${file}.tmp-${process.pid}-${randomBytes(4).toString('hex')}`;
598
+ const handle=await open(temp,'wx',0o600);
599
+ try{await handle.writeFile(bytes);await handle.sync();}finally{await handle.close();}
600
+ try{await rename(temp,file);}catch(error){
601
+ await rm(temp,{force:true}).catch(()=>{});
602
+ if(error?.code==='EEXIST'||error?.code==='EPERM'){
603
+ const existing=await readFile(file);insist(existing.equals(bytes),'memory projection concurrent write mismatch');
604
+ return {path:file,sha256:shaBytes(existing),existing:true};
605
+ }
606
+ throw error;
607
+ }
608
+ return {path:file,sha256:shaBytes(bytes),existing:false};
609
+ }
610
+
611
+ async function readJson(file){return JSON.parse((await readFile(file,'utf8')).replace(/^\uFEFF/,''));}
612
+ async function latestSnapshotPath(goalRoot){
613
+ try{const names=(await readdir(path.join(goalRoot,'snapshots'))).filter(name=>/^\d{12}-[0-9a-f]{64}\.json$/.test(name)).sort();
614
+ return names.length?path.join(goalRoot,'snapshots',names.at(-1)):path.join(goalRoot,'snapshots','missing.json');
615
+ }catch(error){if(error?.code==='ENOENT')return path.join(goalRoot,'snapshots','missing.json');throw error;}
616
+ }
617
+ async function loadHistoricalCorpora({journalRoot,currentGoalId,sourceReleaseManifest,publicKey,keyId,maxHistoricalGoals,maxEventsPerGoal}){
618
+ if(journalRoot===null)return [];
619
+ let entries;
620
+ try{entries=await readdir(journalRoot,{withFileTypes:true});}catch(error){if(error?.code==='ENOENT')return [];throw error;}
621
+ const goalIds=entries.filter(entry=>entry.isDirectory()&&HEX64.test(entry.name)&&entry.name!==currentGoalId)
622
+ .map(entry=>entry.name).sort((a,b)=>a.localeCompare(b,'en'));
623
+ insist(goalIds.length<=maxHistoricalGoals,'R41 historical goal bound exceeded');
624
+ const corpora=[];
625
+ for(const goalId of goalIds){
626
+ const goalRoot=path.join(journalRoot,goalId);const eventsRoot=path.join(goalRoot,'events');
627
+ const goal=verifyMemoryGoal(await readJson(path.join(goalRoot,'goal.json')),{publicKey,keyId,expectedGoalId:goalId});
628
+ const names=(await readdir(eventsRoot)).filter(name=>/^\d{6}\.json$/.test(name)).sort();
629
+ insist(names.length>=1&&names.length<=maxEventsPerGoal,`R41 historical event bound invalid for ${goalId}`);
630
+ insist(names.every((name,index)=>name===`${String(index+1).padStart(6,'0')}.json`),`R41 historical event gap for ${goalId}`);
631
+ const first=await readJson(path.join(eventsRoot,names[0]));
632
+ verifyMemoryJournal([first],{goalId,publicKey,keyId});
633
+ if(first.type!=='goal_created'||first.payload?.source_release_manifest!==sourceReleaseManifest)continue;
634
+ const events=[first];
635
+ for(const name of names.slice(1))events.push(await readJson(path.join(eventsRoot,name)));
636
+ verifyMemoryJournal(events,{goalId,publicKey,keyId});
637
+ corpora.push(buildMemoryCorpus({goal,events,publicKey,keyId,sourceReleaseManifest}));
638
+ }
639
+ return corpora;
640
+ }
641
+
642
+ export function createR41MemoryProvider({memoryRoot,sourceReleaseManifest,writerVersion='0.13.0',privateKey,publicKey,keyId,
643
+ byteBudget=65536,semantic={enabled:false},journalRoot=null,maxHistoricalGoals=256,maxEventsPerGoal=10000}={}){
644
+ insist(typeof memoryRoot==='string'&&path.isAbsolute(memoryRoot),'R41 memory root must be absolute');
645
+ hex(sourceReleaseManifest,'R41 memory source release manifest');
646
+ insist(privateKey&&publicKey,'R41 memory provider trust keys missing');
647
+ insist(typeof keyId==='string'&&keyId.length>=1&&keyId.length<=128,'R41 memory provider key id invalid');
648
+ insist(Number.isInteger(byteBudget)&&byteBudget>=4096&&byteBudget<=4*1024*1024,'R41 memory provider byte budget invalid');
649
+ insist(journalRoot===null||(typeof journalRoot==='string'&&path.isAbsolute(journalRoot)),'R41 memory journal root invalid');
650
+ insist(Number.isInteger(maxHistoricalGoals)&&maxHistoricalGoals>=0&&maxHistoricalGoals<=4096,'R41 historical goal bound invalid');
651
+ insist(Number.isInteger(maxEventsPerGoal)&&maxEventsPerGoal>=1&&maxEventsPerGoal<=100000,'R41 historical event bound invalid');
652
+ insist(semantic?.enabled===false,'R41 semantic memory must remain disabled unless a verified adapter is explicitly configured');
653
+ async function refresh({goal,events,currentPlan=null,currentFiles=[],currentSymbols=[],currentAuthority={}}={}){
654
+ insist(Array.isArray(events)&&events.length>=1,'R41 memory provider requires journal events');
655
+ const goalRoot=path.join(memoryRoot,'goals',goal.goal_id);
656
+ const loadedState=await loadMemoryState({snapshotPath:await latestSnapshotPath(goalRoot),goal,events,publicKey,keyId,sourceReleaseManifest});
657
+ const corpus=buildMemoryCorpus({goal,events,publicKey,keyId,sourceReleaseManifest});
658
+ insist(canonicalJson(loadedState.state)===canonicalJson(corpus.state),'R41 snapshot replay diverged from full replay');
659
+ const index=buildRetrievalIndex(corpus,{sourceReleaseManifest});
660
+ const historicalCorpora=await loadHistoricalCorpora({journalRoot,currentGoalId:goal.goal_id,sourceReleaseManifest,
661
+ publicKey,keyId,maxHistoricalGoals,maxEventsPerGoal});
662
+ const historicalArchive=buildMemoryArchive(historicalCorpora,{sourceReleaseManifest});
663
+ const historicalIndex=buildRetrievalIndex(historicalArchive,{sourceReleaseManifest});
664
+ const snapshot=createMemorySnapshot({goal,events,snapshotSequence:events.length,sourceReleaseManifest,writerVersion,
665
+ createdAtUtc:events.at(-1).created_at_utc,privateKey,publicKey,keyId});
666
+ const snapshotPath=path.join(goalRoot,'snapshots',`${String(events.length).padStart(12,'0')}-${snapshot.journal_prefix_hash}.json`);
667
+ const indexPath=path.join(goalRoot,'indexes',`${index.index_sha256}.json`);
668
+ const archivePath=path.join(memoryRoot,'archives',`${historicalArchive.memory_sha256}.json`);
669
+ const archiveIndexPath=path.join(memoryRoot,'archive-indexes',`${historicalIndex.index_sha256}.json`);
670
+ const [snapshotFile,indexFile,archiveFile,archiveIndexFile]=await Promise.all([writeProjectionOnce(snapshotPath,snapshot),
671
+ writeProjectionOnce(indexPath,index),writeProjectionOnce(archivePath,historicalArchive),writeProjectionOnce(archiveIndexPath,historicalIndex)]);
672
+ const snapshotProof=verifyMemorySnapshot(snapshot,{goal,events,publicKey,keyId,sourceReleaseManifest});
673
+ insist(snapshotProof.ok,`R41 memory snapshot self-verification failed: ${snapshotProof.reason}`);
674
+ const indexProof=verifyRetrievalIndex(index,{corpus,sourceReleaseManifest});
675
+ insist(indexProof.ok,`R41 memory index self-verification failed: ${indexProof.reason}`);
676
+ const working=buildWorkingMemory({goal,events,corpus,index,publicKey,keyId,sourceReleaseManifest,byteBudget,
677
+ currentPlan,currentFiles,currentSymbols,currentAuthority,historicalArchive,historicalIndex});
678
+ return Object.freeze({status:'ok',source_release_manifest:sourceReleaseManifest,
679
+ journal_head_sha256:events.at(-1).event_sha256,snapshot_path:snapshotFile.path,
680
+ snapshot_sha256:snapshot.snapshot_sha256,snapshot_file_sha256:snapshotFile.sha256,
681
+ index_path:indexFile.path,index_sha256:index.index_sha256,index_file_sha256:indexFile.sha256,
682
+ historical_archive_path:archiveFile.path,historical_archive_sha256:historicalArchive.memory_sha256,
683
+ historical_archive_file_sha256:archiveFile.sha256,historical_index_path:archiveIndexFile.path,
684
+ historical_index_sha256:historicalIndex.index_sha256,historical_index_file_sha256:archiveIndexFile.sha256,
685
+ historical_goal_count:historicalCorpora.length,
686
+ replay_mode:loadedState.mode,replay_snapshot_reason:loadedState.snapshot_reason,
687
+ memory_sha256:corpus.memory_sha256,working_memory_sha256:working.working_memory_sha256,
688
+ semantic_enabled:false,planner_context:working});
689
+ }
690
+ async function plannerContext(input){return (await refresh(input)).planner_context;}
691
+ return Object.freeze({refresh,plannerContext,source_release_manifest:sourceReleaseManifest,semantic_enabled:false});
692
+ }