fix(pi): keep active runs alive during background sleep

This commit is contained in:
2026-08-25 20:56:17 +08:00
parent 92f4c91088
commit 621ebb1781
22 changed files with 1061 additions and 68 deletions

View File

@@ -270,9 +270,11 @@ describe('PI-100 coding core Host contract', () => {
await archivePiConversationSession({ userDataDir, ...input });
},
});
const dispose = vi.spyOn(result.runtime, 'dispose');
await conversations.deleteConversation(conversation.id);
expect(dispose).toHaveBeenCalledWith(conversation.id, 'conversation_deleted');
await expect(result.projects.conversationStore(result.root).get(conversation.id)).resolves.toBeNull();
await expect(readFile(path.join(
userDataDir,
@@ -652,16 +654,24 @@ describe('PI-100 coding core Host contract', () => {
createId: () => `project-${++nextId}`,
});
const first = await createLocalCodingProject({ projectPath: projectRoots[0]! }, store);
const deactivated: string[] = [];
const deactivated: Array<{ projectId: string; reason: string }> = [];
const projects = new CodingProjectService(store, {
onProjectDeactivated: async (project) => { deactivated.push(project.id); },
onProjectDeactivated: async (project, reason) => {
deactivated.push({ projectId: project.id, reason });
},
});
const opened = await projects.openProject(projectRoots[1]!);
const created = await projects.createProject({ projectPath: projectRoots[2]! });
await projects.setActiveProject(first.project.id);
await projects.removeProject(first.project.id);
expect(deactivated).toEqual([first.project.id, opened.id, created.project.id]);
expect(deactivated).toEqual([
{ projectId: first.project.id, reason: 'project_deactivated' },
{ projectId: opened.id, reason: 'project_deactivated' },
{ projectId: created.project.id, reason: 'project_deactivated' },
{ projectId: first.project.id, reason: 'project_removed' },
]);
});
it('removes absolute project roots from every core project response', async () => {
@@ -852,7 +862,7 @@ describe('PI-100 coding core Host contract', () => {
await expect(conversations.fork(source.id, 'entry-user-fork-cleanup')).rejects.toMatchObject({
code: 'CODING_SESSION_UNREADABLE',
});
expect(dispose).toHaveBeenCalledWith(forkTargetId);
expect(dispose).toHaveBeenCalledWith(forkTargetId, 'fork_replacement');
expect(archiveSession).toHaveBeenCalledWith({
projectId: 'project-a',
sessionKey: 'fork-session-key',