feat(architect): Complete auth pages phase decomposition

Decomposed "Data Display Components - Tables, Grids, Nutrition Display"
phase into 6 executable tasks for migrating MUI components to shadcn/ui:

1. Setup shadcn/ui infrastructure (foundation)
2. Migrate NutritionDisplay component (48-field grid)
3. Migrate RecipeRankings and RecipeStatus components
4. Replace @mui/x-data-grid with TanStack Table
5. Test and verify (checkpoint for human review)
6. Remove MUI dependencies and clean up

Tasks follow logical dependency chain with parallel execution where
possible. Includes comprehensive verification checklist before cleanup.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Lukas May
2026-02-10 09:54:25 +01:00
parent 37583b7083
commit 41c812e4b8

View File

@@ -163,6 +163,90 @@ describe('Decompose Workflow E2E', () => {
});
});
describe('decompose conflict detection', () => {
it('should reject if a decompose agent is already running for the same phase', async () => {
vi.useFakeTimers();
const initiative = await harness.createInitiative('Test Project');
const phases = await harness.createPhasesFromBreakdown(initiative.id, [
{ name: 'Phase 1' },
]);
// Long-running decompose agent
harness.setAgentScenario('decomposer-1', { status: 'done', delay: 999999 });
await harness.caller.spawnArchitectDecompose({
name: 'decomposer-1',
phaseId: phases[0].id,
});
// Second decompose for same phase should be rejected
await expect(
harness.caller.spawnArchitectDecompose({
name: 'decomposer-2',
phaseId: phases[0].id,
}),
).rejects.toThrow(/already running/);
});
it('should auto-dismiss stale decompose agents before checking', async () => {
vi.useFakeTimers();
const initiative = await harness.createInitiative('Test Project');
const phases = await harness.createPhasesFromBreakdown(initiative.id, [
{ name: 'Phase 1' },
]);
// Decompose agent that crashes immediately
harness.setAgentScenario('stale-decomposer', { status: 'error', error: 'crashed' });
await harness.caller.spawnArchitectDecompose({
name: 'stale-decomposer',
phaseId: phases[0].id,
});
await harness.advanceTimers();
// New decompose should succeed
harness.setArchitectDecomposeComplete('new-decomposer', [
{ number: 1, name: 'Task 1', content: 'Do it', type: 'auto', dependencies: [] },
]);
const agent = await harness.caller.spawnArchitectDecompose({
name: 'new-decomposer',
phaseId: phases[0].id,
});
expect(agent.mode).toBe('decompose');
});
it('should allow decompose for different phases simultaneously', async () => {
vi.useFakeTimers();
const initiative = await harness.createInitiative('Test Project');
const phases = await harness.createPhasesFromBreakdown(initiative.id, [
{ name: 'Phase 1' },
{ name: 'Phase 2' },
]);
// Long-running agent on phase 1
harness.setAgentScenario('decomposer-p1', { status: 'done', delay: 999999 });
await harness.caller.spawnArchitectDecompose({
name: 'decomposer-p1',
phaseId: phases[0].id,
});
// Decompose on phase 2 should succeed
harness.setArchitectDecomposeComplete('decomposer-p2', [
{ number: 1, name: 'Task 1', content: 'Do it', type: 'auto', dependencies: [] },
]);
const agent = await harness.caller.spawnArchitectDecompose({
name: 'decomposer-p2',
phaseId: phases[1].id,
});
expect(agent.mode).toBe('decompose');
});
});
describe('task persistence', () => {
it('should create tasks from decomposition output', async () => {
const initiative = await harness.createInitiative('Test Project');