/** Scripted acceptance cases run through the world extension loader and real guest Git. */ import { BACKGROUND_CONTEXT as context, awaitWithContext } 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, defineTool } from '@earendil-works/pi-durable'; import { obj, str } from '@earendil-works/pi-schema'; import { loadExtensions, fs } from './extensions'; import { openStorage } from './sqlite'; const assert=(value:any,message:string)=>{if(!value)throw new Error(message)}; 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'},cwd:'/project'}}); if(globalThis.workspacesMode==='kill') { const install=registry.install.bind(registry); registry.install=(extension:any)=>install(extension.name!=='workspaces'?extension:{...extension,tasks:extension.tasks.map((task:any)=>task.definition.name!=='workspaces.lander'?task:{definition:{...task.definition,phases:{...task.definition.phases,land:async(record:any,runtime:any,ctx:any)=>{ const commit=runtime.commit.bind(runtime); await taskDefinition(record,runtime,ctx); async function taskDefinition(record:any,rt:any,c:any){ await task.definition.phases.land(record,{...rt,commit:async(...args:any[])=>{ await commit(...args); const index=await harness.snapshot(globalThis.workspaceService.doc,root.id,context); if(index.queue.some((entry:any)=>entry.landed)) { await fs.write('/push-ready','yes');await awaitWithContext(new Promise(()=>{}),c); } }},c); } }}}})}); } const probe=defineExtension({name:'guest',tools:[defineTool({name:'implement',description:'Write and commit in the prepared checkout',parameters:obj({name:str()}),replay:'safe',execute:async(args:any,api:any,ctx:any)=>{ const cwd=(await api.agent(ctx)).cwd; assert(cwd.startsWith('/worktrees/'),'First tool needs isolated cwd'); assert((await fs.stat(`${cwd}/base.txt`)).kind==='file','Checkout must exist before first tool'); const workspace=await globalThis.workspaceService.get(api.conversationId,ctx); assert(workspace.state==='ready','Preparation must finish'); await fs.write(`${cwd}/${args.name}`,'feature'); for(const args of [['add','.'],['-c','user.name=Test','-c','user.email=test@example.com','commit','--no-gpg-sign','-m','feature']])await globalThis.workspaceHost.git(cwd,...args); return {output:[{type:'text',text:'committed'}]}; }})]}); const route=(transcript:any):any=>{ faux.appendResponses([route]); const last=transcript.messages.findLast((message:any)=>message.role!=='system'); const text=typeof last.content==='string'?last.content:last.content.filter((part:any)=>part.type==='text').map((part:any)=>part.text).join(''); if(last.role==='user'&&text.startsWith('CALL ')){const {tool,args}=JSON.parse(text.slice(5));return fauxAssistantMessage([fauxToolCall(tool,args)],{stopReason:'toolUse'});} if(last.role==='user'&&text==='IMPLEMENT')return fauxAssistantMessage([fauxToolCall('implement',{name:'feature.txt'})],{stopReason:'toolUse'}); if(last.role==='user'&&text==='BROKEN')return fauxAssistantMessage([fauxToolCall('implement',{name:'broken.txt'})],{stopReason:'toolUse'}); return fauxAssistantMessage('Done'); };faux.setResponses([route]); const loader=await loadExtensions(harness,registry,storage,models,context,[probe]); assert(!loader.state().error,`Load: ${loader.state().error}`); const service=globalThis.workspaceService,host=globalThis.workspaceHost; const call=async(tool:string,args:any)=>{ await(await root.submit({type:'input',content:`CALL ${JSON.stringify({tool,args})}`},context)).wait(context); const result=(await root.context(context)).entries.filter((entry:any)=>entry.kind==='pi.tool-result').at(-1)?.model?.[0] as any; assert(!result?.isError,`Tool error: ${JSON.stringify(result)}`); return result; }; const submit=async(id:number)=>{ const {Started}=await import(`file:///run/sausage/extensions/${await fs.read('/src/sausage/.git/sausage-last-good')}/extensions/messages/addresses.ts`); await harness.commit(async(tx:any)=>{(await tx.doc(Started,id)).by=root.id},context); const child=await harness.conversation(id,context); await(await child.submit({type:'input',content:`CALL ${JSON.stringify({tool:'workspace',args:{action:'submit',divergence:'None'}})}`},context)).wait(context); const result=(await child.context(context)).entries.filter((entry:any)=>entry.kind==='pi.tool-result').at(-1)?.model?.[0] as any; assert(!result?.isError,`Workspace tool: ${JSON.stringify(result)}`); return JSON.parse(result.content.filter((part:any)=>part.type==='text').map((part:any)=>part.text).join('')); }; const children=async()=>{ const {Subagents}=await import(`file:///run/sausage/extensions/${await fs.read('/src/sausage/.git/sausage-last-good')}/extensions/subagents/api.ts`); return Object.values((await harness.snapshot(Subagents,root.id,context)).agents) as any[]; }; const waitQueue=async()=>{ const deadline=Date.now()+30000; while((await harness.snapshot(service.doc,root.id,context)).queue.length) { if(Date.now()>deadline)throw new Error(`Lander deadline: ${JSON.stringify(await harness.snapshot(service.doc,root.id,context))}`); await new Promise(r=>setTimeout(r,0)); } await harness.waitForIdle(context); }; const reports=async(id:number)=>(await(await harness.conversation(id,context)).context(context)).entries.filter((entry:any)=>entry.kind==='workspaces.lander-report'); const notes=async()=>{ const {Messages}=await import(`file:///run/sausage/extensions/${await fs.read('/src/sausage/.git/sausage-last-good')}/extensions/messages/api.ts`); const deadline=Date.now()+30000; for(;;) { const notes=((await harness.snapshot(Messages,root.id,context)).messages as any[]).filter(message=>message.text.startsWith('[lander] Submission')&&message.text.includes(' landed as ')); if(!notes.some(note=>note.state==='sent'))return notes; assert(Date.now()setTimeout(r,0)); } }; harness.resume(); try { if(globalThis.workspacesMode==='resume') { await waitQueue(); const index=await harness.snapshot(service.doc,root.id,context); const result=Object.values(index.results)[0] as any; assert(result?.outcome==='landed',`Recovery result ${JSON.stringify(index)}`); const [child]=await children(); const report=await reports(child.conversationId); assert(report.length===1,'Restart must report once'); assert(report[0].data.sha===result.sha,'Report must retain landed.sha'); const delivered=await notes(); assert(delivered.length===1&&delivered[0].state==='delivered'&&delivered[0].text.includes(result.sha),`Restart must notify the starter once with landed.sha: ${JSON.stringify(delivered)}`); assert(await host.git('/remote.git','rev-parse','main')===result.sha,`Push must retain landed.sha: ${JSON.stringify(result)}`); assert((await host.git('/project','log','--format=%s')).split('\n').filter((line:string)=>line.startsWith('Merge from')).length===1,'Restart must not merge again'); assert((await host.eventLog.recent({events:[{kind:'event.workspaces.landed'}]})).length===1,'Restart must emit once'); } else { await call('subagent',{action:'start',agent:'worker',task:globalThis.workspacesMode==='normal'?'BROKEN':'IMPLEMENT'}); if(globalThis.workspacesMode==='normal') { const [broken]=await children(); const before=globalThis.workspaceExecutions.length; assert(!await service.unavailable(broken.conversationId,context),'Ready VFS gate'); assert(globalThis.workspaceExecutions.length===before,'Ready gate must not spawn Git'); const checkout=await service.get(broken.conversationId,context); await fs.rename(`${checkout.path}/.git`,`${checkout.path}/.git.saved`); assert((await service.unavailable(broken.conversationId,context)).includes('missing or unregistered'),'Gate must reject missing registration'); const blocked=await harness.conversation(broken.conversationId,context); await(await blocked.submit({type:'input',content:`CALL ${JSON.stringify({tool:'implement',args:{name:'guard.txt'}})}`},context)).wait(context); const blockedResult=(await blocked.context(context)).entries.filter((entry:any)=>entry.kind==='pi.tool-result').at(-1)?.model?.[0] as any; assert(blockedResult.isError&&JSON.stringify(blockedResult).includes('missing or unregistered'),'beforeTool must block the guest tool'); assert(!await fs.stat(`${checkout.path}/guard.txt`).then(()=>true,(error:any)=>{if(error.code==='not_found')return false;throw error}),'Blocked tool must not write'); await fs.rename(`${checkout.path}/.git.saved`,`${checkout.path}/.git`); assert(globalThis.workspaceExecutions.length===before,'Failed VFS gate must not spawn Git'); const failed=await submit(broken.conversationId); await waitQueue(); const result=(await harness.snapshot(service.doc,root.id,context)).results[failed.id]; assert(result.outcome==='failed'&&result.reason.includes('Check sh'),`Check must fail: ${JSON.stringify(result)}`); assert((await reports(broken.conversationId)).length===1,'Failed check must return to submitter'); const failedWorkspace=await service.get(broken.conversationId,context); assert((await service.release([broken.conversationId],context)).length===1,'Release must retain unlanded work'); await call('subagent',{action:'discard',id:broken.conversationId}); assert(await host.git('/project','rev-parse',failedWorkspace.branch),'Discard must retain its branch'); await call('subagent',{action:'start',agent:'worker',task:'IMPLEMENT'}); const child=(await children()).at(-1); await call('subagent',{action:'land',id:child.conversationId}); assert(await fs.read('/project/feature.txt')==='feature','Parent fast-forward'); assert((await service.get(child.conversationId,context)).state==='removed','Land must release checkout'); await call('subagent',{action:'start',agent:'worker',task:'BROKEN'}); } const submitter=(await children()).at(-1).conversationId; const submission=await submit(submitter); if(globalThis.workspacesMode==='kill')await new Promise(()=>{}); await waitQueue(); const result=(await harness.snapshot(service.doc,root.id,context)).results[submission.id]; // feature.txt came from synchronous landing, so this submission passes its real shell check too. assert(result.outcome==='landed',`Landing failed: ${JSON.stringify(result)}`); assert(await host.git('/remote.git','rev-parse','main')===result.sha,`Local bare push: ${JSON.stringify(result)}`); assert((await reports(submitter)).length===1,'Submission report'); const delivered=await notes(); assert(delivered.length===1&&delivered[0].state==='delivered'&&delivered[0].from===submitter&&delivered[0].to===root.id&&delivered[0].reply===false&&delivered[0].text.includes(result.sha),`Landing note must use the messages API: ${JSON.stringify(delivered)}`); const commands=globalThis.workspaceExecutions.filter((entry:any)=>typeof entry.command==='string'||entry.command[1]==='fetch'||entry.command[1]==='push'); const push=commands.findLast((entry:any)=>entry.command[1]==='push'); assert(push,'Real push must run'); assert(JSON.stringify(push.options.conversations)===JSON.stringify([String(submitter),String(root.id)]),'Push must use the exact submitter chain'); for(const entry of commands) { assert(entry.options.task!==undefined,'Lander exec needs its task tag'); if(typeof entry.command==='string')assert(entry.options.timeout===600,'Checks need a bounded default timeout'); assert(entry.options.conversations[1]===String(root.id),'Lander exec needs the submitter ancestor'); assert(entry.options.conversations[0]!==String(root.id),'Lander exec needs the submitter first'); } } }finally{await loader.close();await harness.close(context)}