Conversation
ProjectContext hydrated activeProject from localStorage without checking whether the project still existed server-side. If a project was deleted in another session, the chat page would render its empty state and any query would 404. The sidebar dropdown would also disagree with itself (stored ID not in the fetched list, so it fell back to the placeholder). Reconcile the stored project against useProjects() once the list loads and clear it if the ID isn't present.
Uploading multiple contradictory documents back-to-back spawned parallel background scans that each detected the same chunk pair (in opposite orders) before either had committed, producing two contradiction records for what the spec requires to be one. Add a functional unique index on (project_id, LEAST(chunk_a_id, chunk_b_id), GREATEST(chunk_a_id, chunk_b_id)) so the DB enforces pair uniqueness regardless of insertion order. Have the repository catch IntegrityError from the race-loser insert and return None; the service then skips the found++ bump instead of propagating the error.
The synthesis gate error told users to resolve open contradictions but the text was static, forcing them to find the nav link themselves. Requirement FR-5.1 specifies the message should link to the contradictions page. Wrap the word 'contradiction(s)' in a Link and fix singular/plural grammar for the count=1 case.
The earlier fix cleared a stale activeProject only when useProjects refetched. If the project disappeared while the user stayed on one page (no navigation, no window focus), the cache stayed warm, reconciliation never fired, and the next chat send 404'd with 'Error: Project not found' — leaving the user stuck. Introduce ApiError (carries the HTTP status) and have useChat catch status=404 by clearing activeProject and invalidating the projects query. The chat page then falls back to its 'Select a project' placeholder on the next render.
useChat held messages in local state that persisted across project switches, so chatting in project A, switching to B, and scrolling up would show A's messages alongside B's — and the next send would carry stale visual context into the new project. Apply the same render-phase reset pattern SynthesisPage uses: track the previous projectId and clear messages + isLoading when it changes. Documents and Contradictions already isolate state via React Query keyed on projectId; this brings Chat in line with that behavior.
Ten-scenario manual verification covering all four bug-fix commits plus general chat, documents, contradictions, and synthesis flows. Tied to the seeded Aegis Station demo project.
The checklist referenced tester-local paths under /tmp and a Windows Temp dir — fine for the original run but unusable for anyone else. Promote both fixture sets into docs/qa/fixtures/: the small contradicting pair used by scenario 6, and the six-document Aegis Station demo referenced by the reseed block. Update checklist paths accordingly and add a README explaining what each set is for.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Seven commits fixing four bugs found in QA against
docs/REQUIREMENTS.md, plus the QA assets (checklist + fixtures) that verify them.Bug fixes
5a684bc(reload path) +d31ab05(no-reload self-heal on 404)02fc8173bc377546d5510Supporting work
f205ac2— QA checklist (docs/qa/pr-4-checklist.md): 10 scenarios tagged by commitc800a8f— QA fixtures (docs/qa/fixtures/): contradicting-pair + Aegis Station demo corpus so the checklist is reproducible anywhereTest plan
uv run pytest tests/ -v -m "not integration"— 87/87 passnpm test— 175/175 pass (new: ProjectContext reconciliation, useChat 404 self-heal, useChat reset-on-switch)e5f6a7b8c9d0applied to dev DB; unique-pair index rejects duplicate inserts/contradictions.mddownload HTTP 200cdinto repo, follow scenarios — all paths are now repo-relative)Files changed
Backend
backend/alembic/versions/20260418_contradiction_unique_pair.py(new)backend/app/models/contradiction_repository.pybackend/app/services/contradiction_service.pyFrontend
frontend/src/contexts/ProjectContext.tsxfrontend/src/contexts/ProjectContext.test.tsx(new)frontend/src/lib/api.ts(addsApiErrorclass)frontend/src/hooks/useChat.tsfrontend/src/hooks/useChat.test.tsx(moved from.ts, expanded)frontend/src/pages/SynthesisPage.tsxfrontend/src/pages/SynthesisPage.test.tsxDocs + QA
docs/qa/pr-4-checklist.md(new)docs/qa/fixtures/README.md(new)docs/qa/fixtures/contradicting-pair/doc-{a,b}.md(new)docs/qa/fixtures/aegis-demo/*.{md,txt,pdf}(new)