diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index e65883463..f90cd32ce 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -23,4 +23,79 @@ - **Security & Compliance**: PII masking cannot break the system. Need SOC 2 and CSAP compliance alternatives to blind PII masking. - **LLM Orchestration**: Ensure ALL LLM calls route through `contextual-orchestrator` utilizing API keys (BYTEZ, NVIDIA, OPENROUTER, OPENAI) with auto model discovery and optimal reasoning effort allocation (Fugu/Conductor/TRINITY research). +## 4. 2026-08-23 Audit: Accessibility, i18n, and Release-Process Gaps + +A dedicated multi-agent audit (independently verified against live source and +cross-checked against the full PR history to rule out duplicates) found 14 +new, previously-untracked gaps. None of these overlap the sections above. + +### 4a. Accessibility (frontend) +- **Post detail popup has no dialog semantics on `main`** (true when this + audit ran): `PostDetailPopup` in `frontend/src/App.tsx` rendered a + backdrop/panel with no `role="dialog"`, `aria-modal`, `aria-labelledby`, + Escape-to-close, or focus trap/restore. **Already fixed, not yet on + `main`**: `docs/customer-master-scope-adr` (verified at commit + `7d6cab694d7d6998a2b5ecf8fb1ed2c704052411`) already has a complete + implementation -- `popupPanelRef`, `role="dialog"`/`aria-modal`, Tab-cycle + wraparound that filters hidden/`aria-hidden`/closed-`
` elements, + Escape-to-close, and focus-restore-on-unmount via effect cleanup. No new + PR needed here; this resolves once that branch reaches `main`. +- **Async error feedback isn't announced**: 17 of 19 `className="error"` + sites in `App.tsx` render as plain `

` with no `role="alert"`/`aria-live` + (Ask, Keymen extraction, lineage rebuild, Customer Master, Ask Agent, and + more). Fixed in the accessibility-sweep PR referenced below. +- **Two inputs have no accessible name**: the "Ask about this lineage" + question field and the new-ticket-title field use only a `placeholder`, + unlike the adjacent due-date field. Fixed in the same sweep. +- **AdminPanel save result isn't announced**: the save-success/error `` + in `AdminPanel.tsx` carries no `role`/`aria-live`. Fixed in the same sweep. +- **Event Lineage DAG node kind (root/branch/regular) is color-only**: no + textual indication in the `aria-label`, tooltip, or a legend; not fixed by + the existing DAG test/story coverage (that PR explicitly found no bug). + Needs a legend/label design decision, not yet fixed. +- **DAG keyboard focus ring is very weak**: `.lineage-dag-node:focus` strips + the native outline and replaces it with only a 1px stroke-width bump in the + same border color. Fixed in the accessibility-sweep PR. +- **Rendered post-body tables have no header semantics**: both the + structured-unit table renderer and the OCR-image-text table renderer in + `PostBody.tsx` emit only ``, no ``/``. Was + present in a prior merged PR (#303) but silently dropped by a later + whole-file rewrite (commit `ef6f5a5f`). Not yet re-fixed. + +### 4b. i18n +- **Unregistered aria-label key**: `tf("Affiliates of {name}")` (the + customer-entity-tree `aria-label` in `App.tsx`) has no entry in any of the + ko/zh/ja/vi locale blocks in `i18n.ts`, so it always renders in English + regardless of the active locale. Fixed in the accessibility-sweep PR. + +### 4c. Release-process / CHANGELOG hygiene +- **CHANGELOG.md stalled at `[2.12.6]`** while the tree already contains ~80 + additional ADRs and whole undocumented feature surfaces (Global Ask + evidence workspace, the buyer-facing global nav). No version header past + 2.12.6 exists anywhere in the file. Large, needs careful reconstruction; + logged here rather than attempted in this pass. +- **9 already-drafted `CHANGELOG.d/` fragments (2.12.7 through 2.21.1) were + never compiled** into `CHANGELOG.md` — the release text already exists, + the compile step was simply never run. Fixed in a dedicated compilation PR + (mechanical, low-risk since the prose already exists). +- **The `ef6f5a5f` squash-merge (PR #347) left at least one shipped feature + undocumented**: the durable post-content ingestion queue (ADR 0098) has no + CHANGELOG.md entry and no `CHANGELOG.d/` fragment, unlike its sibling + changes in the same commit. Logged, not yet fixed. +- **PR #460's own fix is missing from `CHANGELOG.md`'s `[Unreleased]` + section.** Will be added alongside the CHANGELOG.d compilation PR. +- **Version fields agree with CHANGELOG (2.12.6) only because both are + equally stalled**, not because the release process is healthy — real + merged work already sits past that version with no compiled release. + Same root cause as the two items above; resolved once a batch-release pass + runs. + +### 4d. Test coverage +- **Bookmark endpoints (`GET`/`POST /api/posts/{post_id}/bookmark`) have zero + HTTP-level test coverage.** The only existing tests exercise the lower-level + `_load_visible_post` helper directly, bypassing FastAPI entirely — the + route wiring, request validation, and the `post_bookmark` insert/delete SQL + introduced by a recent fix are unexercised. Needs a `TestClient`-level + test; not yet added. + *This document is continuously updated by the hourly automated agent loop.* diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx index 7462abd2c..9582ae69e 100644 --- a/frontend/src/App.test.tsx +++ b/frontend/src/App.test.tsx @@ -28,19 +28,25 @@ beforeEach(() => { afterEach(() => { vi.unstubAllGlobals(); + window.sessionStorage.clear(); + window.localStorage.clear(); }); describe("App, unauthenticated", () => { it("shows a login button that starts the real OIDC redirect", async () => { + window.history.replaceState({}, "", "/?post=abc#details"); render(); const button = screen.getByRole("button", { name: /log in/i }); await userEvent.click(button); expect(signinRedirect).toHaveBeenCalledTimes(1); expect(signinRedirect).toHaveBeenCalledWith( expect.objectContaining({ - state: expect.objectContaining({ returnUrl: expect.stringMatching(/^\//) }), + state: expect.objectContaining({ returnUrl: "/?post=abc#details" }), }), ); + // Persisted as a fallback in case the OIDC state round-trip is dropped + // (see oidcReturnUrl.ts's restoreOidcReturnUrl, consumed in main.tsx). + expect(window.sessionStorage.getItem("lineageweave.oidc.returnUrl")).toBe("/?post=abc#details"); }); }); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 6fba0dd41..1b5b351ab 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4610,7 +4610,8 @@ export default function App({ showLabPanels = false }: { showLabPanels?: boolean

- {destination === "admin" ? : null}