/** The six Ultimate plan/todos cases, plus real-loader turns and branch reset. */ import { BACKGROUND_CONTEXT as context } from '@earendil-works/chord/context'; import { createModels } from '@earendil-works/pi-ai/models'; import { fauxProvider, fauxAssistantMessage, fauxToolCall } from '@earendil-works/pi-ai/providers/faux'; import { Harness, createRegistry, defineExtension } from '@earendil-works/pi-durable'; import { openStorage } from './sqlite'; import { loadExtensions, fs, Metadata } from './extensions'; const assert = (value:any, message:string) => { if (!value) throw new Error(message); }; const equal = (actual:any, expected:any) => assert(JSON.stringify(actual) === JSON.stringify(expected), `Mismatch: ${JSON.stringify(actual)} != ${JSON.stringify(expected)}`); const rejects = async (call:()=>Promise, text:string) => { try { await call(); } catch(error) { assert(String(error).includes(text), String(error)); return; } throw new Error(`Expected ${text}`); }; const models = createModels(), faux = fauxProvider({tokensPerSecond:100000}); models.setProvider(faux.provider); const registry = createRegistry(), storage = await openStorage(globalThis.storagePath); const harness = await Harness.open(storage,{models,registry,settings:{get extensions(){return registry.snapshot().installed();}}},context); const root = await harness.root(context,{agent:{model:{provider:'faux',modelId:'faux-1'}}}); const loader = await loadExtensions(harness,registry,storage,models,context); assert(!loader.state().error, loader.state().error); const base = `file:///run/sausage/extensions/${loader.state().good}/extensions`; const planModule = await import(/* @vite-ignore */ `${base}/plan/server.ts`); const todosModule = await import(/* @vite-ignore */ `${base}/todos/server.ts`); const {Plan,TaskIndex,Branch,Started} = planModule; const {Todos,Standing,add,mark,noteFor,DONE_LIMIT} = todosModule; const call = async (args:any, id=root.id, name='plan') => { const conversation = await harness.conversation(id,context); await conversation.configure({model:{provider:'faux',modelId:'faux-1'},modelTools:{add:[todosModule.default().tools[0]]}},context); faux.setResponses([fauxAssistantMessage([fauxToolCall(name,args)],{stopReason:'toolUse'}),fauxAssistantMessage('Complete')]); await (await conversation.submit({type:'input',content:'Update ledger'},context)).wait(context); await harness.waitForIdle(context); return (await conversation.context(context)).entries.filter((entry:any)=>entry.kind==='pi.tool-result').at(-1).model[0]; }; const text = (result:any)=>result.content.map((block:any)=>block.text).join(''); harness.resume(); try { if (globalThis.planTodosRestart) { const saved = JSON.parse(await fs.read('/saved')); equal(await harness.snapshot(Plan,root.id,context),saved.plan); equal(await harness.snapshot(TaskIndex,root.id,context),saved.index); equal(await harness.snapshot(Todos,root.id,context),saved.todos); assert(!(await call({action:'show'})).isError,'Plan survives restart'); } else { // Plan case 1: descendants, verdicts, memo replay, transactional receipts, nested namespaces. const extension = planModule.default({metadata:Metadata}); const tool = extension.tools[0], replayResults:any[] = [], nestedResults:any[] = []; let childId:number, grandchildId:number; registry.install(defineExtension({...extension,tools:[{...tool,execute:async(args:any,api:any,ctx:any)=>{ if(args.title==='Nested') { const results=[]; for(const namespace of ['first','second']) { const nestedApi={...api,memo:(name:string,value:any,memoContext?:any)=>memoContext===undefined?api.memo(`${namespace}/${name}`,ctx):api.memo(`${namespace}/${name}`,value,memoContext)}; const first=await tool.execute(args,nestedApi,ctx); const replayApi={...nestedApi,memo:(name:string,...rest:any[])=>name==='result'&&rest.length===1?Promise.resolve(undefined):nestedApi.memo(name,...rest)}; nestedResults.push([first,await tool.execute(args,replayApi,ctx)]);results.push(first); } return results[1]; } const result=await tool.execute(args,api,ctx); if(api.conversationId===childId && grandchildId===undefined) grandchildId=await api.commit(async(tx:any)=>(await tx.createConversation({ownership:{kind:'task',taskId:api.taskId}})).id,ctx); if(args.action==='create') childId=await api.commit(async(tx:any)=>(await tx.createConversation({ownership:{kind:'task',taskId:api.taskId}})).id,ctx); if(args.action==='add') { const replayApi={...api,memo:(name:string,...rest:any[])=>name==='result'&&rest.length===1?Promise.resolve(undefined):api.memo(name,...rest)}; replayResults.push([result,await tool.execute(args,api,ctx),await tool.execute(args,replayApi,ctx)]); } return result; }}]})); await call({action:'create',title:'Ship ledger',body:'## Request\nDurable plans'}); await call({action:'add',epic:'E1',title:'Implement',role:'worker',description:'Build it'}); await call({action:'add',epic:'E1',title:'Review',role:'reviewer',description:'Check it',deps:['E1.1']}); await call({action:'update',key:'E1.1',status:'in_review',child:42,verdict:'Checks passed'}); await call({action:'note',key:'E1.1',text:'Checks passed'}); const saved=await harness.snapshot(Plan,root.id,context), task=saved.epics.E1.tasks['E1.1']; equal(Object.keys(saved.epics.E1.tasks),['E1.1','E1.2']); assert(saved.next===2 && task.status==='in_review' && task.child===42 && task.verdict==='Checks passed','Saved verdict'); assert(task.notes[0].text==='Checks passed' && typeof task.notes[0].at==='string','Saved note'); equal(saved.epics.E1.tasks['E1.2'].deps,['E1.1']); assert(saved.epics.E1.tasks['E1.2'].role==='reviewer','Reviewer role'); assert(replayResults.length===2,'Two replayed additions'); for(const [result,memo,receipt] of replayResults){equal(memo,result);equal(receipt,result);} for(const key of ['E1','E1.1']) equal(JSON.parse(text(await call({action:'show',key},childId!))),key==='E1'?saved.epics.E1:task); for(const args of [{action:'create',title:'Forbidden',body:'No'},{action:'add',epic:'E1',title:'Forbidden',role:'worker',description:'No'},{action:'update',key:'E1.1',status:'done'},{action:'note',key:'E1.1',text:'No'}]) { const denied=await call(args,childId!);assert(denied.isError && text(denied).includes(`Only conversation ${root.id} edits this plan`),'Descendant write refusal'); } equal(JSON.parse(text(await call({action:'show',key:'E1.1'},grandchildId!))),task); assert((await call({action:'note',key:'E1.1',text:'No'},grandchildId!)).isError,'Grandchild write refusal'); equal(await harness.snapshot(Plan,root.id,context),saved); for(const args of [{action:'update',key:'E1.1',body:'No'},{action:'update',key:'E1',status:'todo'},{action:'show',key:'E99'}]) assert((await call(args)).isError,'Invalid plan edit'); equal(await harness.snapshot(Plan,root.id,context),saved); await call({action:'update',key:'E1',status:'done',verdict:'Approved'});await call({action:'show'}); await call({action:'add',epic:'E1',title:'Nested',role:'worker',description:'Separate calls'}); assert(nestedResults.length===2 && JSON.stringify(nestedResults[0][0])!==JSON.stringify(nestedResults[1][0]),'Separate nested calls'); for(const [first,replay] of nestedResults)equal(first,replay); equal(Object.keys((await harness.snapshot(Plan,root.id,context)).epics.E1.tasks),['E1.1','E1.2','E1.3','E1.4']); registry.install(extension); // Plan case 2: the child index tracks title changes and link replacement. await harness.commit(async(tx:any)=>Object.assign(await tx.doc(Plan,root.id),Plan.definition.initial()),context); const [first,second]=await harness.commit(async(tx:any)=>[(await tx.createConversation({ownership:{kind:'ownerless'}})).id,(await tx.createConversation({ownership:{kind:'ownerless'}})).id],context); await call({action:'create',title:'Index',body:'Body'}); await call({action:'add',epic:'E1',title:'Build it',role:'worker',description:'D'}); await call({action:'update',key:'E1.1',child:first}); const index=async()=>(await harness.snapshot(TaskIndex,root.id,context)).children; const title=async(id:number)=>(await harness.snapshot(Metadata,id,context)).title; equal(await index(),{[first]:{coordinator:root.id,epic:'E1',key:'E1.1',title:'Build it',status:'backlog'}});equal(await title(first),'Build it'); await call({action:'update',key:'E1.1',status:'in_progress',title:'Build it well'}); assert((await index())[first].status==='in_progress','Index status');equal(await title(first),'Build it well'); await harness.commit(async(tx:any)=>{(await tx.doc(Metadata,first)).title='Renamed by hand';},context); await call({action:'note',key:'E1.1',text:'Progress'});equal(await title(first),'Renamed by hand'); await call({action:'update',key:'E1.1',child:second});equal(Object.keys(await index()),[String(second)]);equal(await title(second),'Build it well'); // A new lineage branch clears the inherited plan in its first input commit. const at=await root.commit((tx:any)=>tx.appendEntry(root.id,{kind:'branch.origin',data:{}}),context); const branch=await root.commit(async(tx:any)=>{const record=await tx.forkConversation(root.id,at.id,{ownership:{kind:'ownerless'}});(await tx.doc(Branch,record.id)).branch={from:root.id,at:at.id,intent:'Fresh'};return record;},context); assert(Object.keys((await harness.snapshot(Plan,branch.id,context)).epics).length===1,'Fork inherited plan'); equal(JSON.parse(text(await call({action:'show'},branch.id))),Plan.definition.initial()); assert((await harness.snapshot(Started,branch.id,context)).started,'Branch started'); // Todos cases 1-4 retain the original small transaction fixture. const ULTIMATE=5; const fakeTx=()=>{const docs=new Map();return {doc:async({definition:def}:any,id:number)=>{const key=`${def.kind}:${id}`;if(!docs.has(key))docs.set(key,def.kind==='ultimate.standing-agents'?{ultimate:ULTIMATE}:def.initial());return docs.get(key);}};}; const list=async(tx:any)=>(await tx.doc(Todos,1)).items; { const tx=fakeTx();equal((await add(tx,' Deploy fleet ','ultimate')).text,'Deploy fleet'); assert((await add(tx,'Rotate the key','user')).id===2,'Sequential todo ids'); await rejects(()=>add(tx,' ','user'),'nonempty');await rejects(()=>add(tx,'x','lander'),'owner');equal((await list(tx)).map((todo:any)=>todo.id),[1,2]); } { const tx=fakeTx();for(let i=0;itodo.id),Array.from({length:DONE_LIMIT},(_,i)=>i+3));await rejects(()=>mark(tx,999,true),'No to-do 999'); } { const tx=fakeTx(), content=async()=>(await noteFor(tx,ULTIMATE,0))?.entries[0].model[0].content; assert(await content()===undefined,'Empty note');await add(tx,'Mine','ultimate');await add(tx,'Theirs','user'); equal(await content(),"Open to-dos (todo tool: done when finished):\nYours:\n- 1: Mine\nThe user's:\n- 2: Theirs");assert(await content()===undefined,'Unchanged note'); await mark(tx,1,true);await mark(tx,2,true);equal(await content(),'No to-dos are open.');assert(await content()===undefined,'Unchanged empty note'); } { const tx=fakeTx(), extension=todosModule.default(), tool=extension.tools[0]; const run=(conversationId:number,args:any)=>tool.execute(args,{conversationId,commit:(fn:any)=>fn(tx)},context); await rejects(()=>run(9,{action:'list'}),'Only @ultimate');equal(await run(ULTIMATE,{action:'add',text:'Ship it',owner:'user'}),{output:[{type:'text',text:'Added 1 for user: Ship it'}]}); equal(await run(ULTIMATE,{action:'list'}),{output:[{type:'text',text:"The user's:\n- 1: Ship it"}]}); const before=(conversationId:number)=>extension.hooks[0].handlers.beforeInput({}, {tx,conversationId},context); assert(await before(9)===undefined,'Nonstanding note');assert(await before(ULTIMATE)!==undefined,'Standing note'); } // The real world also calls todo through the loaded factory and places its note. await harness.commit(async(tx:any)=>{(await tx.doc(Standing,root.id)).ultimate=root.id;},context); assert(text(await call({action:'add',text:'Real world',owner:'ultimate'},root.id,'todo')).includes('Added 1'),'Loaded todo tool'); assert(text(await call({action:'list'},root.id,'todo')).includes('Real world'),'Loaded todo list'); assert((await root.context(context)).entries.some((entry:any)=>entry.kind==='todos.note'),'Real beforeInput note'); await fs.write('/saved',JSON.stringify({plan:await harness.snapshot(Plan,root.id,context),index:await harness.snapshot(TaskIndex,root.id,context),todos:await harness.snapshot(Todos,root.id,context)})); } } finally {await loader.close();await harness.close(context);}