Skip to content

fix: align Event Lineage shell with UI UX guide - #350

Merged
seonghobae merged 76 commits into
feat/lineage-dag-regressionfrom
fix/uiux-standard-guide-v3-postmerge
Aug 21, 2026
Merged

fix: align Event Lineage shell with UI UX guide#350
seonghobae merged 76 commits into
feat/lineage-dag-regressionfrom
fix/uiux-standard-guide-v3-postmerge

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

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.

  • Adds the authenticated mobile navigation drawer and keeps logout, language, scope, search, and current destination reachable on narrow screens.
  • Preserves feat: make Event Lineage directional and evidence-readable #330's node-clear direction, visible dates, accessible SVG controls, deterministic layout, redundant legend, non-causal truth boundary, exact fused_score evidence, isolated/empty states, five-locale copy, Figma frames, and Storybook inventory.
  • Retains the UI/UX Guide header and Lineage evidence information architecture while using the stronger per-group exact-value evidence contract.
  • Focuses global Search exactly once per request after the Board finishes loading, without stealing focus during later filter, sort, or page refreshes.
  • Preserves phone vertical header padding through one media-query rule; mobileHeaderCss.test.ts prevents the duplicate cascade from returning.
  • Replaces user-facing Buyer terminology with the workspace vocabulary while keeping authorization and domain objects unchanged.
  • Keeps the public gap baseline synthetic and records cross-repository calendar and external-lineage boundaries without pulling those products into this UI PR.

Forward stack convergence completed

A two-parent merge commit incorporates exact parent #330 head 1fad94ff4ec6007d3d3b732580ed68b586f56061 without 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 behind 0 against the exact parent.

Exact current candidate

  • Exact stacked parent: feat/lineage-dag-regression@1fad94ff4ec6007d3d3b732580ed68b586f56061.
  • Exact current head: ef7d33489d73e2e71cd613b6760a1788f753f21a.
  • Valid unresolved review threads: zero.
  • Exact-current-head Tests, SAST Semgrep, and Security Scan must regenerate; queued, absent, or predecessor evidence is non-passing.
  • Existing reviews do not constitute current-head approval unless GitHub records APPROVED for 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.


Open in Devin Review

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 221f7f44-9a2f-4067-a332-2492a6d8df47

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae
seonghobae enabled auto-merge (squash) August 21, 2026 04:13
devin-ai-integration[bot]

This comment was marked as resolved.

seonghobae and others added 2 commits August 21, 2026 13:20
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>
@seonghobae

Copy link
Copy Markdown
Contributor Author

Found and fixed a concrete terminology defect in the locale layer: the new Workspace navigation key still rendered buyer terminology in Korean, Chinese, Japanese, and Vietnamese.

Changed translations to workspace wording and added locale regression coverage. Local verification on exact post-fix HEAD: frontend lint; 13 files / 144 tests; git diff --check. Hosted required checks must still run on 0937a984.

Protected merge gate remains: independent approval and all required terminal checks are still required.

@seonghobae

seonghobae commented Aug 21, 2026

Copy link
Copy Markdown
Contributor Author

Implemented on exact head d49c7169ca302ba4f031fe0e79472e0a2d656001.

  • Search focus is now consumed only after the input exists and is focused, so list reloads no longer steal focus.
  • Event Lineage's Buyer evidence eyebrow uses i18n in Korean, English fallback, Chinese, Japanese, and Vietnamese.
  • Local evidence: App.test.tsx + i18n.test.ts: 100 passed; pnpm run lint: passed; pnpm run build: passed.

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
devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Applied the ADR 0119 terminology correction on exact head 9d124c87.

  • The Event Lineage eyebrow now uses Lineage evidence, not the retired Buyer evidence label.
  • Korean, Chinese, Japanese, and Vietnamese translations and the authenticated App regression expectation were updated together.
  • Local evidence: App/i18n tests 100 passed; frontend lint and production build passed.

Protected Checks and independent review have restarted for this exact head.

devin-ai-integration[bot]

This comment was marked as resolved.

@seonghobae

Copy link
Copy Markdown
Contributor Author

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.

seonghobae and others added 5 commits August 21, 2026 14:12
…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>
seonghobae and others added 7 commits August 21, 2026 17:07
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>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 new potential issues.

Open in Devin Review

Comment thread migrations/0035_body_search_prefix.sql
Comment thread frontend/src/App.tsx
Comment on lines 490 to +493
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]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 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)

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 new potential issues.

Open in Devin Review

Comment thread frontend/src/App.tsx
Comment on lines +3632 to +3639
useEffect(() => {
if (focusSearchRequest <= lastFocusedSearchRequest.current) return;
const input = searchInputRef.current;
if (!input) return;
lastFocusedSearchRequest.current = focusSearchRequest;
input.focus();
onSearchFocusHandled?.();
}, [focusSearchRequest, onSearchFocusHandled, posts]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +19 to +29
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
$$;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Rechecked against the latest remote head 87243268d09d5a47313979bc7370556e971b1b77 (remote documentation evidence commit was preserved).

  • Global search focus requests are consumed only for a newer request, so a remounted board does not steal focus from the customer’s next action.
  • Customer master, calendar, and Ask navigation use the common destination transition, which also closes the mobile drawer.
  • Frontend: 169 tests passed; lint, production build, and Storybook build passed.
  • Backend: 786 passed, 16 skipped, 4 warnings with the repository’s documented dev/backend extras.

Hosted checks are still queued and there is no formal approval yet, so this PR is not merge-ready.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment thread frontend/src/App.tsx
Comment on lines +3667 to +3672
if (focusSearchRequest <= lastFocusedSearchRequest.current) return;
const input = searchInputRef.current;
if (!input) return;
lastFocusedSearchRequest.current = focusSearchRequest;
input.focus();
onSearchFocusHandled?.();

@devin-ai-integration devin-ai-integration Bot Aug 21, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@seonghobae
seonghobae merged commit 0e63ba0 into feat/lineage-dag-regression Aug 21, 2026
3 of 4 checks passed
seonghobae added a commit that referenced this pull request Aug 21, 2026
* 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, "&times;") 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>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment thread lineageweave/ontology.py
return {}
fields = {"ontology_iri": str(subject)}
label = ONTOLOGY.value(subject, RDFS.label)
label = ONTOLOGY.value(subject, RDFS.label) or ONTOLOGY.value(subject, SKOS.prefLabel)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 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.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Revalidated the remote branch tip 66a41597d6aea74db27ffa34d001fe1801ebc765, which is a descendant of the PR API-reported head 819ef876270212305c89743e5443b3ce0b871e66 and includes the subsequent documentation commits.

  • Frontend lint passed.
  • Frontend: 19 files, 174 tests passed.
  • Production build passed.
  • Storybook build passed; only the existing large-chunk advisory was emitted.
  • Backend: 786 passed, 16 skipped, 4 warnings using the documented dev/backend extras.
  • git diff --check passed.

The PR API still reports 819ef876 while the branch ref is 66a41597; hosted checks are queued against the reported PR head. No formal approval is recorded, so this remains unmerged until GitHub’s exact-head/check state converges and the protected review gate is satisfied.

@seonghobae

Copy link
Copy Markdown
Contributor Author

Exact PR-head revalidation for remote-agent race at 819ef876270212305c89743e5443b3ce0b871e66:\n\n- This is the PR API head; local 66a4159 was not overwritten. The exact-head diff versus that local validation tip is limited to docs/product-technical-gap-baseline.md.\n- Backend: uv sync --extra dev --extra backend then uv run pytest -q -> 785 passed, 17 skipped, 4 warnings in 115.18s. Warnings are upstream Starlette deprecations and the existing short synthetic JWT fixture warning.\n- Frontend: pnpm install --frozen-lockfile; lint passed; Vitest 19 files/174 tests passed; production build passed; Storybook build passed (existing chunk-size advisory).\n- git diff --check passed and exact worktree is clean.\n\nThe PR remains unmerged because the exact head has queued hosted Checks and no formal approval was observed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant