fix: align Event Lineage shell with UI UX guide - #350
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
LineageWeave has no explicit buyer actor -- rename BuyerNav/BuyerDestination to WorkspaceNav/WorkspaceDestination, .buyer-gnb* CSS to .workspace-gnb*, the "Buyer navigation" i18n key, the "BUYER EVIDENCE" legend label, and backend _buyer_evidence_kind/_buyer_evidence_text helpers. Replace prose referring to "the buyer" with "the reader" in AGENTS.md, ARCHITECTURE.md, docstrings, living docs, and test descriptions/idempotency keys. Historical ADRs (0002-0118) and CHANGELOG.md/CHANGELOG.d entries keep their original wording as a point-in-time record; ADR 0119 documents the rename. Fixture/table content that uses "buyer" as ordinary sales-note prose is left untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Found and fixed a concrete terminology defect in the locale layer: the new Changed translations to workspace wording and added locale regression coverage. Local verification on exact post-fix HEAD: frontend lint; 13 files / 144 tests; Protected merge gate remains: independent approval and all required terminal checks are still required. |
|
Implemented on exact head
The protected PR Checks and independent review have restarted for this exact head; no merge bypass was used. |
…erge' into fix/uiux-standard-guide-v3-postmerge
|
Applied the ADR 0119 terminology correction on exact head
Protected Checks and independent review have restarted for this exact head. |
|
Exact head 9d124c8 was revalidated after the remote terminology update. Frontend lint passed, 144 tests passed, Vite build passed, and Storybook build passed. Hosted checks are still queued and formal approval is still required; no merge attempted. |
…erge' into fix/uiux-standard-guide-v3-postmerge
- Add a custom Keycloak login theme (docker/keycloak/themes/lineageweave) extending keycloak.v2 with the app's Noto Sans / brand-blue tokens, white background instead of the stock dark polygon image, and a fixed !important-vs-!important override so the realm brand text is legible (the parent theme's #kc-header-wrapper white-on-dark color otherwise renders white-on-white once the background is swapped to white). Set displayName/loginTheme on the realm so "LINEAGEWEAVE-DEMO" no longer shows as the raw realm slug. - Reorder the post-detail popup: the Korean summary and 5W1H now render immediately after the title/actions in a two-column grid (.popup-analysis-grid, single column below 768px), instead of after the full raw post body. The raw body and "Original source state" raw codes move below the analysis, next to Event Lineage/Keyman -- they are supporting evidence, not the first thing a reader needs to see. - Fix the phone header (<=768px): .app-header-top-menu no longer clips the language/search/logout controls off the right edge of a 390px viewport. It now wraps onto additional rows instead, so logout stays reachable (SS3.2 requires a clear logout path on every page). Found via a manual visual E2E walkthrough (login -> board -> post popup -> workspace destinations -> 390px mobile) driven by Playwright against the local docker compose stack. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Nothing in the app respected prefers-reduced-motion: reduce -- every transition/animation played at full motion regardless of the user's OS setting, an explicit anti-pattern on the ui-ux-pro-max Animation checklist. Add the standard global override (near-zero duration instead of fully removing the transition, so state changes stay perceptible without the motion itself). Also switch the skip-link's reveal-on-focus from animating `top` (layout-triggering) to `transform: translateY()` (compositor-only) -- the same category of fix as the checklist's "animating width/height" anti-pattern, free to make while touching this rule. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
| updated_at = _timestamp(_value(row, mapping.updated_at, created_at)) | ||
| post_id = _source_post_id(row, mapping, args.source_system_code, record_key) | ||
| title = str(_value(row, mapping.title, "") or "") | ||
| body = str(_value(row, mapping.body, "") or "") | ||
| body = resolved_bodies[row_number] |
There was a problem hiding this comment.
📝 Info: MHTML body resolver reuses preflight results by row number
import_rows caches each resolved body by row_number during _validate_source_rows, then reads resolved_bodies[row_number] in the import loop. Both loops use enumerate(rows, start=1) and skip excluded rows with the same _source_code_matches check, keeping row numbers aligned so non-excluded rows never hit a missing key.
(Refers to this code)
Was this helpful? React with 👍 or 👎 to provide feedback.
Root/branch/current status was only conveyed by stroke color and border width. Add the same legend wording used visually to each node's aria-label and title tooltip so it reaches screen reader and colorblind users too. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…erge' into fix/uiux-standard-guide-v3-postmerge
| useEffect(() => { | ||
| if (focusSearchRequest <= lastFocusedSearchRequest.current) return; | ||
| const input = searchInputRef.current; | ||
| if (!input) return; | ||
| lastFocusedSearchRequest.current = focusSearchRequest; | ||
| input.focus(); | ||
| onSearchFocusHandled?.(); | ||
| }, [focusSearchRequest, onSearchFocusHandled, posts]); |
There was a problem hiding this comment.
🟡 Header Search button focuses the box only on its first click
The Search button increments focusSearchRequest, and the focus effect records lastFocusedSearchRequest.current at that value and then resets focusSearchRequest to 0 via onSearchFocusHandled. The next click raises it 0→1 again, which fails the focusSearchRequest <= lastFocusedSearchRequest.current guard, so no focus happens. While the board stays mounted only the first click focuses the search box; later clicks do nothing until the user leaves and returns.
Prompt for agents
The global Search focus request in PostList (frontend/src/App.tsx:3632-3639) breaks on repeated use. The effect stores lastFocusedSearchRequest.current = focusSearchRequest after focusing, but onSearchFocusHandled (in App: () => setSearchFocusRequest(0)) resets the request counter to 0 while lastFocusedSearchRequest stays at the previous value. Because the header button only ever increments 0->1, the guard focusSearchRequest <= lastFocusedSearchRequest.current becomes 1 <= 1 and the effect returns early, so the second and later clicks of the header Search button do not focus the search input until PostList is remounted. Reconcile the two pieces of state so each Search request focuses again: e.g. reset lastFocusedSearchRequest.current back to 0 when the request is cleared, or treat focusSearchRequest as a one-shot flag handled without leaving the ref ahead of the counter. Ensure the existing behavior (no focus-steal during later filter/sort/page reloads, and clearing a pending request when leaving the board) is preserved.
Was this helpful? React with 👍 or 👎 to provide feedback.
| if exists ( | ||
| select 1 from information_schema.columns | ||
| where table_schema = 'public' | ||
| and table_name = 'analysis_run_status_event' | ||
| and column_name = 'retryable' | ||
| ) then | ||
| alter table public.analysis_run_status_event | ||
| rename column retryable to is_retryable; | ||
| end if; | ||
| end | ||
| $$; |
There was a problem hiding this comment.
🔍 Verify 0018 trigger does not reference renamed retryable column
0104 renames analysis_run_status_event.retryable to is_retryable and recreates the current-status view. If 0018's enforce_analysis_run_status_transition() trigger function references the old retryable column in its body, the rename would break inserts against that table. The view recreation is handled; confirm the trigger/function is not affected.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
Rechecked against the latest remote head
Hosted checks are still queued and there is no formal approval yet, so this PR is not merge-ready. |
| if (focusSearchRequest <= lastFocusedSearchRequest.current) return; | ||
| const input = searchInputRef.current; | ||
| if (!input) return; | ||
| lastFocusedSearchRequest.current = focusSearchRequest; | ||
| input.focus(); | ||
| onSearchFocusHandled?.(); |
There was a problem hiding this comment.
🟡 Header Search refocuses the search box only once
The header Search button increments searchFocusRequest from 0, since onSearchFocusHandled resets it to 0 after each handled request. The focus effect fires only when the value exceeds lastFocusedSearchRequest, which stays at 1 after the first focus. A second Search click while staying on the Board never refocuses the search box.
Was this helpful? React with 👍 or 👎 to provide feedback.
* fix: preserve oidc deep links across callback storage * fix: render buyer-facing image evidence * fix: label unavailable image evidence * docs: avoid oidc adr number collision * docs: avoid buyer image adr number collision * fix: bind summary actions to source-grounded projects * test: cover project-bound summary action round trip * docs: record buyer gap checkpoint evidence * docs: align image evidence ADR heading * docs: align OIDC ADR heading * fix: preserve legacy action evidence delimiters * docs: refresh buyer gap audit checkpoint * docs: record current project action head * feat: bind summary events to source-grounded projects * docs: record full checkpoint verification * fix(summary): normalize project keys before persistence * docs: refresh exact-head buyer gap audit * test(summary): cover project key sentinel normalization * test(image): cover source placement and OCR rendering * fix: preserve stale summary buyer continuity * fix: keep post content recovery alive * test(summary): cover stale continuity and retry * feat: add explicit post content retry * test(queue): cover explicit retry rejection * docs(queue): complete retry command docstrings * fix: reconcile backfill content with job ledger * fix(ui): preserve indentation after mixed content * docs: record post content recovery evidence * docs(ui): clarify indentation matching boundary * test(ui): cover missing source unit fallback * fix: serialize per-post vision region analysis * fix(ui): preserve adjacent table boundaries * fix: preserve honest image evidence rendering * fix: separate source whitespace from explicit structure * docs: record source indentation buyer gap * feat: enrich semantic hints from source catalogs * fix: reject non-decomposed vision regions * docs: refresh protected gate baseline * docs: record corrected image region evidence * fix: trim source catalog lookup codes * docs: record catalog hint boundary * docs: record exact-head validation evidence * docs: record live browser acceptance * docs: refresh live gate topology * fix: refresh content after summary ingestion * test: cover lineage graph interactions * fix: bound OIDC return state parsing * fix: validate buyer image sources at render boundary * fix: expose unexpected content channel defects * fix: expose recoverable content batch failures * test: define directional accessible lineage graph contract * test: avoid duplicate lineage marker identities * feat: make event lineage direction and evidence explicit * fix: keep lineage graph legible across themes and widths * fix: expose lineage evidence by default * test: require accessible lineage graph regions * feat: make lineage graph structure accessible * style: add lineage graph interaction states * docs: add lineage graph Storybook states * docs: record lineage DAG evidence improvements * test: keep lineage node controls exposed to assistive technology * fix: expose lineage node controls outside image semantics * docs: record buyer lineage DAG design boundary * test: cover isolated roots and fused-score labeling * fix: omit empty lineage evidence tables * docs: add isolated lineage Storybook state * docs: record Event Lineage Figma frame IDs * test: require lineage meaning and legend disclosure * test: require five-locale lineage meaning copy * feat: add localized lineage meaning copy * feat: disclose lineage legend and inference boundary * style: add lineage legend and inference notice * docs: record lineage meaning and legend disclosure * test: require actionable lineage empty state and Space activation * test: require localized lineage empty-state next action * feat: localize actionable lineage empty state * feat: make the lineage empty state actionable * docs: record actionable lineage empty state * test: require mobile evidence-card labels * feat: label mobile lineage evidence cards * fix: guard lineage dag layout against cycles * docs: plan forward-only fast stabilization * test: reproduce lineage date specificity defect * fix: preserve muted lineage event-date styling * fix: keep unauthenticated admin controls gated * fix: align Event Lineage shell with UI UX guide (#350) * fix: align buyer lineage shell with UI UX guide * docs: track post-merge UI UX review gate * feat: expose authorized account scope and global search * fix: place locale control in header top menu * docs: record central hourly merge loop * fix: refocus buyer search after board load * refactor: retire "Buyer" terminology across code and living docs LineageWeave has no explicit buyer actor -- rename BuyerNav/BuyerDestination to WorkspaceNav/WorkspaceDestination, .buyer-gnb* CSS to .workspace-gnb*, the "Buyer navigation" i18n key, the "BUYER EVIDENCE" legend label, and backend _buyer_evidence_kind/_buyer_evidence_text helpers. Replace prose referring to "the buyer" with "the reader" in AGENTS.md, ARCHITECTURE.md, docstrings, living docs, and test descriptions/idempotency keys. Historical ADRs (0002-0118) and CHANGELOG.md/CHANGELOG.d entries keep their original wording as a point-in-time record; ADR 0119 documents the rename. Fixture/table content that uses "buyer" as ordinary sales-note prose is left untouched. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: translate workspace navigation labels * fix: make buyer search focus one-shot and localize lineage label * docs: record authenticated UI UX gap evidence * fix: use lineage evidence terminology * fix: keep health probe public and settings route covered * docs: record current health and lineage coverage gaps * fix: brand the Keycloak login theme and put post-popup analysis first - Add a custom Keycloak login theme (docker/keycloak/themes/lineageweave) extending keycloak.v2 with the app's Noto Sans / brand-blue tokens, white background instead of the stock dark polygon image, and a fixed !important-vs-!important override so the realm brand text is legible (the parent theme's #kc-header-wrapper white-on-dark color otherwise renders white-on-white once the background is swapped to white). Set displayName/loginTheme on the realm so "LINEAGEWEAVE-DEMO" no longer shows as the raw realm slug. - Reorder the post-detail popup: the Korean summary and 5W1H now render immediately after the title/actions in a two-column grid (.popup-analysis-grid, single column below 768px), instead of after the full raw post body. The raw body and "Original source state" raw codes move below the analysis, next to Event Lineage/Keyman -- they are supporting evidence, not the first thing a reader needs to see. - Fix the phone header (<=768px): .app-header-top-menu no longer clips the language/search/logout controls off the right edge of a 390px viewport. It now wraps onto additional rows instead, so logout stays reachable (SS3.2 requires a clear logout path on every page). Found via a manual visual E2E walkthrough (login -> board -> post popup -> workspace destinations -> 390px mobile) driven by Playwright against the local docker compose stack. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: localize Event Lineage labels * fix: complete lineage locale coverage * fix: remove duplicate lineage locale keys * test: reproduce phone header padding override * fix: bound normalized body search indexes * fix: preserve phone header padding * docs(gap): track external lineage and calendar integration * docs: record search and phone UI gap fixes * docs: anchor merged gap baseline * docs: record current runtime evidence * docs: record source mapping boundary * test: preserve global search focus behavior * fix: preserve UI guide shell and exact Event Lineage evidence * fix: preserve metric scripts and replay tenant settings * fix: keep lineage boundary evidence accessible * docs: refresh UI UX and runtime gap evidence * docs: refresh stacked PR gate status * fix: preserve lineage edge direction markers * fix: bump minimum control size to the 44px touch-target floor --size-control-min was 24px, well under the WCAG 2.5.5 / platform minimum of 44x44px. It backed three icon-only, high-traffic controls with no other size constraint: the mobile drawer hamburger trigger, the main post-popup close button (.popup-close, previously sized only by its font-size glyph with no box), and the mobile drawer close button. Bump the token once and give the trigger/popup-close buttons the flex centering needed so the larger hit area doesn't misalign the glyph. Found via the ui-ux-pro-max skill's touch-target checklist, cross- checked against the live app. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * feat: add a skip-to-main-content link for keyboard users The authenticated shell puts a sticky header top-menu (user info, language, search, logout) and a five-item GNB before <main>, so a keyboard user had to Tab through all of it on every page load with no way to jump straight to content. Add a standard skip link: visually hidden until focused, translated in all five locales, and explicitly focuses #main-content on activation rather than relying on native anchor-fragment focus (inconsistent across browsers, notably Safari, and not exercised by jsdom in tests). Found via the ui-ux-pro-max skill's Accessibility checklist (Skip Links, priority 1). Also fixes a stacking bug caught while verifying it live: the skip link initially shared --z-header with the sticky header, so with equal z-index the header (later in DOM order) painted over it -- focused but invisible. Added a dedicated --z-skip-link token above every other layer. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * perf: lazy-load and async-decode embedded post images Posts can carry a dozen-plus embedded base64 images (e.g. the HSWG technical-diagram post seen during manual walkthrough). None had loading="lazy" or decoding="async", so opening a popup forced the browser to synchronously decode every embedded image up front instead of deferring off-screen ones -- main-thread cost that scales with how image-heavy a given post is. Image scaling (max-width:100%/height:auto) and the Noto Sans web font load (display=swap + preconnect) were already correct; checked both while auditing this against the ui-ux-pro-max Performance checklist. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * docs: remove stale duplicate gap section reintroduced by a merge A concurrent session independently resolved the same feat/lineage-dag-regression <- fix/uiux-standard-guide-v3-postmerge merge conflict and pushed it first (d0cef47). Their resolution for docs/product-technical-gap-baseline.md kept both sides of the conflict instead of dropping the stale one, reintroducing an old, generic "## 2. LLM Extraction & Knowledge Graph Gaps" / "## 3. General Architecture Gaps" section -- duplicating the "## 2" heading number and sitting stale content (Entity Resolution/Searxng, Base64 Image Omni-modal, DB Architecture, Zotero, PII masking, LLM Orchestration) ahead of the detailed, current traceability table that already tracks every one of those same topics with live-corpus evidence. Verified equivalent (already-pushed tip matches everywhere else this worktree's merge resolution touched: workspace-gnb naming, the skip-link CSS, and the mobile lineage-dag-evidence rules are all present), then reset this local branch to the pushed tip and removed just the reintroduced stale section, restoring sequential ## numbering. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: enforce canonical database identifiers * docs: record final local quality evidence * docs: anchor final exact audit head * fix: close mobile navigation and preserve search focus * docs: refresh acceptance evidence after UI fix * docs: record mobile navigation review fixes * fix: use inline SVG icons instead of raw glyphs for menu/close buttons The mobile drawer trigger ("☰"), drawer close ("×"), and main popup close (PopupCloseButton, "×") all rendered raw font glyphs. A glyph's shape, weight, and baseline vary by OS/browser font stack -- inconsistent with the design system's rendered chrome and a known anti-pattern (SVG icons, no emoji/glyph icons is a Must-Have per ui-ux-pro-max's Style Selection checklist). Added two small inline SVG icons (MenuIcon, CloseIcon; no new dependency -- native SVG covers it) using currentColor so they inherit each button's existing color token, and swapped all three usages. aria-labels are unchanged so no accessible-name regression. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * test: model mobile drawer navigation flow * docs: anchor drawer acceptance evidence * feat: resolve source bodies from verified MHTML artifacts * fix: floor form-control font-size at 16px to stop iOS auto-zoom The base font scales down at narrower breakpoints (16px -> 15px -> 14px at 768px, SS2.1.2), and the existing "Base Form & Input Standards" block (SS3.1.4) inherited that scale verbatim on every input/select/ textarea. Any focused control under 16px makes iOS Safari zoom the whole viewport -- a well-known WebKit behavior unrelated to the body- text density tuning that rule exists for. Floor it at `max(16px, 1em)` so it still respects an explicitly larger font-size where one is set, but never drops below 16px. The one place with its own smaller explicit size (.language-switcher select at 0.82rem) gets the same floor for the same reason -- select focus triggers the same WebKit zoom. Found via the ui-ux-pro-max Typography & Color checklist ("Base 16px"). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix: respect prefers-reduced-motion and use transform for skip-link Nothing in the app respected prefers-reduced-motion: reduce -- every transition/animation played at full motion regardless of the user's OS setting, an explicit anti-pattern on the ui-ux-pro-max Animation checklist. Add the standard global override (near-zero duration instead of fully removing the transition, so state changes stay perceptible without the motion itself). Also switch the skip-link's reveal-on-focus from animating `top` (layout-triggering) to `transform: translateY()` (compositor-only) -- the same category of fix as the checklist's "animating width/height" anti-pattern, free to make while touching this rule. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * docs: refresh source mapping acceptance evidence * fix: clear stale search focus on navigation * fix: improve post popup action layout * docs: record navigation focus acceptance * fix: label chat and ticket inputs * docs: anchor accessibility acceptance head * feat: model operational vocabularies in ontology * fix: preserve popup history navigation * fix: name lineage DAG node kind for screen readers and tooltips Root/branch/current status was only conveyed by stroke color and border width. Add the same legend wording used visually to each node's aria-label and title tooltip so it reaches screen reader and colorblind users too. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * docs: refresh product gap evidence baseline * fix: preserve search focus request boundaries * fix: add send affordance to ask actions * docs: anchor baseline to final UI head * feat: add desktop site map utility * fix: improve desktop evidence popup layout * docs: record site map and popup gap evidence * feat: turn Ask Agent into an evidence conversation --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
| return {} | ||
| fields = {"ontology_iri": str(subject)} | ||
| label = ONTOLOGY.value(subject, RDFS.label) | ||
| label = ONTOLOGY.value(subject, RDFS.label) or ONTOLOGY.value(subject, SKOS.prefLabel) |
There was a problem hiding this comment.
📝 Info: Operational lookup codes now resolve to ontology labels
ontology_annotations/iri_for_lookup_code now resolve operational codes (visibility, voc, permission, ticket status) that previously returned empty, via the new RDFS.label or SKOS.prefLabel fallback (ontology.py). Any caller relying on empty results to suppress a label would change behavior. Backend label surfaces use common_lookup_value joins here, so no regression was found.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
Revalidated the remote branch tip
The PR API still reports |
|
Exact PR-head revalidation for remote-agent race at |
Forward-only product scope
This PR keeps the complete UI/UX Guide v3 buyer surface and now sits directly on the stabilized Event Lineage foundation from #330.
fused_scoreevidence, isolated/empty states, five-locale copy, Figma frames, and Storybook inventory.Lineage evidenceinformation architecture while using the stronger per-group exact-value evidence contract.mobileHeaderCss.test.tsprevents the duplicate cascade from returning.Buyerterminology with the workspace vocabulary while keeping authorization and domain objects unchanged.Forward stack convergence completed
A two-parent merge commit incorporates exact parent #330 head
1fad94ff4ec6007d3d3b732580ed68b586f56061without force-push or history rewrite. Conflict resolution preserves both capability sets: the UI/UX Guide shell remains, and #330's complete Event Lineage semantics/tests/assets are inherited. GitHub compare reports behind0against the exact parent.Exact current candidate
feat/lineage-dag-regression@1fad94ff4ec6007d3d3b732580ed68b586f56061.ef7d33489d73e2e71cd613b6760a1788f753f21a.APPROVEDfor this head.Protected merge gate
Merge only after #330 integrates, the stacked exact head is revalidated, every required check is terminal-success, no valid review thread remains, and an independent formal approval exists. No force-push, self-approval, protection bypass, dependency downgrade, or capability reduction is allowed.