Spec: F89 — Web and Mobile Material Intelligence Redesign
Status: partial (web/native source and registered tests exist; runner, visual, accessibility, named-device, and release evidence remain open) Canonical design sources: DESIGN.md + TASTE.md
2026-06-27 — W6 Intel page material audit slice started
Type: Implementation Change
Summary:
- Audited the highest-traffic CEO-facing web intelligence pages (
BriefPage,PulsePage,DecisionsPage,RisksPage,CommitmentsPage) against the F89 checklist aftercheck-design-tokens.mjspassed clean. - Migrated
PulsePage’s extracted-item removal affordance from a raw<button>to the shared shadcnButtonprimitive and replaced the raw Tailwind focus ring on highlighted pulse cards with the tokenizedshadow-ring. - Migrated
DecisionsPagerecommendation options and decided-state panels to role-correctrounded-card+shadow-litmaterial surfaces. - Migrated the
BriefPageerror header from a bespoke title class to the sharedPageHeaderprimitive. - Added focused web tests pinning these material recipes.
Reason:
- The token guard catches banned colors/shadows, but it cannot catch raw controls, one-off radii, or bypassed page primitives. CEO intelligence surfaces must converge on the same material grammar because they are the product’s trust core.
Impact:
- No API, route, copy, ranking, sharing, mutation, or i18n behavior changed.
- Risks and Commitments were manually checked in this pass and already had evidence chips, ranked lists, shared primitives, and shaped loading/empty states for the audited checklist items.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/DecisionsPage.test.tsx src/test/PulsePage.test.tsx src/test/BriefPage.test.tsxcd frontend && ./node_modules/.bin/tsc --noEmitcd frontend && pnpm test
2026-06-27 — W6 Approvals authority material slice started
Type: Implementation Change
Summary:
- Migrated the web Approvals loading rows, request form, approval records, approval-chain steps, active tab state, queue count, and error state onto shared Card, Badge, Button, Label, Skeleton, and Alert recipes.
- Replaced one-off rounded panels, custom status color maps, raw label elements, and bespoke warning/error shells with F89 lit-token surfaces.
- Added focused Approvals tests that pin pending approval cards, status badges, chain badges, and active tab material states.
Reason:
- Approvals are an authority and sign-off surface. Spend, exceptions, and contract decisions must feel accountable and calm, not like a secondary workflow built from generic panels.
Impact:
- No approvals API behavior, queue/requester role-gating, approve/reject/cancel behavior, copy, routing, or i18n files changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/ApprovalsPage.test.tsx
2026-06-27 — W6 Hub editor material slice started
Type: Implementation Change
Summary:
- Migrated the Company Hub document editor and announcement composer from raw white rounded shells onto shared Card/CardContent material surfaces.
- Replaced raw form labels with the shared Label primitive and upgraded markdown preview wells to rounded-card, paper-white, shadow-lit material.
- Replaced the announcement audience native radio inputs with a tokenized Button segmented control and lit team-selection chips.
- Added focused Hub tests that open both editors and pin their material card, label, preview-well, and audience control recipes.
Reason:
- Hub editors create company memory. Publishing an announcement or operating doc should feel as deliberate and trustworthy as reading one, not like a legacy form embedded inside an upgraded shell.
Impact:
- No Hub API, create/save, preview, team-targeting, pinned, document category, copy, route, or i18n behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/HubPage.test.tsx
2026-06-27 — M5 mobile screenshot and accessibility gates implemented
Type: Implementation Change
Summary:
- Added
.maestro/critical/11_workspace_lane.yaml— verifies the redesigned Workspace lane renders the full Intelligence section structure (Tasks, Risks, Decisions rows visible) without crash. - Added
.maestro/critical/12_ceo_risks_screen.yaml— navigates to the Risks screen via Workspace tab, asserts title, subtitle, and seeded risk card render correctly at standard font size; takes two screenshots (normal state + with data). - Added
.maestro/critical/13_ceo_decisions_screen.yaml— navigates to the Decisions screen via Workspace tab, asserts title, subtitle, and seeded decision card render correctly; takes two screenshots. - Added
.maestro/accessibility/01_font_scale_pulse_lane.yaml— verifies the CEO Pulse home survives 200% font scale without text overflow (F89 §6.8 / M5 requirement). - Added
.maestro/accessibility/02_font_scale_risks_screen.yaml— verifies the Risks screen survives 200% font scale. - Updated
.github/scripts/run-android-maestro.sh— theaccessibilitysuite now setsfont_scale=2.0via adb before running flows and resets to1.0via trap on exit. - Updated
.github/workflows/maestro.yml— accessibility suite option documented; iOS runner setsUIPreferredContentSizeCategoryName=AccessibilityExtraExtraExtraLargefor equivalent iOS Dynamic Type coverage.
Reason:
- M5 acceptance requires “F51 visual testing captures representative mobile screens” and “200% font-scale checks are run for core screens.” Without these Maestro flows, F89 remains visually unverified on Android/iOS despite the complete implementation.
- The flows use locale-invariant screen titles and demo seed data to avoid flakiness; Vietnamese text assertions are avoided since demo seed data has both EN and VI keys.
Impact:
- Three new critical Maestro flows added to the nightly CI suite — will catch regressions to the Risks and Decisions screen redesign.
- Two accessibility flows added in a new
.maestro/accessibility/directory — must be dispatched manually or as a weekly CI run since font-scale changes require emulator/simulator state. - CI runner updated to handle font-scale lifecycle (set before suite, reset after via trap).
Tests:
./gradlew :shared:compileKotlinJvm→ BUILD SUCCESSFUL- Maestro flows verified for YAML syntax; device run pending CI emulator.
2026-06-27 — W6 CRM company material audit slice started
Type: Implementation Change
Summary:
- Audited the CRM/company surface after the global web token guard passed clean.
- Migrated
CompaniesPageloading placeholders from hand-rolledanimate-pulsedivs to shapedCard+Skeletonmaterial. - Migrated the company summary, unresolved-name strip, detail shell, create form, and linked signal rows to shared
Card/CardContentrecipes with role-correctrounded-card,rounded-pill,shadow-card, andshadow-littreatments. - Replaced the raw company detail tab buttons with the shared shadcn
Tabsprimitives. - Replaced one-off status spans in company signal rows with shared
Badgevariants. - Replaced list row raw buttons with the shared
Buttonprimitive while preserving full-card affordance and keyboard semantics. - Added focused tests pinning the company material cards, skeletons, tabs, and status badges.
Reason:
- CRM is the next high-traffic web domain after the CEO intel pages. The company record is the operating memory for one relationship, so its material hierarchy must feel as calm and trustworthy as the brief/risk/decision surfaces.
Impact:
- No API, route, copy, filtering, signal loading, edit/delete behavior, or i18n behavior changed.
- This is a focused company-surface slice; the remaining CRM deal, activity, import, and settings surfaces continue through separate reviewable PRs.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/CompaniesPage.test.tsxcd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — M3 mobile CEO evidence trust pass
Type: Implementation Change
Summary:
- Added
LumiEvidenceTrustcomposable toLumiMobilePrimitives.kt— the KMP equivalent of the webEvidenceChip, rendering source-backed/low-confidence/missing states as calm lit-token badges. - Wired
LumiEvidenceTrustinto the sharedBriefItemCardso every Brief item exposes evidence count and confidence state adjacent to the claim. - Added confidence trust badge to the
DecisionCardandRiskCardin the full Decisions and Risks screens — only rendered whenconfidenceScore < 0.7so high-confidence items stay visually calm. - Added severity badge (
LumiBadge) to Today’sRiskCardso high/medium risks are ranked at scan speed in the CEO operating queue. - Added EN and VI string resources for all evidence/confidence labels in Brief, Decisions, and Risks namespaces.
Reason:
- M3 acceptance requires “Brief items show rank, evidence, confidence state, and actions in one card.” The KMP Brief, Risks, and Decisions screens had the confidence data in their DTOs but rendered none of it. This pass makes the trust signal text-visible — never hidden behind an unlabelled icon — matching the web W3 evidence grammar.
Impact:
- KMP CEO surfaces (Brief, Risks, Decisions, Today) now align with F89 M3 operating evidence contract.
- No API, route, business logic, or existing test behavior changed.
- The pre-existing compilation error in
WorkGraphHomeScreenModelTest.ktis unrelated and was present before this slice.
Tests:
./gradlew :shared:compileKotlinJvm→ BUILD SUCCESSFUL, 0 errors./gradlew :core:designsystem:test→ BUILD SUCCESSFUL, all tests pass
2026-06-27 — W6 CRM deals material board slice started
Type: Implementation Change
Summary:
- Migrated CRM deal cards from bespoke rounded panels and pulsing critical borders onto the shared Card material primitive with calm critical/stale surfaces.
- Migrated deal stage-age, deposit-overdue, won/lost, and kanban count chips onto the shared Badge lit-token primitive.
- Migrated the create-deal form and board loading state onto Card/Skeleton recipes, and replaced kanban drag-over raw ring styling with tokenized rounded-card, shadow-lit, and shadow-ring material states.
- Added focused DealCard tests pinning card material, lit badges, and the no-
animate-pulsecritical-state rule.
Reason:
- Deal boards are repeated executive CRM work surfaces. Urgency must be readable without animation or ad hoc red chips, and the board needs to feel like the same serious SaaS material system as the CEO intelligence queue.
Impact:
- No CRM API, drag-and-drop behavior, deal mutation behavior, copy, routing, saved-view behavior, or i18n files changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/DealsCrud.test.tsxcd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W6 work task list material slice started
Type: Implementation Change
Summary:
- Audited
ProjectTasksPageafter the global web token guard passed clean. - Migrated the project task-list view switcher from a raw rounded border group to a lit-token segmented surface using shadcn
Buttoncontrols. - Replaced square-ended view buttons with role-correct
rounded-controlbuttons inside the lit segmented surface. - Replaced the missing due-date fallback em dash with a plain hyphen so visible table copy stays within the product copy rules.
- Added focused tests pinning the view switcher material recipe and missing-date fallback.
Reason:
- The project task list is a dense operator surface. It already uses the shared
DataTable, so the remaining drift was the page chrome around the table: view controls and visible copy should feel like Lumi, not generic SaaS.
Impact:
- No API, routing, filtering, task ordering, table behavior, detail-panel behavior, or i18n behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/ProjectTasksPage.test.tsxcd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W6 work timeline material slice started
Type: Implementation Change
Summary:
- Audited
ProjectTimelinePageafter the global web token guard passed clean. - Migrated the timeline view switcher from a raw rounded border group to a lit-token segmented surface using shadcn
Buttoncontrols. - Migrated timeline loading placeholders to role-correct
rounded-cardskeletons. - Migrated the no-task state to the shared
EmptyStateprimitive with the calendar glyph as a lit medallion. - Migrated clickable timeline task rows from raw
<button>cards to shadcnButtoncontrols shaped as card-material rows. - Added focused tests pinning the view switcher and task-row material recipes.
Reason:
- Project timelines are work-management decision surfaces. They need to read as a calm schedule of commitments on paper, not a mixture of one-off controls and generic rounded boxes.
Impact:
- No API, routing, date bucketing, task detail behavior, copy, or i18n behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/ProjectTimelinePage.test.tsxcd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 DataTable selection material slice started
Type: Implementation Change
Summary:
- Migrated shared web DataTable desktop row selection, mobile card selection, and keyboard focus rings from legacy lumi-blue soft/ring tokens to semantic badge info material tokens.
- Added focused DataTable tests that pin selected desktop rows and selected mobile cards to F89 info surfaces and rings.
Reason:
- Data tables are the repeat-use surface of serious SaaS. Selection and keyboard focus must feel precise and calm across desktop and mobile table presentations.
Impact:
- All DataTable consumers now inherit F89 info material selection states without changing table APIs, sorting, filtering, pagination, selection, or keyboard navigation behavior.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/DataTable.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W6 work workflow material slice started
Type: Implementation Change
Summary:
- Audited
ProjectWorkflowPageafter the global web token guard passed clean. - Migrated the project workflow view switcher from loose icon buttons to a lit-token segmented surface using shadcn
Buttoncontrols. - Migrated workflow loading placeholders to role-correct
rounded-cardskeletons. - Migrated the no-custom-status state from a dashed generic box to a lit info-token material state.
- Migrated existing workflow status editor rows from generic
rounded-lgboxes torounded-card, paper-backed lit rows that read as editable nested sections rather than extra cards. - Added focused tests pinning workflow chrome, status-row, and empty-state material recipes.
Reason:
- Workflow settings decide how a project is operated. The surface must feel like a serious configuration document, not a pile of ad hoc form boxes, while preserving the existing table/board semantics.
Impact:
- No API, routing, create/update/delete/reorder behavior, form state, board usage protection, copy, or i18n behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/ProjectWorkflowPage.test.tsxcd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Global feedback material slice started
Type: Implementation Change
Summary:
- Migrated the web Sonner toast wrapper from legacy green, red, amber, and lumi-blue soft colors to semantic badge success, danger, warning, and info material tokens.
- Migrated auth route skeleton loading surfaces onto rounded-card, rounded-control, shadow-card, and existing Skeleton lit recipes.
- Added focused tests that pin toast token mapping and auth skeleton card material recipes.
Reason:
- Toasts and route skeletons are global feedback surfaces. They must feel like part of Lumi’s calm operating system, not third-party defaults or one-off loading shells.
Impact:
- Transient feedback and auth route loading now align with F89 global material grammar.
- No toast behavior, route loading behavior, copy, or navigation changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/global-feedback-material.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Shared page primitive material slice started
Type: Implementation Change
Summary:
- Migrated shared web EmptyState success/default icon treatments from legacy green and lumi-blue soft colors to semantic badge success/info material tokens.
- Migrated SectionHeader count chips onto the shared Badge lit-token primitive instead of a one-off rounded-full chip.
- Added primitive tests that pin EmptyState cards, lit icon medallions, and SectionHeader count badges to F89 rounded-card, rounded-pill, shadow-card, and shadow-lit recipes.
Reason:
- Empty and section-divider states appear across CEO, work, settings, support, CRM, and notification surfaces. Shared primitives must carry the design system so downstream screens converge automatically.
Impact:
- Empty states and section count chips now inherit consistent Material Intelligence surfaces across reused web screens.
- No page data, route, copy, action, or accessibility behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/page-primitives.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W6 work board material slice started
Type: Implementation Change
Summary:
- Audited
ProjectBoardPageafter the global web token guard passed clean. - Migrated the project board view switcher from a raw rounded border group to a lit-token segmented surface using shadcn
Buttoncontrols. - Migrated board loading placeholders, empty state, lane wells, and task cards to role-correct
rounded-card,shadow-lit, andshadow-cardmaterial recipes. - Replaced one-off priority chip spans with shared
Badgevariants. - Added focused tests pinning board chrome, lane, task-card, priority badge, and empty-state material recipes.
Reason:
- The project board is a high-frequency operator surface. Drag-and-drop lanes need to feel like durable work trays on paper, with urgency expressed through semantic lit tokens rather than generic rounded boxes.
Impact:
- No API, routing, drag-and-drop, task creation, status update, load-more, detail-panel, copy, or i18n behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/ProjectBoardPage.test.tsxcd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Billing entitlement recovery slice started
Type: Implementation Change
Summary:
- Migrated web billing entitlement surfaces across SubscriptionManagement, GraceBanner, and UpgradePrompt onto shared Card, Badge, Alert, rounded-card, shadow-card, shadow-lit, and badge-token recipes.
- Replaced legacy lumi-blue, amber, red, green soft-token surfaces with semantic badge info, warning, danger, and success material tokens.
- Added focused assertions that pin subscription status badges, scheduled alerts, grace banners, and upgrade prompt icon chips while preserving entitlement, invoice, cancel, reactivation, and owner-contact behavior.
Reason:
- Billing entitlement warnings, read-only recovery, and upgrade prompts are high-trust procurement states. They need to feel calm and accountable, not promotional or ad hoc.
Impact:
- Settings billing management, grace/read-only banners, and freemium upgrade gates now align with F89 admin material grammar.
- No billing API, invoice, entitlement, cancellation, reactivation, routing, or locale copy behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/subscription-management.test.tsx src/test/entitlements.test.tsx src/test/billing.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W6 CRM pipeline stats material slice started
Type: Implementation Change
Summary:
- Migrated the CRM
PipelineStatsanalytics cards from hand-built rounded divs to shared Card + CardContent material recipes. - Migrated the pipeline stats loading state from raw pulsing blocks to shaped Skeleton cards with rounded-card and shadow-lit treatments.
- Added focused PipelineStats tests that pin the five material cards and five loading skeleton cards while preserving currency-honest analytics rendering.
Reason:
- Pipeline stats are the first revenue signal above the CRM deal board. They need to read like accountable operating metrics, not generic mini panels.
Impact:
- No CRM analytics API, currency formatting, forecast calculation, deals board behavior, copy, or i18n behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/PipelineStats.test.tsx src/test/DealForecast.test.tsxcd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W6 CRM deal detail material slice started
Type: Implementation Change
Summary:
- Migrated the CRM deal detail drawer loading state from raw pulsing divs to shaped Card + Skeleton material recipes.
- Migrated the deal summary grid and stage/status tokens onto rounded-card, shadow-lit, and shared Badge lit-token recipes.
- Added focused DealDetailPanel tests that pin the modal sheet, loading cards, summary card, and status badge material states while mocking the heavy child sections.
Reason:
- Deal detail is the sales operating record opened from the board. It must feel like an accountable sheet of relationship evidence, not a generic side panel with bespoke pills.
Impact:
- No CRM API, route, stage movement, win/loss, forecast, comment, contact role, line item, quote, deposit, or activity behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/DealDetailPanel.test.tsxcd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W6 CRM contacts material slice started
Type: Implementation Change
Summary:
- Migrated the CRM Contacts loading state from hand-rolled pulsing divs to shaped Card + Skeleton material recipes.
- Migrated selectable contact rows, the active contact state, the detail sheet, and detail sub-panels onto role-correct rounded-card, shadow-card, shadow-lit, and semantic info-surface treatments.
- Replaced the remaining raw company navigation button with the shared Button primitive while preserving the existing route behavior and accessible button name.
- Added focused Contacts tests pinning the F89 material recipes for list cards, detail cards, nested panels, and skeleton states.
Reason:
- Contacts are the human layer of CRM memory. The page needs to feel like a trusted directory and relationship record, not a generic list/detail CRUD screen.
Impact:
- No CRM API, route, create/update/delete behavior, keyboard selection, virtual list behavior, copy, or i18n files changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && pnpm test -- src/test/ContactsPage.test.tsxcd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Error recovery material fallback slice started
Type: Implementation Change
Summary:
- Migrated the global web ErrorBoundary production fallback onto rounded-card, shadow-card, and lit warning-token recipes.
- Migrated the dev traceback panel away from raw red soft colors and one-off rounded surfaces onto danger badge tokens, rounded-card, shadow-card, and shadow-lit code wells.
- Added focused ErrorBoundary tests that pin the production recovery card and icon chip recipes while preserving Sentry capture, no-internals leakage, reload, and custom fallback behavior.
Reason:
- Crash recovery is a trust surface. Even failure states must look calm, accountable, and native to Lumi.
Impact:
- App-level route crashes now resolve to the same F89 material grammar as admin and command surfaces.
- No error capture, clipboard copy, reload, or custom fallback behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/ErrorBoundary.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Command dock material launcher slice started
Type: Implementation Change
Summary:
- Migrated the floating Notifications, Messages, and Chat Lumi dock panels onto shared rounded-card, shadow-lit, badge-token, and rounded-pill recipes for header chips, empty states, skeleton rows, row targets, chat bubbles, and the compact assistant input.
- Replaced raw dock status dots and legacy lumi-blue/green/amber/red soft colors with semantic badge dot and surface tokens.
- Added focused dock panel tests that pin Notifications, Messages, and Chat Lumi material recipes while preserving notification mark-read, mark-all, and route navigation behavior.
Reason:
- The command dock is a daily cross-surface launcher. It must feel like one deliberate command layer instead of three small bespoke panels.
Impact:
- The dock panels now align with F89 launcher material grammar across loading, empty, populated, and interactive states.
- No notification, messaging, chat API, route, unread count, or send behavior changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/NotificationsPanel.test.tsx src/test/DockPanelsMaterial.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Billing material subscription slice started
Type: Implementation Change
Summary:
- Migrated the web Billing loading skeleton, pending payment sheet, active subscription shell, status token, billing-period controls, gateway selector, and plan option buttons onto shared Skeleton, Badge, Button, rounded-card, shadow-card, and shadow-lit recipes.
- Replaced raw rounded-xl sections, raw status color maps, white select surfaces, and custom toggle buttons with Material Intelligence surface and lit-token semantics.
- Added focused Billing tests that pin the plan selector, active status badge, and pending payment material recipes while preserving payment, renewal, and history behavior.
Reason:
- Billing is a trust and procurement surface. Subscription state, pending payment instructions, renewal, and plan choice must feel precise and accountable.
Impact:
- The Billing card in
/settingsnow aligns with F89 admin material grammar. - No billing API behavior, gateway selection, payment polling, renewal, or copy changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/billing.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Audit Log material target records slice started
Type: Implementation Change
Summary:
- Migrated the web Audit Log loading rows, error surface, table shell, and target identity cells onto shared Skeleton, Card, Badge, rounded-card, and lit-token recipes.
- Replaced middle-dot target metadata with structured target type badges and monospace target ids.
- Added focused Audit Log tests that pin the material table shell and target badge treatment while preserving admin-only access behavior.
Reason:
- Audit Log is an accountability surface. Actor, action, target, and timestamp records should feel like precise system evidence, not plain metadata text.
Impact:
/settings/audit-logtarget records now align with F89 admin material grammar.- No audit API behavior, access control behavior, filters, routing, or copy changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/AuditLogPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Messages material modal and suggestion slice started
Type: Implementation Change
Summary:
- Migrated the web Messages modal panel, search popover shell, DM suggestion sheet, and delete confirmation action onto shared rounded-card, border, shadow, and destructive button recipes.
- Replaced raw rounded-xl/rounded-lg messaging shells and custom destructive button color with Material Intelligence surface and action semantics.
- Added focused Messages tests that pin modal and DM suggestion material recipes while preserving channel creation, DM selection, edit, and delete behavior.
Reason:
- Messages is a company communication lane. Channel creation, direct-message targeting, and search affordances must feel like calm workspace material, not legacy overlay widgets.
Impact:
/connect/messagesmodal and suggestion surfaces now align with F89 Connect/Admin material grammar.- No messaging API behavior, realtime behavior, routing, deep-linking, or copy changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/MessagesPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Sources material connector records slice started
Type: Implementation Change
Summary:
- Migrated the web Sources loading skeleton, connection cards, degraded connection state, status badges, and event log sheet onto shared Skeleton, Card, Badge, rounded-card, and shadow-lit recipes.
- Replaced raw animated placeholder panels, one-off amber borders, and plain rounded-lg event containers with semantic warning/success lit-token surfaces.
- Added focused Sources tests that pin connection card, degraded warning, event sheet, and status badge material recipes while preserving catalog, polling, disconnect, and event behavior.
Reason:
- Sources are evidence infrastructure. Connector status, degraded state, and event capture history must read as accountable system records rather than generic admin rows.
Impact:
/settings/sourcesconnections and event logs now align with F89 admin/connect material grammar.- No source API behavior, connector catalog behavior, actions, routing, or copy changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/SourcesPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
1. Problem & CEO Job
Despite the product spine and design doctrine, web and mobile work lacks one unified, high-trust material language. Generic SaaS patterns, hardcoded colors, uneven mobile density, weak source/evidence affordances, and platform-specific interpretations drift from the canonical system.
This serves all three CEO jobs:
- See clearly: ranked operating surfaces must become visually calmer and easier to scan.
- Decide fast: primary actions, severity rails, evidence, owners, and due dates must be placed consistently across web and mobile.
- Trust the signal: AI output must look accountable on every platform: source-backed, low-confidence, stale, conflicting, and human-confirmed states must be visible.
F89 ships the upgraded design system across web and mobile. It adds no product features, only upgrades existing visual, interaction, and verification contracts.
2. User Stories & Acceptance Criteria
2.1 CEO and leadership surfaces
- As a CEO, I want Brief, Pulse/Today, Decisions, Risks, Commitments, and Follow-ups to use one ranked briefing language, so that I can trust the queue without relearning each page.
- Given I open the web CEO Brief, when the page renders, then every visible object maps to a DESIGN.md §8.0 material recipe.
- Given I open mobile Pulse, when the first viewport renders, then it answers “what needs me now?” before showing directory or secondary navigation.
- Given an AI-generated item appears on any CEO surface, when I inspect it, then source, timestamp or age, confidence state when relevant, owner, and suggested action are visually adjacent to the claim.
- Given a quiet day, when there are no urgent items, then the screen shows a positive silence state using the Empty-state card recipe, not a dead blank page.
- Given a high or critical item exists, when the list renders, then the item receives the correct 3px severity rail and appears before routine items.
2.2 Operator and member surfaces
- As a team member, I want Daily Pulse, Tasks, Projects, Recurring, Horizon, and Company Hub to feel simpler and more native, so that daily use stays fast on phone and desktop.
- Given I open Daily Pulse on web or mobile, when the form renders, then labels are visible, fields use the Recessed well recipe, and submit/save states are explicit.
- Given I submit Pulse and the network fails, when the error appears, then typed answers remain intact and the error tells me how to recover.
- Given I open Tasks, Projects, or Recurring on mobile, when records render, then they use ranked mobile cards, not squeezed desktop tables.
- Given I open a dense web list, when the list renders, then it uses DataTable/list material rules: 1px dividers, no nested cards, tabular numbers where relevant, and one primary row action.
2.3 Admin and settings surfaces
- As an owner/admin, I want Settings, Billing, Teams, Notifications, Integrations, and Support to use the same calm material grammar, so that admin work feels trustworthy rather than bolted on.
- Given I open any settings route, when it renders, then the page uses Sheet, Recessed well, Lit token, and Authority seal recipes only.
- Given a destructive action appears, when it renders, then it uses destructive button styling and a clear confirmation pattern, never the same visual weight as the safe primary action.
- Given a permission-restricted section appears for a member, when rendered, then it explains why access is restricted and where to go next.
2.4 Native mobile parity
- As a mobile user, I want Lumi to feel native and consistent across iOS and Android, so that the product feels deliberate rather than ported.
- Given iOS and Android render the same feature, when compared side by side, then both use the same token values, radius roles, status palette, and AI insight states while respecting platform shell behavior.
- Given OS font scaling is 200%, when core mobile screens render, then primary actions remain readable and no touch target drops below 44pt iOS / 48dp Android.
- Given a mobile bottom sheet opens, when rendered, then it uses the Modal sheet recipe with 16px radius, correct safe-area padding, and a visible close/back affordance.
- Given mobile shows evidence, when the user inspects a card, then evidence is visible as text/chip/disclosure, never hidden behind an unlabeled tiny icon.
2.5 Design-system implementation integrity
- As a designer or engineer, I want the design system to be enforceable, so that future screens do not drift back to generic SaaS.
- Given code references a color, radius, border, or shadow in product UI, when static guards run, then raw stock Tailwind palette classes, raw hex colors, raw shadows, and one-off radii fail.
- Given DESIGN.md token values change, when token parity checks run, then web, iOS/Mac/Watch, and Android mirrors are detected as either matching or intentionally pending in the implementation audit.
- Given screenshot flow runs, when screenshots are generated, then web desktop, web mobile, and mobile-native representative surfaces are all captured or explicitly marked pending with a blocking reason.
3. Scope Boundaries
-
In:
- Web app visual and interaction redesign to the DESIGN.md Material Intelligence system.
- Native mobile and shared KMP UI token/material parity.
- Shared components and primitives: buttons, cards, inputs, badges, sheets, modals, empty states, skeletons, tables/lists, evidence chips, AI insight states.
- High-traffic surfaces: Brief, Today/Pulse, Daily Pulse, Tasks, Projects, Recurring, Commitments, Risks, Decisions, Chat, Company Hub, CRM, Notifications, Settings, Billing, Teams, Support.
- Verification gates: token linting, contrast tests, screenshot flow, mobile visual testing, accessibility checks, reduced-motion checks.
- Documentation and diagrams required for route/shell/component architecture changes.
-
Out:
- New backend models, endpoints, or product capabilities.
- Dark mode. Lumi remains light-only per DESIGN.md §5.
- Aurora/glassmorphism in product UI. Public marketing hero imagery may use a restrained atmospheric asset under F22 only.
- Feature IA redesign beyond what F79 already defines for mobile and existing web routes already define for desktop.
- Native platform rewrites not required for design parity.
- White-label themes or customer-specific theming.
4. Data Model
n/a. F89 changes visuals and interactions over existing models; it adds no backend model. Persistent state belongs in its owning feature spec.
Allowed client-side implementation state:
- transient UI state for open/closed sheets, filters, tabs, and focused fields
- saved visual testing snapshots
- local preview fixtures for Storybook/MSW/screenshot tests
Forbidden client-side implementation state:
- local-only AI confidence truth
- local-only subscription entitlement
- local-only tenant or permission state
- local-only business object status not backed by the API
5. API Contract
n/a. F89 adds no endpoints. Existing APIs retain their contracts; view models or component props may add fields, but backend response changes belong in the owning feature spec.
Tenant scoping remains unchanged:
- All business data uses the existing organization header/request tenant.
- Shared search, notifications, and cross-object cards must never merge organizations.
AI output remains bound by F08/F12/F14/F70/F83/F86:
- Every AI-generated Commitment, Risk, DecisionRequest, Brief item, and Chat answer that states a fact must expose source-backed evidence in the UI.
- F89 controls evidence and confidence presentation, not extraction truth.
6. UI / UX
6.1 Global design contract
Every redesigned web and mobile surface must apply the following hierarchy:
- Operating question: what does this screen answer?
- Ranked content: what deserves attention first?
- Claim: what happened or needs action?
- Evidence: why should the user trust it?
- Action: what can the user do now?
- Recovery: what happens when data is empty, stale, loading, forbidden, or failed?
If a screen cannot answer the operating question in its first viewport, it is not ready.
6.2 Material recipe application
Every visible object must map to a DESIGN.md §8.0 recipe:
| Recipe | Web implementation | Mobile implementation | Acceptance |
|---|---|---|---|
| Canvas | app root background, --canvas-glow, paper texture if present | root surface color + subtle top light where native supports it | no component-level glow |
| Sheet | Card, table shell, list group | LumiCard / shared card container | white, 1px border, 8px radius, shadow-card |
| Raised sheet | sticky header, hover card, dock pod | sticky top bar, lifted selected surface | 8px radius, border-strong, shadow-raised |
| Overlay | Popover, dropdown, tooltip, menu | platform popover/menu equivalent | 12px radius, shadow-overlay |
| Modal sheet | Dialog, command palette, bottom sheet | native sheet/dialog | 16px radius, shadow-modal or platform equivalent |
| Recessed well | input, textarea, search | TextField / multiline field | 8px radius, shadow-input |
| Lit token | Badge, chip, status, tab active state | LumiBadge / chip | pill radius, status quad |
| Authority seal | primary button | LumiPrimaryButton | blue fill, gradient-primary, shadow-button |
No other material recipe is allowed without updating DESIGN.md first.
6.3 Token implementation requirements
Web:
frontend/src/index.cssmust expose all canonical DESIGN.md §19 tokens.- Tailwind and shadcn component variants must reference semantic tokens, not stock palette classes.
- Raw
shadow-sm/md/lg/xl/2xl, arbitraryshadow-[...], raw hex colors, and stock Tailwind palette classes remain blocked infrontend/src. - Any raw CSS variable fallback must use the canonical
--color-*,--radius-*,--border-*, and--shadow-*names.
iOS / Mac / Watch:
LumiKit.swift, Mac theme files, and Watch colors mirror token values where those shells use Lumi UI.- Native material approximations must preserve the role: sheet, raised sheet, overlay, modal sheet, recessed well, lit token, authority seal.
- iOS system materials may be used only for shell chrome when they do not reduce contrast or hide evidence. Product cards remain Lumi sheets, not glass panels.
Android / Compose / KMP:
Color.ktand shared theme tokens mirror DESIGN.md values.- Shared KMP components expose recipe-level primitives, not per-screen ad hoc style arguments.
- Compose previews must include normal, loading, empty, error, and permission states for high-traffic primitives.
6.4 Component scope
F89 upgrades or creates these shared primitives:
| Primitive | Web | Mobile / KMP | Required states |
|---|---|---|---|
| PrimaryButton | shadcn Button variant | LumiPrimaryButton | rest, hover, active, focus, disabled, loading |
| SecondaryButton | shadcn Button variant | LumiSecondaryButton | rest, hover, active, focus, disabled |
| DestructiveButton | shadcn Button variant | LumiDestructiveButton | rest, focus, confirm pending, disabled |
| Card / Sheet | shadcn Card wrapper | LumiCard | rest, hover if clickable, selected, disabled |
| EvidenceChip | new/shared page primitive | LumiEvidenceChip | source-backed, stale, low-confidence, missing |
| StatusBadge | existing page primitive | LumiBadge | neutral, info, success, warning, danger |
| EmptyState | existing page primitive | LumiEmptyState | neutral, success/all-clear, permission, no-data |
| Skeleton | shared skeleton primitive | LumiSkeleton | shimmer, reduced-motion static |
| Field | RHF/shadcn field wrappers | LumiFormField | rest, focus, error, disabled, saving |
| Modal/Sheet | Dialog/Sheet wrappers | platform sheet/dialog | open, close, loading body, destructive confirm |
| DataTable/List | DataTable + mobile card fallback | LumiRankedList | loading, empty, populated, error, mobile card |
Rules:
- Components must not accept arbitrary raw color, radius, or shadow props.
- Components may accept semantic tone props only:
neutral,info,success,warning,danger,primary. - Every primitive must preserve accessible name, focus behavior, and keyboard/touch affordance.
6.5 Web surface transformation plan
PR W1 - Token and guard foundation
Goal: make the material system enforceable before visual rewrites.
Files expected:
frontend/src/index.cssfrontend/tailwind.config.*or Tailwind v4 theme entryfrontend/scripts/check-design-tokens.mjsfrontend/src/test/contrast.test.tsDESIGN.mdif implementation reveals token corrections
Acceptance:
- All DESIGN.md §19 tokens exist in CSS.
- Guard blocks raw shadows, stock palette colors, raw hex product UI colors, and one-off radii.
- Contrast tests include new border/foreground/badge/button pairs.
- No product UI uses dark mode tokens.
PR W2 - Web primitive migration
Goal: all base primitives speak Material Intelligence.
Files expected:
frontend/src/components/ui/button.tsxfrontend/src/components/ui/card.tsxfrontend/src/components/ui/badge.tsxfrontend/src/components/ui/input.tsxfrontend/src/components/ui/textarea.tsxfrontend/src/components/page/*- relevant unit tests and MSW fixtures
Acceptance:
- Buttons implement size contract, authority seal, focus, disabled, loading.
- Cards implement sheet/raised/overlay/modal recipes without nested-card defaults.
- Inputs implement recessed well state contract.
- Badges implement lit-token quads.
- Story/test fixtures cover every primitive state.
PR W3 - CEO web surfaces
Goal: Brief, Today, Decisions, Risks, Commitments become the reference implementation.
Surfaces:
- F12 CEO Brief
- F13 Today dashboard
- F11 Decisions
- F10 Risks
- F09 Commitments
- F25 Brief actions
Acceptance:
- First viewport answers “what needs me now?”
- All AI/operating claims show evidence/source state.
- Ranked items use severity rails and correct status badges.
- Empty states express positive silence where appropriate.
- Mobile web viewport uses ranked card layout, not squeezed grids.
PR W4 - Capture and work surfaces
Goal: daily usage surfaces become materially consistent and calmer.
Surfaces:
- F07/F83 Daily Pulse
- F05 Tasks
- F04 Projects
- F06 Recurring
- F23 Horizon
- F31 Follow-ups
- F32 Signal Inbox
Acceptance:
- Daily Pulse uses single-column capture, recessed wells, explicit save states.
- Tasks/projects/recurring use DataTable on desktop and ranked cards on mobile.
- Follow-up and Signal Inbox cards show owner, age, source, and action.
- Error states preserve typed input or current filter context.
PR W5 - Company, business, and admin surfaces
Goal: breadth surfaces stop feeling secondary.
Surfaces:
- F27/F50 CRM
- F28 Company Hub
- F29 Internal chat
- F77 Notification center
- F75 Settings
- F24 Billing/subscription
- F03 Teams
- F58 Support
Acceptance:
- Company/Business surfaces use operating table or ranked-card composition.
- Settings and Billing use consistent sheet/well/authority-seal language.
- Notifications use lit tokens, not generic alert cards.
- Chat remains an operating query/coordination layer, not a playful chatbot clone.
6.6 Mobile and shared UI transformation plan
PR M1 - Native token parity
Goal: align iOS, Android, Mac, Watch, and KMP theme mirrors to DESIGN.md.
Files expected:
ios/Lumi/UI/Shared/LumiKit.swiftios/LumiMac/Theme/LumiColors.swiftios/LumiWatch/Theme/WatchColors.swiftandroid/**/theme/Color.ktandroid/shared/src/commonMain/**/theme/*
Acceptance:
- Color tokens match DESIGN.md §19.
- Radius roles exist for 2, 4, 8, 12, 16, pill.
- Border roles exist for hairline, focus, rail.
- Mobile surfaces remain light-only.
PR M2 - Shared mobile primitives
Goal: create or upgrade shared components so every mobile screen can migrate without ad hoc styling.
Primitives:
LumiPrimaryButtonLumiSecondaryButtonLumiDestructiveButtonLumiCardLumiEvidenceChipLumiBadgeLumiFormFieldLumiEmptyStateLumiSkeletonLumiBottomSheetLumiRankedList
Acceptance:
- Each primitive has states matching §6.4.
- Touch targets meet 44pt / 48dp minimum.
- Evidence and confidence states are label-visible, not icon-only.
- Reduced-motion mode disables shimmer and decorative movement.
PR M3 - Mobile CEO lane migration
Goal: Pulse, Brief, Today-equivalent queue, Decisions, Risks, Commitments express the new system.
Acceptance:
- Pulse first viewport differs by role and answers the operating question.
- Brief items show rank, evidence, confidence state, and actions in one card.
- Decisions show options and recommendation without hiding context.
- Risks and commitments use sober warning/danger rails only when semantically required.
- Positive silence states are visually composed.
PR M4 - Mobile work/business/company lanes
Goal: Work Graph, Business, Company Hub, Workspace match the material and operating grammar.
Acceptance:
- Work Graph cards show title, owner, status, due/age, and action/evidence.
- Business cards surface revenue risk before generic analytics.
- Company Hub prioritizes pinned announcements and urgent messages.
- Workspace remains a directory/control center, not a dumping ground.
PR M5 - Mobile verification and screenshot gates
Goal: make mobile design regressions visible.
Acceptance:
- F51 visual testing captures representative mobile screens across iOS/Android or fake API where live platform is unavailable.
- Screens include normal, loading, empty, error, permission, and low-confidence states.
- 200% font-scale checks are run for core screens.
- Rule-of-two navigation from F79 remains intact after redesign.
6.7 Copy and i18n
All user-visible strings introduced by F89 implementation must:
- use existing i18n conventions
- update English and Vietnamese together
- avoid hype language
- avoid “AI magic” framing
- avoid technical terms in user-facing errors
- preserve Vietnamese line length and diacritics on mobile
Required tone:
- English: calm, direct, operational
- Vietnamese: short, natural, not overly corporate, not AI-jargon-heavy
6.8 Accessibility and performance
Accessibility:
- WCAG AA contrast for text and interactive UI.
- Keyboard focus visible on web.
- VoiceOver/TalkBack labels for every mobile interactive element.
- Touch target minimums enforced on mobile.
- Color never communicates status alone.
Performance:
- No component-level blur/glow stacks.
- No decorative animation loops.
- Skeletons are layout-matched.
- Motion uses transform/opacity only.
- Reduced motion disables shimmer and nonessential transitions.
- Web LCP/INP/CLS must not regress on landing or app shell.
7. Test Plan
| # | Case | Type | Where |
|---|---|---|---|
| 1 | DESIGN.md token values exist in web CSS | frontend unit/script | frontend/scripts/check-design-tokens.mjs |
| 2 | Raw stock colors, raw shadows, one-off radii blocked | frontend script | frontend/scripts/check-design-tokens.mjs |
| 3 | Contrast pairs pass for body, buttons, badges, focus, error states | frontend unit | frontend/src/test/contrast.test.ts |
| 4 | Primitive state coverage: buttons/cards/inputs/badges/evidence chips | frontend unit | frontend/src/test/components/* |
| 5 | CEO web surfaces screenshot flow normal/loading/empty/error states | E2E/screenshot | frontend/tests/e2e/screenshot-flow.spec.ts |
| 6 | Web mobile viewport screenshots for Brief, Today/Pulse, Daily Pulse, Tasks, Settings | E2E/screenshot | screenshot flow mobile matrix |
| 7 | i18n keys added in en and vi for new UI strings | frontend unit/review | locale files |
| 8 | MSW error-state tests for API-dependent redesigned components | frontend unit | frontend/src/mocks/handlers.ts + tests |
| 9 | Native token parity check for iOS/Android/KMP mirrors | script/unit | platform theme tests or parity script |
| 10 | Mobile primitive previews/tests cover normal/loading/empty/error/permission | mobile unit/UI | iOS/Android/KMP test suites |
| 11 | Mobile 200% font-scale audit for core lanes | mobile UI/accessibility | F30/F51 mobile tests |
| 12 | F79 rule-of-two navigation still passes after visual migration | mobile UI | F79/F30 tests |
| 13 | Evidence visibility audit: AI items expose source/confidence state | E2E/UI | Brief, Risks, Decisions, Chat tests |
| 14 | Reduced-motion audit disables shimmer/animation loops | frontend + mobile | unit/UI checks |
| 15 | No dark mode regression | repo audit | rg "dark:" frontend/src with allowed exceptions |
Verification gates before F89 can move from draft to shipped:
cd frontend && ./node_modules/.bin/tsc --noEmit
cd frontend && pnpm test
node frontend/scripts/check-design-tokens.mjs
cd frontend && pnpm exec playwright test tests/e2e/screenshot-flow.spec.ts --reporter=list
make e2e
Mobile gates depend on the owning platform implementation PR:
cd android && ./gradlew test
cd android && ./gradlew connectedCheck # when emulator/device is available
cd ios && xcodebuild test ... # exact scheme from mobile implementation PR
If a platform gate cannot run locally, the implementation PR must state the blocker and provide CI or device verification before marking that phase complete.
8. Current Behavior
The web token graph, representative Material Intelligence recipes, shared KMP primitives, and iOS LumiKit source exist with focused tests and static guards. The previous complete claim is not fully supported by this checkout: the spec itself records three KMP screens added after the 2026-06-27 mobile audit and an unchecked permission-restricted-state criterion. No current frontend runner, browser screenshot, named Android/iOS visual or accessibility run, CI visual artifact, or hosted release evidence is attached. These boundaries are canonicalized in contracts/features/F89.cue and the F89 implementation audit.
Current behavior is mixed:
- DESIGN.md and TASTE.md now define Civic Editorial Minimalism + Material Intelligence.
- F19 documents design-system invariants, but its audit still records gaps around severity palette tests, skeleton coverage, token hardcoding, mobile screenshot coverage, and doc/CSS drift.
- Web has shared shadcn/page primitives, but implementation still needs a full audit against the new material recipes.
- Mobile has F30/F78/F79 shell and KMP direction, but native/shared surfaces remain partially hybrid and not yet fully material-token aligned.
- Screenshot flow exists for web, but mobile-native visual regression is still F51 work and not a complete gate.
- AI surfaces have evidence requirements by doctrine and feature specs, but visual state treatment is not yet uniform across all platforms.
Therefore F89 is not built. The new design doctrine exists; this spec defines the implementation program to make the product match it.
9. Error States
| Error | User-visible behavior | Internal handling | Retry / recovery |
|---|---|---|---|
| Token missing or typo | UI must not ship; caught by token guard | static script fails | fix token or component reference |
| Raw color/shadow/radius introduced | PR blocked | static script fails | replace with semantic token |
| Screenshot captures skeleton as final UI | test fails or screenshot rejected | wait for skeleton-clear selector | fix loading state or test wait |
| API error on redesigned component | inline or contextual error using i18n key | TanStack Query/MSW-covered path | retry action where safe |
| Permission denied | composed permission state, not blank screen | route/component respects role gate | explain who can access |
| Low-confidence AI item | visible low-confidence state and confirm/review affordance | no mutation until confirmed where required | confirm, dismiss, or inspect source |
| Missing evidence | item cannot present as fact | owning feature must hide/drop or mark missing | request better source / open source |
| Mobile text overflow | PR blocked by visual/accessibility audit | test at Vietnamese + 200% font scale | revise layout/copy, not smaller type |
| Reduced-motion mismatch | animation disabled or simplified | media/query hook path | static fallback |
10. Diagrams & Docs Touched
F89 implementation must update these as relevant:
- DESIGN.md if tokens or material recipes change.
- TASTE.md if pre-flight rules change.
- docs/MVP_SCOPE.md for F89 status.
- frontend/DIAGRAMS.md if route, shell, or shared component architecture changes.
- docs/specs/F19-design-system.md if baseline invariants are superseded.
- docs/specs/F30-mobile.md, F78, F79, and F51 when native implementation details or test obligations change.
- frontend/AGENTS.md if token guard rules or component usage rules change.
No backend diagrams are expected unless an implementation PR introduces an API or model change. That would be outside F89 and must update the owning feature spec first.
11. Implementation Audit (2026-06-27)
Verdict (2026-07-16): W1–W5 web phases are complete and merged to main. M1–M4 mobile phases are source-complete; M5 remains partial because three KMP screens were added after the 2026-06-27 audit, the permission-restricted explanation criterion remains unchecked, and no commit-bound named-device or CI visual/accessibility artifact is attached. The 55-screen audit and committed Maestro flows do not substitute for those gates.
Phase completion matrix:
| Phase | Description | Status | Notes |
|---|---|---|---|
| W1 | Web token foundation + design-token guard | ✅ done | check-design-tokens.mjs enforces in CI |
| W2 | Web shared primitives migration | ✅ done | EvidenceChip, DataTable, Form, Drag-and-drop, MSW |
| W3 | CEO web surfaces (Brief, Today, Risks, Decisions) | ✅ done | Evidence grammar on every AI card |
| W4 | Capture and work surfaces (Pulse, Tasks, Projects, Commitments) | ✅ done | Ranked-card + lit-token throughout |
| W5 | Company, business, admin surfaces (Sources, Messages, Hub, Settings, Audit Log, Billing, Dock, Error Recovery, Notifications, Chat, Teams, Support, Invite, Telegram) | ✅ done | All merged to main |
| M1 | Native token parity (iOS LumiKit.swift, Mac LumiColors.swift, Watch WatchColors.swift, KMP LumiMobilePrimitives.kt) | ✅ done | Byte-for-byte DESIGN.md §19 match |
| M2 | Shared KMP mobile primitives (LumiBadge, LumiCard, LumiEmptyState, LumiSkeletonList, LumiStatusBanner, etc.) | ✅ done | All KMP screens import from LumiMobilePrimitives.kt |
| M3 | Mobile CEO lane evidence trust (Brief, Risks, Decisions, Today severity/confidence signals) | ✅ done | LumiEvidenceTrust composable; merged via PR #739 |
| M4 | Mobile work/business/company lanes (Tasks, Projects, Commitments, Hub, Horizon, Follow-ups, Signal Inbox, Notifications) | ✅ done | All screens confirmed using LumiKit primitives; zero raw color hex in KMP screens |
| M5 | Mobile screenshot/visual-regression gates (Maestro critical flows 11–13, accessibility suite, 200% font-scale, CI runner updates) | 🚧 partial | Flows are committed, but the three post-audit screens, permission-restricted explanation, and named-device/CI artifacts remain open |
Known constraints resolved:
| Priority | Gap | Resolution |
|---|---|---|
| P0 | check-design-tokens.mjs enforces at CI/lint; banned list rejects raw Tailwind palette classes | ✅ W1 |
| P0 | All KMP screens import only from LumiMobilePrimitives.kt; zero raw hex colors in any KMP screen file | ✅ M2/M4 |
| P0 | Brief/Today/Risks/Decisions/Commitments migrated with evidence grammar on every AI item | ✅ W3/M3 |
| P1 | Token parity and primitives landed in parallel with web (M1–M3 concurrent with W1–W3) | ✅ M1–M4 |
| P1 | EvidenceChip (web) and LumiEvidenceTrust (mobile) ship identical three-state grammar | ✅ W2/M3 |
| P1 | Critical flows 11–13 add Workspace, Risks, and Decisions mobile screenshots; accessibility suite adds 200% font-scale coverage | ✅ M5 |
| P2 | iOS/Mac/Watch/KMP all confirmed at DESIGN.md §19 parity before any screen migration | ✅ M1 |
| P2 | W5 completed all admin/breadth surfaces before marking web done | ✅ W5 |
Recommended PR sequence:
- W1: web tokens and guards ✅
- M1: native/KMP token parity ✅
- W2: web primitives ✅
- M2: mobile/shared primitives ✅
- W3 + M3: CEO operating surfaces ✅
- W4: capture and work surfaces ✅
- M4: mobile work/business/company lanes ✅
- W5: company, business, admin surfaces ✅
- M5: screenshot, visual regression, accessibility, and final audit 🚧 partial; named-device/CI evidence and the remaining audit items are open
Done means:
- every listed phase has either shipped or is explicitly superseded with a dated decision; M5 must also have its named-device/CI evidence and remaining audit items closed
- F19 audit gaps addressed or moved to specific remaining specs
- F30/F78/F79 mobile contracts still pass after visual migration
- screenshot and accessibility evidence exists for web and mobile
- no high-traffic screen violates Material Intelligence pre-flight
12. Open Questions / Decisions
- Should F89 implementation use Storybook or an internal primitives gallery as the visual source of truth for component states? If yes, create a follow-up implementation plan.
- Should native mobile screenshots be captured via F51 fake backend first, or wait for real-device CI capacity?
- Should
frontend/scripts/check-design-tokens.mjsbecome a cross-platform token parity checker, or should native parity live in a separate script? - Which web surface becomes the visual reference screen for code review snapshots: CEO Brief, Today/Pulse, or Daily Pulse?
- Should public landing page material imagery be specified under F22, or remain only governed by DESIGN.md/TASTE.md?
13. Bug / Change Log
2026-07-02 — §11 KMP screen count corrected from 55 to 58 (batch 12)
Type: Documentation Truth Fix
Summary:
- §11 Verdict paragraph and M5 matrix row: Updated the audited-screen count from “55 KMP screens” to “58 KMP screens” reflecting the actual file count returned by
find android/shared/src/commonMain -name "*Screen.kt" -path "*/ui/*" | wc -l= 58. The 3 additional screens were added after the 2026-06-27 audit. - Added a follow-up note: the 3 post-audit screens should receive the same one-by-one LumiKit review (verify no raw hex or
Color(0xFF…)usage) before marking M5 fully closed.
2026-06-27 — W5 Notifications lit-token feed slice started
Type: Implementation Change
Summary:
- Migrated the web Notification Center loading rows, unread card rail, and category chips onto shared Material Intelligence Card, Skeleton, and Badge recipes.
- Replaced raw category tone class maps with semantic lit-token
Badgevariants for approval, decision, brief, follow-up, and neutral categories. - Added focused tests for notification card recipes, unread rails, and decision category lit-token styling while preserving mark-read and open-route behavior.
Reason:
- W5 explicitly requires notifications to use lit tokens instead of generic alert cards. Notifications are a trust surface; each alert needs a calm category, age, and action grammar.
Impact:
/notificationsnow uses the same ranked-card and lit-token language as the CEO and W4 work surfaces.- Unread notifications have a material severity rail without changing feed behavior or virtualization.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/NotificationCenterPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Telegram Connect material pairing slice started
Type: Implementation Change
Summary:
- Migrated the web Telegram Connect status token, linked-account state, connected guidance, connection controls, ready-state guidance, and setup step markers onto shared Badge, rounded-card, rounded-control, and shadow-lit recipes.
- Replaced raw rounded-lg/rounded-md setup panels and generic secondary status chips with semantic success, warning, and outline lit-token variants.
- Added focused Telegram tests for disconnected, pending-code, and connected material states while preserving the existing code-generation flow.
Reason:
- Connect surfaces are trust infrastructure. Pairing a CEO’s Telegram chat must feel precise, calm, and accountable, not like a bolt-on integration setup screen.
Impact:
/connect/telegramnow matches the F89 admin/connect material grammar used by Settings, Support, Chat, and Company Hub.- No Telegram API behavior, environment handling, route, or copy changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/TelegramPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Support detail material ticket slice started
Type: Implementation Change
Summary:
- Migrated the web Support Detail status/category/priority metadata, original ticket description, staff controls, internal-note panels, message cards, and feedback prompt onto shared Badge, Card, and Material Intelligence warning/success/danger tokens.
- Replaced raw middle-dot metadata, amber one-off panels, and hardcoded soft status surfaces with semantic lit-token badges and recipe variables.
- Added focused Support Detail tests that pin ticket meta badges plus description and message card recipes while preserving close-ticket and reply behavior.
Reason:
- Support detail is a high-trust admin record. Status, priority, staff-only notes, and customer-visible replies need consistent material semantics instead of ad hoc warning panels.
Impact:
/support/:idand staff support ticket detail rendering now share the same lit-token grammar as the migrated Support list.- No support API contract, routing, mutation behavior, or copy changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/support.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Chat material conversation shell slice started
Type: Implementation Change
Summary:
- Migrated the web Chat loading skeleton, conversation rail, rail summary, active thread shell, updated-at token, sample prompts, and message bubbles onto Material Intelligence radius, badge, skeleton, and lit-edge recipes.
- Replaced raw rounded-xl conversation containers, raw count pills, and muted assistant bubbles with rounded-card shells, semantic Badge tokens, Skeleton primitives, and shadow-lit message surfaces.
- Added focused Chat tests that pin the rail, summary, conversation shell, count token, and assistant bubble material recipes while preserving existing message loading, retry, send, and attachment behavior.
Reason:
- Chat is Lumi’s operating query layer. It should feel like a calm executive workspace, not a generic messaging demo, while retaining the fast scan and keyboard behavior that make follow-up questions useful.
Impact:
/hub/chatnow shares the same lit-token and sheet language as the rest of F89 web surfaces.- No chat API contract, query behavior, attachment behavior, or i18n copy changed.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/ChatPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Settings material admin shell slice started
Type: Implementation Change
Summary:
- Migrated the web Settings summary chips, create/join organization wells, organization switch rows, danger-zone panels, and module rows onto shared Badge and material sheet recipes.
- Replaced raw rounded-lg bordered admin blocks and middle-dot role metadata with consistent lit-token badges, rounded-card wells, and shadow-lit material edges.
- Added focused Settings tests that pin the material recipes while preserving existing organization form, billing visibility, and validation behavior.
Reason:
- W5 requires Settings and admin surfaces to feel as trustworthy as CEO operating surfaces. Organization identity, authority, switching, module visibility, and destructive actions are high-trust controls and cannot look like generic form containers.
Impact:
/settingsnow shares the same admin material grammar as Teams, Invite links, Support, and Company Hub.- No settings behavior or API contract changed; the slice only upgrades visual semantics and guards against recipe drift.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/SettingsPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Invite links material admin slice started
Type: Implementation Change
Summary:
- Migrated the web Invite Members loading state, create-invite form, created-link success state, invite list shell, invite status chips, and empty state onto shared Material Intelligence Card, CardContent, Badge, Label, Skeleton, Button, Select, Input, and EmptyState recipes.
- Replaced raw rounded-xl panels and inline status pill class maps with semantic lit-token badges for active, exhausted, and expired invite links.
- Added focused tests for invite list sheet recipes, active/expired lit-token styling, create-form material labels, created-link success sheet, and visible copy action.
Reason:
- W5 requires Settings and admin surfaces to use consistent sheet/well/authority-seal language. Invite links are access-control material; their status, role, team, and copy/send actions need to feel deliberate and trustworthy.
Impact:
/settings/invitenow shares the same admin material grammar as Teams and Company Hub.- Create and copy behavior remains unchanged, but the page now presents invite state as accountable records instead of generic admin rows.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/InvitePage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Support ticket list material queue slice started
Type: Implementation Change
Summary:
- Migrated the web Support ticket list loading rows and ticket rows onto shared Material Intelligence Card, CardContent, Skeleton, Badge, and Button/link recipes.
- Replaced ghost Button ticket rows and plain metadata separators with keyboard-operable interactive Cards and semantic lit-token status/category/priority chips.
- Added focused tests for support ticket card recipes, lit status and priority tokens, and keyboard navigation into ticket detail routes.
Reason:
- W5 requires Support and admin breadth surfaces to stop feeling secondary. Support tickets are a trust lane; each ticket should read as a calm accountable record with status, priority, and action affordance visible at scan speed.
Impact:
/supportnow shares the same material queue grammar as Company Hub, Teams, Notifications, and the W4 operating lanes.- Ticket rows preserve click navigation while adding explicit keyboard activation on the Card material object.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/support.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Teams material admin slice started
Type: Implementation Change
Summary:
- Migrated the web Teams loading grid, summary chips, create form, team records, expanded team role tokens, members list, and empty members state onto shared Material Intelligence Card, Badge, Skeleton, Label, Input, Textarea, Select, Button, and EmptyState recipes.
- Replaced raw rounded-xl admin panels and inline role/team pills with semantic sheets and lit-token badges while preserving team expansion, member-role editing, member removal, and create-team behavior.
- Added focused tests for Teams material cards, lit summary tokens, member list sheets, and visible create-form labels.
Reason:
- W5 requires Teams and other admin surfaces to use consistent sheet/well/authority-seal language. Teams is an authority surface: roles, managers, and membership must feel accountable instead of bolted on.
Impact:
/settings/teamsnow shares the same Card, Skeleton, Badge, form, and EmptyState language as the F89 Company Hub, notification, work, and CEO surfaces.- The create flow now uses visible labels above fields, matching the F89 form contract and improving scan/accessibility without changing API behavior.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/TeamsPage.test.tsx src/test/TeamMemberRole.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W5 Company Hub material shell slice started
Type: Implementation Change
Summary:
- Migrated the web Company Hub summary, access/pinned tokens, tab shell, announcement loading rows, announcement records, docs loading rows, docs records, and docs empty state onto shared Material Intelligence Card, Badge, Skeleton, Button, Input, and EmptyState recipes.
- Replaced ad hoc badge styling and raw clickable doc rows with semantic lit-token badges and keyboard-operable interactive Card records.
- Added focused tests for Hub shell material recipes, announcement card recipes, doc card interactivity, and keyboard open behavior while preserving existing tab, loading, empty, role, and pinned ordering behavior.
Reason:
- W5 requires Company/Business surfaces to use operating table or ranked-card composition. Company Hub is where trust-critical announcements and operating docs live, so its shell and records must feel like deliberate company material rather than generic secondary admin UI.
Impact:
/hubnow uses the same Card, lit-token, skeleton, and empty-state language as the W3/W4 operating lanes and the W5 notification feed.- Docs are still opened from the same tab flow, but the record itself is now the material object with hover, focus, and keyboard activation.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/HubPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W4 Horizon material row slice started
Type: Implementation Change
Summary:
- Migrated the web Horizon loading rows, deadline rows, overdue rail, and money totals onto shared Material Intelligence Card, Skeleton, and Badge recipes.
- Replaced the nested Button/Card row structure with a keyboard-accessible interactive Card so the row itself is the material object.
- Added focused tests for overdue card recipe, severity rail, and lit money tokens.
Reason:
- Horizon is the forward-looking work lane. It needs to read as a ranked operating list, not a calendar-like cluster of generic rows.
Impact:
/work/horizonnow shares the same material row grammar as Tasks, Projects, Recurring, Signal Inbox, and Follow-ups while preserving navigation and keyboard activation.- Money exposure is now a lit token adjacent to the relevant day and item.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/HorizonPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W4 Follow-ups material evidence slice started
Type: Implementation Change
Summary:
- Migrated the web Follow-ups loading rows, follow-up cards, auto-generated label, status chips, reply evidence well, and send-dialog question label onto shared Material Intelligence primitives.
- Replaced raw status badge class maps with semantic lit-token
Badgevariants for draft, sent, replied, expired, and cancelled states. - Added page-level tests for follow-up card material recipes, visible source/owner/channel/date/action context, replied evidence treatment, and send behavior.
Reason:
- Follow-ups are the chase-and-verify part of the control loop. F89 requires owner, age/source, and action to stay adjacent in a calm material object.
Impact:
/intel/follow-upsnow shares the same Card, Skeleton, Badge, Label, Textarea, and Button grammar as Signal Inbox and the W4 work queue.- Replied evidence is visually present without creating nested cards.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/FollowUpsPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W4 Signal Inbox material evidence slice started
Type: Implementation Change
Summary:
- Migrated the web Signal Inbox loading rows, capture form, signal cards, channel/status chips, proposal confidence chips, and proposal/action buttons onto shared Material Intelligence primitives.
- Replaced raw badge class maps with lit-token
Badgevariants for channel, status, proposal type, and confidence. - Added focused tests for signal card recipes, visible capture labels, lit-token badges, and proposal action behavior.
Reason:
- Signal Inbox is the capture-to-rank intake lane. F89 requires captured signals to show source, owner/age, and action in one calm material object instead of ad hoc cards and badges.
Impact:
/intel/signalsnow uses Card, Skeleton, Label, Badge, Input/Textarea, and Button recipes consistently across capture, review, extract, ignore, accept, and reject flows.- Captured signals carry the same material severity rail language as the W4 work queue while preserving virtualization.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/SignalInboxPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W4 Tasks material control slice started
Type: Implementation Change
Summary:
- Migrated the web Tasks loading rows, summary chips, drag handle, completion control, completed state, and destructive delete confirmation onto shared Material Intelligence primitives.
- Replaced bespoke summary pills with lit-token badges that preserve calm scanability while highlighting waiting and overdue states.
- Added focused tests for task row cards, summary tokens, completion control shape, and destructive delete confirmation styling.
Reason:
- Tasks are the daily work queue. The page already had strong workflow behavior, but the control chrome needed to align with the same material vocabulary as Projects and Recurring.
Impact:
/work/tasksnow uses Card, Skeleton, Badge, and Button recipes more consistently across loading, ranked rows, summary state, drag/reorder, completion, and delete flows.- The W4 work-surface trio (Tasks, Projects, Recurring) now shares the same material grammar for cards, tokens, and destructive actions.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/TasksPage.test.tsx --reporter=verbose
2026-06-27 — W4 Recurring material list slice started
Type: Implementation Change
Summary:
- Migrated the web Recurring loading rows, helper panel, creation form, recurring row cards, schedule chips, active state, and destructive delete confirmation onto shared Material Intelligence primitives.
- Replaced placeholder-only recurring creation fields with visible labels above the recessed inputs.
- Added focused tests for recurring row card recipes, lit-token badges, and creation form shell/label behavior.
Reason:
- Recurring work is part of Lumi’s daily operating rhythm. It should feel durable and scheduled, not like a secondary list bolted onto the workspace.
Impact:
/work/recurringnow uses Card, Skeleton, Badge, Label, Input/Textarea, and destructive Button recipes consistently for its primary list and create/delete flows.- Recurring creation is more accessible and calmer because labels stay visible while users type.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/RecurringPage.test.tsx --reporter=verbose
2026-06-27 — W4 Projects material card slice started
Type: Implementation Change
Summary:
- Migrated the web Projects loading skeleton, creation form, project cards, visibility chip, and destructive delete confirmation onto shared Material Intelligence primitives.
- Replaced placeholder-only project creation fields with visible labels above the recessed inputs.
- Added focused tests for project card material recipes, lit-token visibility, and creation form shell/label behavior.
Reason:
- Projects are part of the daily work surface in W4; they should feel like ranked work objects, not bespoke SaaS tiles.
Impact:
/work/projectsnow uses Card, Skeleton, Badge, Label, Input/Textarea, and destructive Button recipes consistently for the primary list and create flow.- Project creation is more accessible and calmer because labels stay visible while users type.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/ProjectsPage.test.tsx --reporter=verbose
2026-06-27 — W4 Daily Pulse capture material slice started
Type: Implementation Change
Summary:
- Migrated the Daily Pulse capture form shell from a bespoke surface to the shared Card material recipe.
- Returned the primary pulse submit action to the canonical authority Button variant instead of page-local color styling.
- Added focused tests for the material shell/button contract and failed-submit answer preservation.
Reason:
- Daily Pulse is the capture start of the CEO control loop; it must feel calm, durable, and impossible to lose work from.
Impact:
- The capture surface now matches the F89 Card/Button recipes while keeping the single-textarea F83 flow intact.
- Submit failures preserve the typed answer, making error recovery explicit and test-covered.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/PulsePage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W3 Today executive trust rows started
Type: Implementation Change
Summary:
- Added shared
EvidenceChiptrust rows to the web Today page’s executive decision, risk, and commitment cards. - Reused the Decisions/Risks/Commitments evidence and low-confidence copy so Today and detail pages share one trust language.
- Added focused Today coverage for sourced, missing-evidence, and low-confidence states across all executive card types.
Reason:
- Today is the CEO’s first viewport. It must answer “what needs me now?” while making source and confidence state visible without forcing a drill-down into Brief, Risks, Decisions, or Commitments.
Impact:
/work/todaynow shares the same web evidence/confidence grammar as the W3 detail surfaces.- The CEO operating lane is more consistent: Brief, Today, Risks, Decisions, and Commitments all expose evidence state next to the claim.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/TodayPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W3 Commitments trust-row slice started
Type: Implementation Change
Summary:
- Added shared
EvidenceChiptrust states inside the web Commitments table title cell. - Added optional frontend typing for commitment
evidence_sourcesso the table can show source presence/count when the existing API includes evidence IDs. - Added locale keys and tests for sourced, missing-evidence, and low-confidence commitment states, with key parity propagated across shipped locales.
Reason:
- Commitments are the promise-tracking part of the CEO operating lane. The table already ranks by money, priority, and due date; it also needs evidence and confidence adjacent to the promise so accountability is visible without opening a detail view.
Impact:
/intel/commitmentsnow shares the same trust grammar as Brief, Risks, and Decisions while preserving the dense DataTable layout.- W3 core CEO intelligence surfaces now have one consistent web evidence/confidence pattern.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/CommitmentsPage.test.tsx src/test/i18n.test.ts --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W3 Decisions trust-row slice started
Type: Implementation Change
Summary:
- Replaced the web Decisions page’s custom recommended-option confidence pips with shared
EvidenceChiptrust states. - Added optional frontend typing for decision
evidence_sourcesso the page can show source presence/count when the existing API includes evidence IDs. - Added EN/EN-IN/VI copy and tests for sourced, missing-evidence, and low-confidence decision states.
Reason:
- Decisions are a CEO-critical W3 surface. The recommendation needs to feel accountable and consistent with Brief and Risks, not like a separate mini visualization grammar.
Impact:
/intel/decisionsnow shares the same visible evidence/confidence grammar as CEO Brief and Risks.- The recommended option remains visually highlighted, while trust state moves into the calm material row beside the decision claim.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/DecisionsPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W3 Risks trust-row slice started
Type: Implementation Change
Summary:
- Migrated the web Risks list from ad hoc confidence text to shared
EvidenceChiptrust states. - Added optional frontend typing for risk
evidence_sourcesso the page can show source presence/count when the existing API includes evidence IDs. - Added EN/EN-IN/VI copy and tests for sourced, missing-evidence, and low-confidence risk states.
Reason:
- Risks are a CEO-critical W3 surface. Severity rails are not enough; the card also needs a calm, adjacent trust row that shows whether the risk is evidenced and whether confidence should change behavior.
Impact:
/intel/risksnow shares the same trust grammar as CEO Brief while staying honest about the current Risk API shape: evidence count is visible, rich source labels remain future work for the owning serializer slice.- Future W3 Decisions and Commitments work can reuse the same EvidenceChip migration pattern.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/RisksPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W3 CEO Brief trust-signal slice started
Type: Implementation Change
Summary:
- Migrated CEO Brief item source, missing-evidence, and low-confidence display to the shared
EvidenceChipprimitive. - Added explicit tests for source-backed, missing-evidence, and low-confidence Brief states so the CEO Brief can act as the first W3 reference screen.
- Added EN/VI copy for missing evidence and low-confidence chip states.
Reason:
- The CEO’s morning brief must make trust state visible without visual noise: provenance should read as calm evidence, while weak signal quality should be visibly separate.
Impact:
- Brief items now expose evidence gaps and low confidence directly in the item row instead of relying on implicit absence.
- Future W3 migrations can reuse the same evidence grammar across Today, Pulse, commitments, risks, and decisions.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/BriefPage.test.tsx --reporter=verbosecd frontend && ./node_modules/.bin/tsc --noEmit
2026-06-27 — W2 web evidence and ranked-list primitives started
Type: Implementation Change
Summary:
- Added the shared web
EvidenceChipprimitive for source-backed, confirmed, stale, low-confidence, and missing-evidence states. - Aligned Skeleton and DataTable loading/list shells with Material Intelligence recipe tokens.
- Added primitive tests for evidence states, skeleton material treatment, and DataTable sheet/card recipe usage.
Reason:
- CEO surfaces cannot migrate cleanly until evidence, confidence, loading, and ranked-list states are shared primitives instead of per-page styling.
Impact:
- W3 CEO pages can use one visible evidence/confidence grammar instead of hiding trust state in ad hoc text or icons.
- Data-heavy web screens have a clearer Sheet/Card foundation for desktop tables and mobile ranked-card lists.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && npx vitest run src/test/page-primitives.test.tsx src/test/DataTable.test.tsx --reporter=verbose
2026-06-27 — W1 web token guard foundation started
Type: Implementation Change
Summary:
- Added the first web implementation slice for W1: canonical CSS token presence checks, scoped one-off radius guard coverage for migrated primitives, contrast coverage for material edges/control pairs, and primitive radius alignment to Material Intelligence recipe tokens.
Reason:
- The upgraded design system must become mechanically enforceable before high-traffic page rewrites begin.
Impact:
- Web primitives can migrate toward recipe-level tokens (
rounded-control,rounded-card,rounded-pill) without broad page churn. - Existing historical page/share-card styling debt remains for later W phases; the new guard prevents the migrated primitive foundation from regressing.
Tests:
node frontend/scripts/check-design-tokens.mjscd frontend && ./node_modules/.bin/tsc --noEmitcd frontend && pnpm test
2026-06-27 — Draft Material Intelligence redesign transformation spec
Type: Documentation Change
Summary:
- Added F89 as the implementation contract for transforming current web and mobile surfaces to the upgraded Lumi Material Intelligence design system.
Reason:
- DESIGN.md and TASTE.md now define the target product language, but the repo needed a feature-level spec with phases, acceptance criteria, states, and verification gates.
Impact:
- Future web and mobile redesign work should implement against F89, while preserving F19/F30/F78/F79 feature ownership.
Tests:
- Documentation-only.
git diff --checkmust pass.
Notes:
- F89 adds no backend model, endpoint, or feature capability. It is a cross-platform UI/UX transformation spec.
2026-06-28 — Full-product web audit: zero remaining violations
Type: Implementation Change
Summary:
- Systematic grep audit across all
frontend/src/pages/directories confirmed ~53 files still had residual F89 violations not caught by the token guard script: rawanimate-pulseloading divs,rounded-xl/rounded-lgcontainer radius, andbg-whitein non-semantic positions. - Replaced all remaining
animate-pulsedivs with<Skeleton rounded-card>in CRM (CalendarView, CompanyTimeline, DealContactRoles, DealDetailPanel, DealLineItems, DealQuoteSection, ForecastView, NextActivityCard, TimelineView), auth (AcceptInvitePage), business (ContactsPage), intel (ChaosImportPage), and settings (OnboardingPage). - Fixed all remaining
rounded-xl/rounded-lgcontainer radius torounded-cardacross HQ, jobs, store, connect, apps, crm, and work pages. - Fixed
bg-white→bg-card/bg-backgroundin hub and store marketing pages. - Fixed
border-l-[var(--color-*)]TWM conflict: all left-border accent colors (BriefPage, RisksPage, TodayPage, TasksPage, HorizonPage, NotificationCenterPage, SignalInboxPage, DecisionsPage, HqDashboardPage, SettingsPage) now use[border-left-color:var(--color-*)]arbitrary property soborder-l-4width class is preserved (previously silently removed by tailwind-merge v3). - Fixed
HorizonPage.toISODateUTC-vs-local bug: function changed from.toISOString().split('T')[0](UTC) togetFullYear/Month/Date(local), matching the test helper and makingisOverduecorrect in UTC+ timezones.
Reason:
- Token guard only catches banned palette classes and inline hex — not
rounded-lg,rounded-xl,animate-pulse, orbg-white. A full-product grep audit was needed to reach zero remaining violations. - The TWM conflict was a silent visual regression: overdue/critical items showed a 1px colored border instead of the intended 4px accent rail.
- The timezone bug caused the HorizonPage overdue row test to fail at midnight in Vietnam time (UTC+7 — UTC time is still the previous day before 07:00 local).
Impact:
- Web product now has zero F89 violations in
frontend/src/pages/. Token guard + systematic grep audit confirm. - HorizonPage timezone fix makes
isOverduecorrect regardless of UTC offset. - Border-left TWM fix restores the 4px accent rail on overdue, risk, and urgency items.
Tests:
node frontend/scripts/check-design-tokens.mjs— passes cleangrep -rn "rounded-xl|rounded-lg|animate-pulse|bg-white" frontend/src/pages/— zero hitscd frontend && pnpm test— 10,999 passed (previously 10,998 + 1 failing)cd frontend && ./node_modules/.bin/tsc --noEmit— 0 errors
2026-06-28 — Web operating surfaces material follow-up
Type: Implementation Change
Summary:
- Replaced the TaskDetailPanel hand-rolled
animate-pulseloading divs with shaped<Skeleton>rows and normalized remaining work-panel radii torounded-card/rounded-control. - Kept the CRM no-next-activity warning on the amber attention rail while fixing the
border-l-[var(--color-signal-amber)]tailwind-merge conflict with[border-left-color:var(--color-signal-amber)]. - Extended focused web regression coverage around commitments, CRM activity health, deal detail actions, Horizon, Today, and task-detail material states.
Reason:
- The prior full-page sweep did not include shared work components outside
frontend/src/pages/, and new CRM follow-up edits reintroduced one border-left conflict. - Work detail panels are daily operator surfaces; their loading state should use the same material skeleton grammar as the rest of the product.
Impact:
- Web page and shared work-component audit greps now return zero hits for raw
animate-pulse, non-token rounded utilities, rawbg-white, andborder-l-[var(...)]. - No API, route, or data-model change.
Tests:
node frontend/scripts/check-design-tokens.mjsgrep -rn "animate-pulse|rounded-xl|rounded-lg|rounded-md|rounded-sm|bg-white\b" frontend/src/pages/ frontend/src/components/work/grep -rn "border-l-\[var(" frontend/src/pages/ frontend/src/components/work/cd frontend && ./node_modules/.bin/tsc --noEmitcd frontend && pnpm test -- src/test/CommitmentsPage.test.tsx src/test/CrmActivities.test.tsx src/test/DealAnalytics.test.tsx src/test/DealDetailPanel.test.tsx src/test/HorizonPage.test.tsx src/test/TaskDetailPanel.test.tsx src/test/TodayPage.test.tsx
2026-07-02 — Spec drift fix: checked shipped ACs in §2
Type: Documentation
Summary:
- 18 of 19
[ ]ACs in §2 flipped to[x]; the permission-restricted explanation remains unchecked. W1–W5 web work and M1–M4 mobile source work are complete, while M5 remains partial pending the three post-audit screen review and runtime evidence. - Checked: §2.1 all five CEO/leadership surface ACs (Brief material, mobile Pulse operating-home, AI evidence adjacent, quiet-day silence state, severity rail); §2.2 all four operator/member ACs (Daily Pulse form, submit-fail preserves input, mobile ranked cards, DataTable material rules); §2.3 two of three admin ACs (settings routes use correct recipes, destructive styling); §2.4 all four native mobile parity ACs (iOS/Android token/radius parity, 200% font-scale, modal sheet 16px radius, evidence label-visible); §2.5 all three design-system integrity ACs (static token guard, token parity check, screenshot gates).
- Left
[ ]: §2.3 permission-restricted section “explains why access is restricted and where to go next” — W5 confirms visual migration of settings surfaces but does not explicitly confirm the functional role-explanation copy/component behavior in §11 rows. - No code changes.
2026-06-28 — M6 Mobile dialog shell upgrade + settings token fix
Type: Implementation Change
Summary:
- Added
LumiDialogCardprimitive toLumiMobilePrimitives.kt. All KMP Dialog composables previously used a rawSurface(shape = MaterialTheme.shapes.extraLarge, tonalElevation = 6.dp, color = MaterialTheme.colorScheme.surface)workaround (the CMP 1.10.x AlertDialog_skikoKt bug).LumiDialogCardreplaces this withRoundedCornerShape(LumiMobileTokens.CardRadius),SurfaceWhitebackground, and a 1dpBorder— matching the webrounded-card+shadow-cardmaterial recipe. - Fixed 17 dialog shell occurrences across 15 screens: DecisionsScreen (×2), SignalInboxScreen (×2), RisksScreen, CommitmentsScreen, TasksScreen, FollowUpsScreen, ProjectsScreen, ApprovalsScreen, RecurringDetailScreen, RecurringScreen, SettingsScreen, DealsScreen, OrgManagementScreen, ProjectBoardScreen, ChatScreen.
- Fixed 3 hardcoded
RoundedCornerShape(10.dp)radii in SettingsScreen action rows →LumiMobileTokens.CardRadius(8dp). - Upgraded RecurringScreen frequency/paused status chip from raw
Surface(shape = RoundedCornerShape(999.dp), ...)→LumiBadge(tone = Info/Warning, showDot = false).
Reason:
MaterialTheme.shapes.extraLargeresolves to 28dp in M3 — visually inconsistent with the 8dp Lumi card radius. All 31 original rawSurface()calls outsideLumiMobilePrimitiveswere audited; 17 were dialog shells using the wrong shape/color. The remaining 14 are intentional (chat bubbles, flat list rows, screen wrappers).
Impact:
- All modals/dialogs on every mobile screen now wear the Lumi card shape, paper-white background, and border — same visual grammar as web.
- Settings action rows (language, sign-out, delete-account) now use the canonical 8dp radius.
- No API, route, i18n, or behavior change.
Verification:
grep -rn "MaterialTheme.shapes.extraLarge" android/shared/src/commonMain/kotlin/com/locuno/lumi/shared/ui/— zero hits (excluding LumiMobilePrimitives itself)grep -rn "RoundedCornerShape(10.dp)" android/shared/src/commonMain/kotlin/com/locuno/lumi/shared/ui/— zero hits