Skip to content

Validation & Health

This area covers 24 features. Watch the walkthrough, then use the reference below — each feature links to the exact moment it appears (▶).

Who this is for: Reviewer / translation consultant. Each feature below lists the role/permission it requires.

Features

Per-cell validation toggle ▶ 00:11

As a translator or reviewer, I want to mark a translated cell as validated, so that I can indicate the translation quality meets project standards.

How it works. User clicks the validation button on a cell with non-empty translation → `emitCellValidate` event fires → cell status changes from 'unvalidated' to 'validated' → validation button updates to show emerald indicator and 'Validated' state → cell appears in 'Recent Examples' on memory page.

WhoReviewer / translation consultant PermissionsValidate/unvalidate: reviewer(300)
Key files

src/lib/sync/events-emit.ts:233-253
src/components/EditorTable.tsx:2636-2660
e2e/specs/validation/validate.smoke.spec.ts

Per-cell unvalidation (remove own validation) ▶ 00:00

As a translator or reviewer, I want to remove my validation from a cell, so that I can undo an accidental validation or change my quality assessment.

How it works. User opens validation popover on a self-validated cell → clicks 'Remove your validation' trash button → `emitCellUnvalidate` event fires → cell status changes from 'validated' to 'unvalidated' → button state flips back to unvalidated indicator → user is no longer listed in activeValidators.

WhoReviewer / translation consultant PermissionsValidate/unvalidate: reviewer(300)
Key files

src/lib/sync/events-emit.ts:256-268
src/components/EditorTable.tsx:3073-3086
e2e/specs/validation/cell-unvalidate.smoke.spec.ts

Bulk validation via selection bar ▶ 00:00

As a translator, I want to validate multiple cells at once via selection checkboxes, so that I can quickly mark a batch of translations as complete.

How it works. User selects 1+ cells via checkbox → SelectionBar appears with 'Validate N' button → user clicks button → `emitCellValidate` emitted for each selected unvalidated cell → success toast shows count validated → cells update to validated state.

WhoReviewer / translation consultant PermissionsValidate/unvalidate: reviewer(300)
Key files

src/components/SelectionBar.tsx:140-155
e2e/specs/editor/selection-bar-bulk-validate.smoke.spec.ts

Bulk unvalidation via selection bar ▶ 00:00

As a translator, I want to remove my validations from multiple cells at once, so that I can quickly undo a batch validation.

How it works. User selects 1+ self-validated cells → SelectionBar shows 'Remove my validations' button → user clicks → `emitCellUnvalidate` emitted for each selected validated cell → button becomes disabled or hidden → success indicated.

WhoReviewer / translation consultant PermissionsValidate/unvalidate: reviewer(300)
Key files

src/components/SelectionBar.tsx:164-178
e2e/specs/editor/selection-bar-unvalidate.smoke.spec.ts

Cross-user validation visibility ▶ 00:18

As a translator, I want to see who has validated each cell and when, so that I can understand the state of collaborative validation.

How it works. User hovers over or clicks validation button on a cell validated by others → validation popover opens → 'Validated by' list shows all active validators with timestamps → if current user validated it, a trash icon appears next to their name for removal.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/components/EditorTable.tsx:3066-3089
e2e/specs/collab/cross-user-validate.smoke.spec.ts

Decay-based per-cell health calculation ▶ 00:00

As a project manager, I want to see cell health derived from endorsement count and validation proximity, so that I can identify which cells need attention based on context validation.

How it works. For each cell: health = (1 - decay) * 100, where decay = max(0, 1 - endorsementCount / endorsementTarget). Validated cells (endorsementCount >= required) reach 100. Untranslated cells (empty status) have health 0. Health interpolates smoothly between 0-100 based on distance from validation gate.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/lib/health/decay-engine.ts:90-105
src/hooks/useHealth.ts:154-161

File-level health rollup ▶ 00:00

As a translator, I want to see overall file health, so that I can gauge progress on a particular file.

How it works. File health = mean(decay across all cells in file) converted to 0-100 scale. Updated incrementally as cells are validated. Shown as percentage in sidebar file list (two progress bars: amber for translated%, green for validated%).

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/lib/health/decay-engine.ts:150-177
src/components/FileRow.tsx:42-46

Project-level health rollup (local endorsement path) ▶ 00:00

As a project manager, I want to see overall project health, so that I can track translation completion quality across all files.

How it works. Project health = mean(decay across all cells in all files) converted to 0-100 scale. Displayed as colored HealthRing (red 0-33, amber 34-66, green 67-100) in StatusBar footer and ProjectCard. Updated as files load and cells are validated.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/lib/health/decay-engine.ts:150-177
src/hooks/useHealth.ts:216-226
src/components/HealthRing.tsx

Server-derived confidence-based health (FRO-181) ▶ 00:00

As a project manager, I want project health to reflect server-computed confidence scores from the example-retrieval graph, so that health reflects semantic similarity to validated cells rather than just endorsement counts.

How it works. When serverRollup option is provided to useHealth with projectHealth and fileHealth maps, those values override the endorsement-count path for file/project aggregates. Per-cell healthMap still derives from endorsement or per-cell confidence (via useCellConfidence overlay). Falls back to endorsement-count path if serverRollup is null.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/hooks/useHealth.ts:26-29, 215-219
src/hooks/useHealthRollup.ts:14-104

Cell confidence score (FTS5-based similarity) ▶ 00:00

As a translator, I want per-cell health to reflect semantic similarity to validated examples, so that I know which unvalidated cells are most likely ready to validate based on learned patterns.

How it works. useCellConfidence queries sync-worker /cell-confidence endpoint with cellIds and returns confidence scores 0-1 for each cell. Scores converted to health 0-100 and merged into healthMap. Validated cells immediately snap to 100; server ripple adjusts neighbors based on perHopDecay and maxHops settings. Optional overlay toggled via localStorage.

WhoReviewer / translation consultant PermissionsValidate/unvalidate: reviewer(300)
Key files

src/hooks/useCellConfidence.ts:29-112
src/lib/sync/cell-confidence-read.ts:46-68
src/components/ProjectWorkspace.tsx:1752-1774

Needs-attention marker on cells ▶ 00:00

As a translator, I want cells that lack sufficient surrounding validation context to be visually highlighted, so that I can prioritize validating cells in semantic neighborhoods.

How it works. For each cell: if decay > decayWarnThreshold (default 0.66), the cell shows 'needs attention' marker in UI (text in expansion panel or inline visual cue). Absence of marker is silence, not endorsement. Marker appears in cell expansion Staleness tab as text 'Needs attention — nearby context cells haven't been validated yet.'

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/lib/health/decay-engine.ts:116-134
src/components/EditorTable.tsx:2689-2693, 3705-3708

Health ring visual indicator ▶ 00:05

As a user, I want to see health as a colored circular progress indicator, so that I can quickly gauge validation state at a glance.

How it works. HealthRing component renders circular SVG arc proportional to health (0-100). Color: red (0-33), amber (34-66), green (67-100). At health=0, ring hidden but container occupies space (no layout shift). Used on cell rows (size 22px) and ProjectCard (size 22px) and StatusBar (size 18px).

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/components/HealthRing.tsx:1-63

Decay breakdown popover (health analytics) ▶ 00:00

As a project manager, I want to understand which cells are dragging down project health, so that I can focus validation efforts on high-impact areas.

How it works. User hovers over health ring (StatusBar or ProjectCard) → popover opens showing: overall health%, percentage of cells needing attention, list of 'biggest drags' (8 cells with lowest health, sorted ascending). Optional stale-source count displayed. Clicking a drag cell jumps to it in editor.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/components/DecayBreakdown.tsx:26-98
src/components/StatusBar.tsx:32-42

Project health on dashboard card ▶ 00:00

As a project manager, I want to see project health on the dashboard without opening the project, so that I can quickly compare health across many projects.

How it works. ProjectCard displays a HealthRing with server-fetched projectHealth (via useProjectHealth). Ring hidden if projectHealth is null (local-only project or fetch error). Health fetched from sync-worker /health-rollup route using project-scoped sync token.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/hooks/useProjectHealth.ts:51-90
src/components/ProjectCard.tsx:100-113

File progress tracking (translated and validated counts) ▶ 00:00

As a translator, I want to see how many cells in each file are translated and validated, so that I can monitor work completion.

How it works. useHealth.fileProgress Map tracks {translated, validated, total} per file. Derived from cell.status: 'translated' = not empty, 'validated' = status=='validated'. Displayed in FileRow as two inline progress bars (amber for translated%, green for validated%). Tooltip shows exact counts.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/hooks/useHealth.ts:110-140
src/components/FileRow.tsx:42-46, 125-134

Status bar with validation summary ▶ 00:18

As a translator, I want to see total counts of cells and validation state at a glance, so that I can quickly gauge overall progress.

How it works. StatusBar footer displays: total cells, translated count & %, unvalidated count (if > 0, shown in amber pill), validated count (if > 0, shown in green pill). Clickable health ring opens decay breakdown popover.

WhoReviewer / translation consultant PermissionsValidate/unvalidate: reviewer(300)
Key files

src/components/StatusBar.tsx:14-54

Open comment count per cell ▶ 00:00

As a translator, I want to see which cells have open discussion threads, so that I can prioritize addressing feedback.

How it works. useHealth.cellOpenCommentCount tracks count of open (unresolved) threads per cellId. EditorTable renders comment icon with badge showing count when > 0. Clicking icon opens comments panel. Cell expansion shows count in tooltip.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/hooks/useHealth.ts:127-132, 230-231
src/components/EditorTable.tsx:3654-3665

Project-level open comment count rollup ▶ 00:00

As a project manager, I want to see how many open comments exist across the project, so that I can gauge discussion volume.

How it works. useHealth.projectOpenCommentCount is sum of openCommentCount across all files. Displayed as badge on Comments nav link / tab. Used to route users to pending discussions.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/hooks/useHealth.ts:119, 137-138, 230-231

Rule infraction detection (separate from health) ▶ 00:00

As a QA manager, I want QA rule violations to be flagged separately from health, so that rule violations don't conflate with validation-based confidence.

How it works. useHealth.infractions is Map<cellId, RuleInfraction[]>. Populated by checkRulesForCell for enabled rules. Incremental: cached per cell signature (status, original, translated); only re-run on actual content change, not every keystroke. Infractions shown in cell expansion Issues tab.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/hooks/useHealth.ts:175-206
src/lib/rules/rule-engine.ts
src/components/EditorTable.tsx:1371

Rule violation waiver (dismiss infraction) ▶ 00:00

As a translator, I want to dismiss a QA rule violation with an optional justification, so that I can suppress false positives and explain intentional violations.

How it works. User clicks infraction in Issues tab → ViolationPopover opens → clicks 'Waive' → optional reason input appears → 'Confirm' → `emitCellWaive` fires with ruleId and reason → popover closes → infraction moves to 'Waived' subsection showing waive details (reason, username, timestamp).

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/lib/sync/events-emit.ts:287-302
src/components/ViolationPopover.tsx:54-84
e2e/specs/rules/waive-violation.smoke.spec.ts

Rule violation unwaiver (restore infraction) ▶ 00:00

As a translator, I want to restore a waived rule violation, so that I can reevaluate or remove a prior dismissal.

How it works. User clicks waived infraction in 'Waived' subsection → ViolationPopover opens showing waive details → 'Unwaive' button → click → `emitCellUnwaive` fires → popover closes → infraction moves back to active Issues list.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/lib/sync/events-emit.ts:314-326
src/components/ViolationPopover.tsx:59-62

Decay settings configuration (maxHops and attention threshold) ▶ 00:00

As a project manager, I want to tune how far validated cells' confidence ripples and at what point cells are flagged as needing attention, so that I can customize health scoring to project context.

How it works. ProjectSettings > Staleness & health section shows: 'Max hops' input (1-20, default 4) controlling propagation radius in confidence graph, and 'Attention threshold' input (0-1, default 0.66) controlling when 'needs attention' marker appears. Changes saved to project.decaySettings.

WhoReviewer / translation consultant PermissionsValidate/unvalidate cells: reviewer(300); health/confidence is derived-on-read (no role to view)
Key files

src/components/ProjectSettings/DecaySettingsSection.tsx:23-86

Living memory validated cell recent examples ▶ 00:00

As a translator, I want to see recently validated cells as reference examples, so that I can learn from team translations and maintain consistency.

How it works. Memory page > Recent Examples section displays ValidatedCellCard for each validated cell (status == 'validated') across all project files. Each card shows source text (aria-label='Source text') and translation (aria-label='Translation'). Sorted by most recent validation.

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

e2e/specs/projects/living-memory-validated-cell-card.smoke.spec.ts

Stale source indicator (AD-9) ▶ 00:00

As a translator, I want to see when the source text has changed since I last translated a cell, so that I can identify cells needing re-translation.

How it works. StaleSourceIndicator component shows amber triangle icon (AlertTriangle) with tooltip 'The source has changed since this translation was last revised.' when cell's source event_id differs from target row's staleness pin. Icon appears in cell action rail. Managed mode: parent passes staleCellIds Set; standalone mode: hook fetches internally.

WhoProject lead (source steward) PermissionsSource content edits: project_lead(500)
Key files

src/components/StaleSourceIndicator.tsx:55-126
src/hooks/useStaleSourceCells.ts