diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1d1da99e..b80505d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,6 +5,16 @@ All notable changes to the Fovea project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.5.3] - 2026-06-24
+
+The 0.5.3 patch fixes a claims-workspace interaction bug ([#177](https://github.com/parafovea/fovea/pull/177)). No API shapes change and nothing is breaking.
+
+### Fixed
+
+#### Clicking a Claim Card No Longer Switches to the Summary Tab
+
+- In the video summary editor's Claims tab, clicking a claim card switched the interface back to the Summary tab, which is not what clicking a card should do. A card now selects in place: it is marked selected on the Claims tab and records its source spans so the Summary tab highlights the claim's provenance only if the user chooses to switch there. The card's selected styling, previously bound to a state value that was never set, is now driven by the selected-claim state (`annotation-tool/src/components/video/VideoSummaryEditor.tsx`, `annotation-tool/src/components/claims/ClaimsViewer.tsx`).
+
## [0.5.2] - 2026-06-22
The 0.5.2 patch fixes a Safari-only failure ([#143](https://github.com/parafovea/fovea/issues/143)) where a video in the annotation workspace blacked out the moment it was paused and jumped position on resume, while Chrome and Firefox played it back correctly. The cause was twofold: the video stream endpoint mishandled the byte-range requests Safari issues but Chrome does not, and WebKit dropped the paused video frame from its compositor. No API shapes change and nothing is breaking.
diff --git a/annotation-tool/package.json b/annotation-tool/package.json
index 93162c5a..a1f349d8 100644
--- a/annotation-tool/package.json
+++ b/annotation-tool/package.json
@@ -1,7 +1,7 @@
{
"name": "@fovea/annotation-tool",
"private": true,
- "version": "0.5.2",
+ "version": "0.5.3",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/annotation-tool/src/components/claims/ClaimsViewer.tsx b/annotation-tool/src/components/claims/ClaimsViewer.tsx
index 357f52c4..39166762 100644
--- a/annotation-tool/src/components/claims/ClaimsViewer.tsx
+++ b/annotation-tool/src/components/claims/ClaimsViewer.tsx
@@ -129,6 +129,8 @@ const ClaimTreeNode = memo(function ClaimTreeNode({
return (
state.selectedClaimId)
const extracting = useClaimsUiStore((state) => state.extracting)
const extractionJobId = useClaimsUiStore((state) => state.extractionJobId)
const extractionProgress = useClaimsUiStore((state) => state.extractionProgress)
@@ -399,16 +398,15 @@ const VideoSummaryEditor = forwardRef {
setActiveTab(value)
- // Clear highlighting when switching tabs
- if (value === 'summary') {
- setHighlightedSpans([])
- setHighlightedClaimId(null)
- }
}
const handleClaimSelect = (claimId: string, sourceSpans: ClaimTextSpan[]) => {
- // Switch to Summary tab to show highlighted text
- setActiveTab('summary')
+ // Select the claim in place on the Claims tab; do NOT navigate away.
+ // Selecting a card marks it as selected and records its source spans so
+ // the Summary tab highlights the claim's provenance if and when the user
+ // chooses to switch there (dismissed with the "×" on that view). Clicking
+ // a card previously yanked the user to the Summary tab, which is not what
+ // clicking a card should do.
setHighlightedSpans(sourceSpans)
setHighlightedClaimId(claimId)
}
@@ -626,7 +624,7 @@ const VideoSummaryEditor = forwardRef {
+ /**
+ * Seed a summary with a single leaf claim, open the Claims tab, click the
+ * claim card, and assert the click selects the card and leaves the user on
+ * the Claims tab rather than switching to the Summary tab.
+ */
+ test('clicking a claim card selects it and stays on the Claims tab', async ({
+ page,
+ testVideo,
+ testPersona,
+ workerSessionToken,
+ annotationWorkspace,
+ }) => {
+ const cookie = `session_token=${workerSessionToken}`
+
+ // Seed a summary for (video, persona) with source text the claim spans.
+ const summaryRes = await fetch(`${API}/api/summaries`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json', Cookie: cookie },
+ body: JSON.stringify({
+ videoId: testVideo.id,
+ personaId: testPersona.id,
+ summary: [{ type: 'text', content: 'A red car drives through the intersection.' }],
+ }),
+ })
+ expect(summaryRes.ok).toBe(true)
+ const summary = await summaryRes.json()
+
+ // Seed a single leaf claim (no subclaims), carrying source text spans so
+ // the old behavior would have shown the Summary tab's highlight view.
+ const claimText = `Card-select claim ${Date.now()}`
+ const claimRes = await fetch(`${API}/api/summaries/${summary.id}/claims`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json', Cookie: cookie },
+ body: JSON.stringify({
+ summaryType: 'video',
+ text: claimText,
+ audio: ['speech'],
+ textSpans: [{ charStart: 0, charEnd: 9 }],
+ }),
+ })
+ expect(claimRes.ok).toBe(true)
+
+ // Open the summary dialog, pick the persona, switch to the Claims tab.
+ await annotationWorkspace.navigateTo(testVideo.id)
+ await page.waitForSelector('[data-testid="video-player"], video', { timeout: 10000 })
+ await page.getByRole('button', { name: /edit summary/i }).click()
+ const dialog = page.getByRole('dialog')
+ await expect(dialog).toBeVisible()
+ const personaSelect = dialog.getByLabel(/select persona/i)
+ if (await personaSelect.isVisible()) {
+ await personaSelect.click()
+ await page
+ .getByRole('option')
+ .filter({ hasText: new RegExp('^' + testPersona.name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') + ' \\(') })
+ .first()
+ .click()
+ await page.waitForTimeout(500)
+ }
+
+ const summaryTab = dialog.locator('[role="tab"]').filter({ hasText: 'Summary' })
+ const claimsTab = dialog.locator('[role="tab"]').filter({ hasText: 'Claims' })
+ await claimsTab.click()
+
+ // Precondition: the claim card is shown, unselected, on the Claims tab.
+ await expect(page.getByText(claimText)).toBeVisible({ timeout: 10000 })
+ const card = dialog.getByTestId('claim-card')
+ await expect(card).toHaveAttribute('data-selected', 'false')
+
+ // Click the card body (the claim text, not an action button).
+ await page.getByText(claimText).click()
+
+ // The card is now selected, and we are still on the Claims tab — the
+ // claims viewer stays visible, the Claims tab stays active, and the
+ // Summary tab's highlight view never takes over.
+ await expect(card).toHaveAttribute('data-selected', 'true')
+ await expect(dialog.locator('[data-tour-id="claims-viewer"]')).toBeVisible()
+ await expect(claimsTab).toHaveAttribute('aria-selected', 'true')
+ await expect(summaryTab).toHaveAttribute('aria-selected', 'false')
+ await expect(
+ page.getByText(/showing highlighted text for selected claim/i)
+ ).toBeHidden()
+ })
+})
diff --git a/docs/docs/project/changelog.md b/docs/docs/project/changelog.md
index 6007b5a4..5ffc06a2 100644
--- a/docs/docs/project/changelog.md
+++ b/docs/docs/project/changelog.md
@@ -11,6 +11,16 @@ All notable changes to the Fovea project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+## [0.5.3] - 2026-06-24
+
+The 0.5.3 patch fixes a claims-workspace interaction bug ([#177](https://github.com/parafovea/fovea/pull/177)). No API shapes change and nothing is breaking.
+
+### Fixed
+
+#### Clicking a Claim Card No Longer Switches to the Summary Tab
+
+- In the video summary editor's Claims tab, clicking a claim card switched the interface back to the Summary tab, which is not what clicking a card should do. A card now selects in place: it is marked selected on the Claims tab and records its source spans so the Summary tab highlights the claim's provenance only if the user chooses to switch there. The card's selected styling, previously bound to a state value that was never set, is now driven by the selected-claim state (`annotation-tool/src/components/video/VideoSummaryEditor.tsx`, `annotation-tool/src/components/claims/ClaimsViewer.tsx`).
+
## [0.5.2] - 2026-06-22
The 0.5.2 patch fixes a Safari-only failure ([#143](https://github.com/parafovea/fovea/issues/143)) where a video in the annotation workspace blacked out the moment it was paused and jumped position on resume, while Chrome and Firefox played it back correctly. The cause was twofold: the video stream endpoint mishandled the byte-range requests Safari issues but Chrome does not, and WebKit dropped the paused video frame from its compositor. No API shapes change and nothing is breaking.
diff --git a/docs/package.json b/docs/package.json
index dd6260f9..39e6f064 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -1,6 +1,6 @@
{
"name": "docs",
- "version": "0.5.2",
+ "version": "0.5.3",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
diff --git a/model-service/package.json b/model-service/package.json
index 7708bd06..973c9526 100644
--- a/model-service/package.json
+++ b/model-service/package.json
@@ -1,6 +1,6 @@
{
"name": "fovea-model-service",
- "version": "0.5.2",
+ "version": "0.5.3",
"description": "AI model inference service for video annotation",
"scripts": {
"dev": "source venv/bin/activate && uvicorn src.main:app --reload --host 0.0.0.0 --port 8000",
diff --git a/model-service/pyproject.toml b/model-service/pyproject.toml
index 1f2bcc53..814425db 100644
--- a/model-service/pyproject.toml
+++ b/model-service/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "fovea-model-service"
-version = "0.5.2"
+version = "0.5.3"
description = "Model service for fovea video annotation tool"
requires-python = ">=3.12"
dependencies = [
diff --git a/package.json b/package.json
index d5412261..bde34b09 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "fovea",
"private": true,
- "version": "0.5.2",
+ "version": "0.5.3",
"description": "FOVEA - Flexible Ontology Visual Event Analyzer",
"packageManager": "pnpm@10.15.0",
"engines": {
diff --git a/server/package.json b/server/package.json
index 70a854ac..1bb815aa 100644
--- a/server/package.json
+++ b/server/package.json
@@ -1,6 +1,6 @@
{
"name": "@fovea/server",
- "version": "0.5.2",
+ "version": "0.5.3",
"private": true,
"type": "module",
"scripts": {