mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-14 18:41:42 +08:00
71 lines
4.6 KiB
TypeScript
71 lines
4.6 KiB
TypeScript
import {expect,test} from 'bun:test';
|
|
import fs from 'node:fs';
|
|
import {autoplanPermissionProgressKey} from './helpers/autoplan-artifact-permission';
|
|
import type {NativePublicToolEvent} from './helpers/plan-count-transcript';
|
|
import capture from './fixtures/autoplan-overwrite-progress-ax.json';
|
|
const before=()=>structuredClone(capture.beforeEvents) as NativePublicToolEvent[];
|
|
const after=()=>structuredClone(capture.afterEvents) as NativePublicToolEvent[];
|
|
|
|
test('the acknowledged 92-line Write distinguishes the next identical overwrite footer',()=>{
|
|
expect(capture.before.slice(-500)).toBe(capture.after.slice(-500));
|
|
const oldKey=autoplanPermissionProgressKey(capture.before,before());
|
|
const newKey=autoplanPermissionProgressKey(capture.after,after());
|
|
expect(oldKey).toEndWith(':toolu_01RBorP8UERrbVheRiXSN1v4');
|
|
expect(newKey).toEndWith(':toolu_01RPGbV4z5AAMcnzwD4qcx9p');
|
|
expect(newKey).not.toBe(oldKey);
|
|
});
|
|
|
|
test('the same still-pending dialog has no new progress epoch',()=>{
|
|
const events=before(),key=autoplanPermissionProgressKey(capture.before,events);
|
|
expect(autoplanPermissionProgressKey(capture.after,events)).toBe(key);
|
|
events.push(after()[2]!); // Published use alone has not completed.
|
|
expect(autoplanPermissionProgressKey(capture.after,events)).toBe(key);
|
|
events.push({...after()[3]!,isError:true});
|
|
expect(autoplanPermissionProgressKey(capture.after,events)).toBe(key);
|
|
});
|
|
|
|
test('unrelated results and same-basename files in other directories do not advance the epoch',()=>{
|
|
const key=autoplanPermissionProgressKey(capture.before,before());
|
|
for(const mutate of [
|
|
(events:NativePublicToolEvent[])=>{events[2]!.name='Read';},
|
|
events=>{events[2]!.name='Bash';},
|
|
events=>{events[2]!.input!.file_path=String(events[2]!.input!.file_path).replace('/ceo-plans/','/other-plans/');},
|
|
events=>{events[2]!.input!.file_path=String(events[2]!.input!.file_path).replace('/ceo-plans/','/ceo-plans-sibling/');},
|
|
events=>{events[3]!.isError=undefined;},
|
|
events=>{events[3]!.toolUseId='unrelated-result';},
|
|
events=>{events[3]!.timestamp='invalid';},
|
|
events=>{events[3]!.timestamp='2026-09-11T02:00:00Z';},
|
|
]){const events=after();mutate(events);expect(autoplanPermissionProgressKey(capture.after,events)).toBe(key);}
|
|
});
|
|
|
|
test('missing path authority, mixed sessions and duplicate uses supply no matching progress',()=>{
|
|
expect(autoplanPermissionProgressKey(capture.after,[])).toBeUndefined();
|
|
expect(autoplanPermissionProgressKey(capture.after.replace('overwrite 2026-09-11-user-dashboard.md','overwrite other.md'),after())).toBeUndefined();
|
|
expect(autoplanPermissionProgressKey(capture.after.replace('always allow access to','access to'),after())).toBeUndefined();
|
|
const mixed=after();mixed[3]!.sessionId='other';expect(autoplanPermissionProgressKey(capture.after,mixed)).toBeUndefined();
|
|
const duplicate=after();duplicate.splice(3,0,structuredClone(duplicate[2]!));
|
|
expect(autoplanPermissionProgressKey(capture.after,duplicate)).toBe(autoplanPermissionProgressKey(capture.before,before()));
|
|
});
|
|
|
|
test('the actual generic permission branch preserves classification and waits for selection',async()=>{
|
|
const source=fs.readFileSync(new URL('./skill-e2e-autoplan-chain.test.ts',import.meta.url),'utf8');
|
|
const block=source.slice(source.indexOf(' const recentTail = visible.slice(-1500);'),source.indexOf(' // This new repository offers routing'));
|
|
expect(block.match(/continue;/g)).toHaveLength(1);
|
|
const sends:string[]=[];let release:(()=>void)|undefined;
|
|
const select=async()=>{sends.push('selected');await new Promise<void>(r=>{release=r;});sends.push('confirmed');};
|
|
const make=new Function('autoplanPermissionProgressKey','selectPtyNumberedOption','Bun',`
|
|
let lastPermSig='',lastPermissionProgress='';
|
|
return async(visible,publicTools,allowed=true)=>{
|
|
const transcript={status:'ready'},session={};
|
|
const isNumberedOptionListVisible=()=>allowed,isPermissionDialogVisible=()=>allowed;
|
|
${block.replace('continue;','return;')}
|
|
};
|
|
`);
|
|
const step=make(autoplanPermissionProgressKey,select,{sleep:async()=>{}});
|
|
const first=step(capture.before,before());await Promise.resolve();expect(sends).toEqual(['selected']);release!();await first;
|
|
await step(capture.after,before());expect(sends).toEqual(['selected','confirmed']);
|
|
await step(capture.after,after(),false);expect(sends).toHaveLength(2); // Existing AUQ/permission classification still decides.
|
|
const next=step(capture.after,after());await Promise.resolve();expect(sends).toHaveLength(3);release!();await next;
|
|
await step(capture.after,after());expect(sends).toEqual(['selected','confirmed','selected','confirmed']);
|
|
});
|