diff --git a/codev/projects/bugfix-1110-bugfix-artifact-canvas-test-su/status.yaml b/codev/projects/bugfix-1110-bugfix-artifact-canvas-test-su/status.yaml new file mode 100644 index 000000000..3e7350c55 --- /dev/null +++ b/codev/projects/bugfix-1110-bugfix-artifact-canvas-test-su/status.yaml @@ -0,0 +1,16 @@ +id: bugfix-1110 +title: bugfix-artifact-canvas-test-su +protocol: bugfix +phase: pr +plan_phases: [] +current_plan_phase: null +gates: + pr: + status: pending + requested_at: '2026-06-28T06:00:05.286Z' +iteration: 1 +build_complete: false +history: [] +started_at: '2026-06-28T05:52:25.996Z' +updated_at: '2026-06-28T06:00:05.287Z' +pr_ready_for_human: true diff --git a/codev/state/bugfix-1110_thread.md b/codev/state/bugfix-1110_thread.md new file mode 100644 index 000000000..16ff68d0a --- /dev/null +++ b/codev/state/bugfix-1110_thread.md @@ -0,0 +1,40 @@ +# bugfix-1110 thread + +## Investigate + +Issue #1110: flaky test `surfaces a synchronous FileAdapter.watch() failure via onError without throwing (D2)` +in `packages/artifact-canvas/src/components/__tests__/artifact-canvas.test.tsx`. + +Verified root cause against source (lines 157-166): +- Line 163: `await waitFor(() => expect(onError).toHaveBeenCalled());` +- Line 164: bare synchronous `expect(document.querySelector('p[data-line]')).not.toBeNull();` + +The async `read()` render can resolve after `onError` fires; under CI load the DOM query at +line 164 lands before the paragraph is in the tree. Race → intermittent failure. + +Sibling test (line 171) uses the correct pattern: `await waitFor(() => expect(...).not.toBeNull())`. + +Fix: wrap line 164's assertion in `waitFor`. One-line semantic-preserving change. Confirmed +BUGFIX scope (trivial, mechanical, no production code change). + +## Fix + +Applied the one-line change (line 164 wrapped in `waitFor`). Verified: +- `pnpm --filter @cluesmith/codev-artifact-canvas test` → 56/56 pass +- D2 test stress-run 5× in isolation → 5/5 pass +- porch checks: build ✓ (5.2s), tests ✓ (20.7s) +Committed `[Bugfix #1110]`, advanced to PR phase. + +## PR + +PR #1111 opened (https://github.com/cluesmith/codev/pull/1111). +Running CMAP (gemini/codex/claude) — consult needs `--issue 1110` to disambiguate +the many projects visible in this worktree's `codev/projects/`. + +CMAP verdicts: gemini=APPROVE, codex=APPROVE, claude=APPROVE. +Claude flagged the identical bare-assertion race in the sibling D2 adapter-error +test (line 133) — the issue invited this ride-along, so applied the same waitFor +wrap (commit 846b53dc). 56/56 pass. Posted CMAP results as PR comment. + +`pr` gate requested via `porch done`. Notified architect. **Waiting for human +approval** — will merge only after `porch approve bugfix-1110 pr`. diff --git a/packages/artifact-canvas/src/components/__tests__/artifact-canvas.test.tsx b/packages/artifact-canvas/src/components/__tests__/artifact-canvas.test.tsx index 0daf00464..6ebfc453a 100644 --- a/packages/artifact-canvas/src/components/__tests__/artifact-canvas.test.tsx +++ b/packages/artifact-canvas/src/components/__tests__/artifact-canvas.test.tsx @@ -130,7 +130,7 @@ describe('ArtifactCanvas (Phase 3)', () => { const err = vi.spyOn(console, 'error').mockImplementation(() => {}); render(); await waitFor(() => expect(onError).toHaveBeenCalled()); - expect(document.querySelector('p[data-line]')).not.toBeNull(); // still rendered, no throw + await waitFor(() => expect(document.querySelector('p[data-line]')).not.toBeNull()); // still rendered, no throw err.mockRestore(); }); @@ -161,7 +161,7 @@ describe('ArtifactCanvas (Phase 3)', () => { const err = vi.spyOn(console, 'error').mockImplementation(() => {}); expect(() => render()).not.toThrow(); await waitFor(() => expect(onError).toHaveBeenCalled()); - expect(document.querySelector('p[data-line]')).not.toBeNull(); // read succeeded → content still renders + await waitFor(() => expect(document.querySelector('p[data-line]')).not.toBeNull()); // read succeeded → content still renders err.mockRestore(); });