Skip to content

Living Memory

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: Translator / project lead. Each feature below lists the role/permission it requires.

Features

View Living Memory page (Instructions + Standards + Recent Examples sections) ▶ 00:00

As a translator, I want to view my project's Living Memory page to see all three sections: Instructions (authored guidance), Standards (quality rules), and Recent Examples (validated translations).

How it works. User navigates to /project/:id/memory. Page renders within the ProjectWorkspace shell with a title 'Living Memory', a liveness indicator, and a '0 validated' badge. Three sections are visible: Instructions, Standards, and Recent Examples. Each section has appropriate descriptions. No back button appears (shell owns back navigation).

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:444-701
src/components/LivingMemoryPage.tsx:530-569
e2e/specs/projects/living-memory.smoke.spec.ts:16-41

Add Instructions entry ▶ 00:00

As a maintainer, I want to add an instruction entry to guide the AI on project-specific translation rules.

How it works. User clicks '+ Add' button in Instructions section. An inline EntryForm appears with a textarea (min-h-[72px]). User types text and clicks Save (only enabled if text.trim() is truthy). Entry saves to project settings and appears in the Instructions section. Cancel closes the form without saving. Author name and created date are shown on the card. Add button appears only for users with MAINTAINER role (level >= 600).

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:225-257
src/components/LivingMemoryPage.tsx:305-437
src/components/LivingMemoryPage.tsx:649-662
src/components/LivingMemoryPage.tsx:55-69
src/components/LivingMemoryPage.tsx:515-518
e2e/specs/projects/living-memory-add-entry.smoke.spec.ts

Edit Instructions entry ▶ 00:00

As a maintainer, I want to edit an existing instruction entry to correct or refine project guidance.

How it works. User hovers over an entry card in the Instructions section. An 'Edit entry' button (aria-label) appears. Clicking opens an inline EntryForm pre-filled with the original text. User modifies text and clicks Save. Updated text replaces the original in the section. Cancel closes the form without updating. Only visible to MAINTAINER+ role users.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:376-401
src/components/LivingMemoryPage.tsx:366-407
src/components/LivingMemoryPage.tsx:520-523
src/components/LivingMemoryPage.tsx:71-77
e2e/specs/projects/living-memory-edit-entry.smoke.spec.ts

Delete Instructions entry ▶ 00:00

As a maintainer, I want to delete an instruction entry to remove outdated or incorrect guidance.

How it works. User hovers over an entry card. A red 'Delete entry' button (aria-label) appears on the right side. Clicking opens a confirmation Dialog with title 'Delete entry?' and text 'This will permanently remove the entry. This action cannot be undone.' Dialog has Cancel and Delete (destructive variant) buttons. Clicking Delete removes the entry and closes the dialog. Clicking Cancel keeps the entry. Only visible to MAINTAINER+ role users.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:378-399
src/components/LivingMemoryPage.tsx:411-434
src/components/LivingMemoryPage.tsx:525-528
src/components/LivingMemoryPage.tsx:79-84
e2e/specs/projects/living-memory-delete-entry.smoke.spec.ts

Add Standards entry ▶ 00:00

As a maintainer, I want to add a standard (quality rule) the team enforces on all translations.

How it works. User navigates to Standards section. Clicks '+ Add' button. An inline EntryForm with textarea appears. User types a standard (e.g., 'Always preserve proper nouns untranslated'). Clicks Save. Entry persists and appears in the Standards section with author and date. Cancel closes the form. Only available to MAINTAINER+ role users.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:305-437
src/components/LivingMemoryPage.tsx:664-677
e2e/specs/projects/living-memory-standards-section.smoke.spec.ts

Edit Standards entry ▶ 00:00

As a maintainer, I want to update a standard rule to clarify or correct team policy.

How it works. Same as Instructions edit: hover entry → click 'Edit entry' → inline form pre-filled with current text → modify → Save updates, Cancel cancels.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:305-437
src/components/LivingMemoryPage.tsx:664-677

Delete Standards entry ▶ 00:00

As a maintainer, I want to remove a standard rule that is no longer relevant.

How it works. Same as Instructions delete: hover entry → click red 'Delete entry' → confirmation dialog → confirm to remove.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:305-437
src/components/LivingMemoryPage.tsx:664-677

View Recent Examples (validated translations) ▶ 00:05

As a translator, I want to see validated source→target pairs from my team to understand approved translations.

How it works. Recent Examples section renders below Standards. Cells are loaded from useLivingMemory (filtered by status='validated', sorted descending by lastEditAt, grouped by file). Each validated cell appears as a ValidatedCellCard showing: reference label (if present), source text (aria-label='Source text'), divider, target text (aria-label='Translation'), and validator names in badges. Cards are grouped by file name with FileGroupHeading. If no validated cells exist, RecentExamplesEmpty state shows 'No validated translations yet' and explanatory text. A skeleton loader shows while loading.

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

src/components/LivingMemoryPage.tsx:129-179
src/components/LivingMemoryPage.tsx:180-189
src/components/LivingMemoryPage.tsx:192-223
src/components/LivingMemoryPage.tsx:679-697
src/components/LivingMemoryPage.tsx:107-127
src/components/LivingMemoryPage.tsx:86-103
src/hooks/useLivingMemory.ts:28-49
e2e/specs/projects/living-memory-validated-cell-card.smoke.spec.ts

Recent Examples empty state ▶ 00:00

As a new project owner, I want to see an empty state explaining what Recent Examples are and how they are populated.

How it works. On a fresh project with no validated cells, the Recent Examples section shows RecentExamplesEmpty: a centered icon + heading 'No validated translations yet' + explanation text: 'When translators and reviewers reach the required validation threshold on a cell, that source→target pair appears here. The AI draws on these pairs in every subsequent draft.' Page header badge shows '0 validated'.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:107-127
src/components/LivingMemoryPage.tsx:541-560
e2e/specs/projects/living-memory-empty-state.smoke.spec.ts

Validated cells truncation warning ▶ 00:00

As a project owner with many files, I want to know if the Recent Examples list is incomplete due to performance limits.

How it works. If a project has more than 40 files (MAX_FILES), an AlertTriangle warning bar appears below the Brief section: 'Showing cells from the first {fileCount} files.' with TODO comment referencing SWARM-TODO(living-mem-server) for a dedicated endpoint.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:630-644
src/hooks/useLivingMemory.ts:80-81
src/hooks/useLivingMemory.ts:157-168

Role-based edit affordance lock (Instructions/Standards) ▶ 00:00

As a translator (non-maintainer), I want to understand why I cannot edit entries.

How it works. When a user lacks MAINTAINER role or is offline, the '+ Add' button does not appear in Instructions/Standards sections. Instead, a lock icon with tooltip appears: 'Editing requires Maintainer role (600) or above.' or 'You are offline. Reconnect to edit.' (depending on reasonCannotEdit). Non-editable users see entry cards without Edit/Delete buttons. This mirrors the FRO-255 pattern.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:260-287
src/components/LivingMemoryPage.tsx:330-343
src/components/LivingMemoryPage.tsx:656-661
src/components/LivingMemoryPage.tsx:671-676
src/hooks/useProjectSettings.ts:14-19
src/hooks/useProjectSettings.ts:278-279

Page navigation (back to editor via sidebar) ▶ 00:00

As a translator, I want to navigate back to the project editor from the Living Memory page.

How it works. The Living Memory page renders inside the ProjectWorkspace shell. No back button on the page itself (shell owns navigation). User can click any file row in the persistent left sidebar to navigate back to the editor at /project/:id/file/:fileId. Sidebar shows the same file list as the editor. URL reflects the new route.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:530-699
e2e/specs/projects/living-memory-back-nav.smoke.spec.ts

Liveness indicator (sync status) ▶ 00:00

As a user, I want to see whether the Living Memory data is syncing or if I'm offline.

How it works. Next to the 'Living Memory' heading, a small circular indicator appears: green (synced/ready) → amber with pulse (updating) → red (offline). Hovering shows a tooltip with the status label (e.g., 'All caught up' for ready, 'Syncing' for updating, 'Offline' for offline). Status is derived from useLiveness(cells.length).

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:539-553
src/hooks/useLiveness.ts

Validated cell count badge ▶ 00:05

As a project owner, I want to see at a glance how many validated translations exist.

How it works. Page header shows a badge: '{count} validated' (e.g., '5 validated', '0 validated'). Count uses toLocaleString() for thousands formatting. Skeleton placeholder appears while loading. Badge is visible next to the liveness indicator.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:554-560

Translation Brief section (view/create/edit/generate) ▶ 00:00

As a maintainer, I want to define and manage the translation brief (project skopos/guidelines) so the AI understands the project context.

How it works. Between the page header and the entry sections, a 'Translation brief' section appears. It shows: a status badge ('none' → 'draft' → 'complete') and optionally a 'Summary out of date' badge if L1 is stale. When no brief exists (status='none'), a dashed card says 'Capture this project's purpose...' with a 'Create brief' button (only for MAINTAINER+). When a brief exists, it shows the L1 summary (or 'No summary generated yet.' if only parameters are set). Edit/generate buttons appear for MAINTAINER+ users. Brief can be created via BriefBuilder dialog, edited by clicking 'Edit brief', and L1 summary can be generated/regenerated.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:587-628
src/components/LivingMemoryPage.tsx:480-513
src/components/brief/BriefSection.tsx
src/components/brief/BriefBuilder.tsx

Brief step-by-step builder wizard ▶ 00:00

As a maintainer, I want to fill in a structured translation brief with guided questions.

How it works. Clicking 'Create brief' or 'Edit brief' opens a BriefBuilder dialog. Dialog shows: 1) Optional document pre-fill step (if onExtractDocument is provided), 2) Sequential field steps (from BRIEF_FIELDS schema) with label, helper text, and textarea for each parameter, 3) Freeform notes step. User can navigate Back/Next between steps. 'Save draft' persists current parameters without L1 generation. 'Save & generate summary' (on final step) saves and triggers L1 generation. 'Help me write this' button (if onHelpDraft provided) opens LLM to draft the field. Back button disabled on step 0. Dialog only allows editing when canEdit=true.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/brief/BriefBuilder.tsx:28-119
src/components/LivingMemoryPage.tsx:598-627

Brief document pre-fill (extract from pasted text) ▶ 00:00

As a maintainer, I want to quickly populate the brief by pasting an existing document.

How it works. In the BriefBuilder dialog, if onExtractDocument is provided (i.e., completionSettings is not null), a 'Pre-fill from text' step appears at the start. A dashed card contains a textarea with placeholder 'Paste notes or an existing brief...' and a button 'Pre-fill from text'. User pastes text and clicks the button. The LLM extracts brief fields from the text and auto-populates parameters (preserving any manual edits). Button is disabled if textarea is empty.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/brief/BriefBuilder.tsx:122-135
src/components/LivingMemoryPage.tsx:619-625

Brief L1 summary generation ▶ 00:00

As a maintainer, I want the AI to generate a concise L1 summary of the brief parameters.

How it works. In BriefSection, a 'Generate summary' button appears when a brief exists but l1Summary is null. A 'Regenerate summary' button appears if l1Summary exists but stale=true. Clicking triggers handleGenerate() which calls generateL1Summary() from the LLM. Button shows 'Generating…' and is disabled while in flight. On success, l1Summary is populated and displayed. On error, button returns to enabled state and error is logged. During generation, Edit/generate buttons are locked (busy=true) to prevent concurrent saves from clobbering the brief.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:495-513
src/components/brief/BriefSection.tsx:44-49
src/lib/brief/brief.ts:isL1Stale

Brief field help (AI draft assistance) ▶ 00:00

As a maintainer, I want the AI to help me draft a specific brief field.

How it works. Inside BriefBuilder, when on a field step and onHelpDraft is provided (completionSettings is not null), a 'Help me write this' button appears below the textarea. Clicking calls draftField() which uses the LLM to generate a draft answer for that field (e.g., audience, tone, format constraints). Draft text is inserted into the textarea, replacing the current value. Button is disabled while in flight.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/brief/BriefBuilder.tsx:80-88
src/components/LivingMemoryPage.tsx:615-617

Terminology cross-link ▶ 00:00

As a project owner, I want to navigate to the Terminology page to manage key terms alongside Living Memory guidance.

How it works. Below the main header and liveness badge, a light blue callout card appears: 'Terminology captures your project's key terms and preferred renderings. [Open Terminology]'. Clicking the 'Open Terminology' button navigates to /project/:id/terminology.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:570-584

Entry author and timestamp metadata ▶ 00:00

As a team member, I want to see who created each instruction/standard and when.

How it works. Each entry card in Instructions/Standards sections shows a small footer: '{author} · {formatted date}'. Author is captured at creation time from session.username. Date is formatted using new Date(entry.createdAt).toLocaleDateString().

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:402-404

Validated cell card with group/file reference ▶ 00:00

As a reviewer, I want to see which file and location a validated translation comes from.

How it works. Each ValidatedCellCard in Recent Examples shows an optional reference label at the top (aria-label={`Reference: ${cell.group}`}): file reference in small mono font (text-[10px] font-mono). Below that, the source text, a horizontal divider, and the target text. Validators are shown as small badges with Users icon.

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

src/components/LivingMemoryPage.tsx:131-179

Entries persist across reload ▶ 00:00

As a user, I want my entries to be saved and available after I close and reopen the project.

How it works. After adding/editing/deleting an entry, changes are persisted via useProjectSettings.patch() which writes to IDB (optimistic) and syncs to the server. Closing the browser and reopening /project/:id/memory shows the same entries. If offline, changes queue in IDB outbox and sync when online.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:515-528
src/hooks/useProjectSettings.ts:50-110

Read-only surface for below-floor users ▶ 00:00

As a translator with limited permissions, I want to see the Living Memory entries but not be able to modify them.

How it works. Non-MAINTAINER users see the same layout but with read-only affordances: no '+ Add' buttons in Instructions/Standards (replaced by lock icon with tooltip). Entry cards show no Edit/Delete buttons. All text content is visible. Recent Examples section is fully visible (it's always read-only). Brief section shows read-only mode with no edit/generate buttons.

WhoTranslator / project lead PermissionsRead memory: viewer(100); edit/curate memory entries: contributor(400)+
Key files

src/components/LivingMemoryPage.tsx:656-661
src/components/LivingMemoryPage.tsx:671-676
src/components/brief/BriefSection.tsx:30-53