merge: integrate remote and local main histories

# Conflicts:
#	.project-docs/20-architecture/module-map.md
#	.project-docs/30-worklog/current-state.md
#	.project-docs/50-evidence/evidence-index.md
#	src/pages/MyPlugins/index.tsx
#	tests/unit/pi-agent-server-process-real.test.ts
#	tests/unit/pi-managed-worker-opener.test.ts
#	tests/unit/plugin-marketplace-pages.test.tsx
This commit is contained in:
inman
2026-09-03 10:44:04 +08:00
122 changed files with 10866 additions and 436 deletions

View File

@@ -860,6 +860,44 @@ describe('Pi worker pool', () => {
expect(cancelled).not.toContain('other');
});
it('refreshes idle worker resources immediately and defers an active run until settlement', async () => {
const workers = new Map<string, FakeWorker[]>();
const pool = new PiWorkerPool({
maxIdle: 4,
openWorker: async ({ conversation: input, existingSession }) => {
const worker = new FakeWorker(
`worker-${input.conversationId}-${(workers.get(input.conversationId)?.length ?? 0) + 1}`,
);
workers.set(input.conversationId, [...(workers.get(input.conversationId) ?? []), worker]);
return {
worker,
session: existingSession ?? {
piSessionId: `session-${input.conversationId}`,
sessionKey: `key-${input.conversationId}`,
},
};
},
});
await Promise.all([
pool.prepare(conversation('conversation-running')),
pool.prepare(conversation('conversation-idle')),
]);
pool.startTopLevel({
conversationId: 'conversation-running',
runId: 'run-running',
command: { type: 'prompt', message: 'running' },
});
await expect.poll(() => workers.get('conversation-running')![0]!.requests.length).toBe(1);
await pool.refreshResources();
expect(workers.get('conversation-idle')).toHaveLength(2);
expect(workers.get('conversation-idle')![0]!.stopped).toBe(true);
expect(workers.get('conversation-running')).toHaveLength(1);
workers.get('conversation-running')![0]!.emit({ type: 'agent_settled' });
await expect.poll(() => workers.get('conversation-running')).toHaveLength(2);
});
it('rebuilds stale idle workers before prompt and lets running workers settle first', async () => {
const workers = new Map<string, FakeWorker[]>();
const revisions: Array<{ conversationId: string; provider: number; resources: number }> = [];