Skip to content

feat(ask): show cited-post evidence in a Layer Popup - #420

Merged
seonghobae merged 11 commits into
worktree-ask-agent-image-citationfrom
worktree-ask-agent-layer-popup
Aug 23, 2026
Merged

feat(ask): show cited-post evidence in a Layer Popup#420
seonghobae merged 11 commits into
worktree-ask-agent-image-citationfrom
worktree-ask-agent-layer-popup

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Buyer-visible gap

Reading an Ask answer's evidence meant either scanning the inline fact list under each citation or leaving the answer entirely to open the full post detail popup. There was no focused way to inspect one citation's persisted evidence without losing the answer.

Change

  • New AskEvidenceLayerPopup (frontend/src/components/): focused modal evidence for one cited post using feat(ask): cite persisted image evidence for cited posts #419's cited_post_evidence and cited_post_images.
  • AskAgentPanel gets a View evidence next action per citation.
  • The layer now behaves as an actual modal: role="dialog", aria-modal, Escape/backdrop/close-button exit, initial focus inside, forward and reverse Tab containment, and focus restoration to the invoking control on ordinary close. Choosing Open post closes the layer before transitioning to the source-post workflow rather than stacking the two surfaces.
  • Evidence lists use citation-specific accessible names instead of duplicating the still-rendered inline Evidence facts name.
  • Blank or whitespace-only image captions fall back to Untitled image.
  • chatEvidenceKindLabel is shared through evidenceKindLabels.ts instead of drifting between App.tsx and the layer.
  • Storybook Evidence/AskEvidenceLayerPopup covers default, text-only, image-only, no-evidence, image-without-OCR-text, null-caption, and blank-caption states.
  • docs/doctoring/DESIGN_TOKEN_REFERENCES.md maps the keyboard behavior to the WAI-ARIA APG Dialog (Modal) Pattern and records the primary-source reference in APA 7 style.

Design authority

Fresh Figma metadata for file 1Su3lDRmiZdcUs47t1QwIX contains the Ask Agent answered frames (11:2 desktop, 11:3 mobile) and shared primary-control authority, but no dedicated evidence-layer frame. This PR therefore reuses the existing product tokens/control language and treats Storybook as the executable state catalog for this new layer; it does not claim pixel matching to a nonexistent Figma layer frame.

Stacking and gate ownership

Based on #419 because image evidence needs that checkpoint's cited_post_images contract. The current frontend production/Storybook build is still blocked by the two inherited App.tsx TypeScript errors at lines 106 and 4651. Their minimal repair is owned by #405, whose exact head b170eb4102484a104fb66462fa79a6ec129041d5 has repository-native Tests/Security/SAST/PROV-O success. Do not duplicate that unrelated repair into this layer PR; merge/restack the owning dependency through its own live gates first.

Exact-head verification

Exact head: 17c2f085d74c5ac22874878499d9051bf44f6752.

  • Frontend lint: success; only the two inherited unused-import warnings associated with feat: show persisted image-region locations (v2.12.8) #405's build repair remain.
  • Frontend tests: 151 passed; AskEvidenceLayerPopup.test.tsx has 8 passing tests, including blank-caption fallback, Tab/Shift+Tab containment, source-post transition ordering, and focus restoration.
  • Full backend/PostgreSQL suite: success on this exact head.
  • Production build: fails only on the inherited App.tsx(106,1) TS6192 and App.tsx(4651,112) TS2322 errors; Storybook build is consequently skipped, not treated as passing.
  • The two prior Devin inline findings are addressed on current code and resolved; no unresolved review thread is being treated as waived evidence.

No real records, identifiers, or provider credentials are included.


Open in Devin Review

Reading an Ask answer's evidence today means either scanning the inline
fact list or leaving the answer entirely to open the full post popup.
Add AskEvidenceLayerPopup (frontend/src/components/), a focused modal
layer -- opened via a new "View evidence" button per citation -- showing
that post's text evidence facts (checkpoint 3's cited_post_evidence) and
image evidence (checkpoint 3's cited_post_images) without navigating
away from the answer. Proper dialog semantics: role="dialog",
aria-modal, Escape-to-close, backdrop-click-to-close, initial focus on
the panel -- stricter accessibility than the existing PostDetailPopup,
which has none of these.

Extracted chatEvidenceKindLabel into evidenceKindLabels.ts so both
App.tsx and the new component share one label map instead of drifting.

Stacked on #419 (checkpoint 3): the popup's image-evidence section needs
that PR's cited_post_images field to be meaningful.

Part of the Ask Agent temporal/lineage/evidence goal (checkpoint 4 of 4).
@coderabbitai

coderabbitai Bot commented Aug 22, 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: d7260908-20a1-49a9-8abf-e5337bc4fc82

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[bot]

This comment was marked as resolved.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

2 similar comments
@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

@coderabbitai

coderabbitai Bot commented Aug 22, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


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.

…rsistence

The pre-login screen rendered AdminPanel with a possibly-undefined
accessToken (a TS6192/TS2322 build break) and never used the persisted
return-URL helpers on the login redirect. Same fix as LineageWeave#456
on main, applied here since this stack predates that fix.

@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 2 new potential issues.

Open in Devin Review

Comment thread frontend/src/App.tsx
Comment thread frontend/src/App.tsx
@seonghobae
seonghobae merged commit c7f4d6c into worktree-ask-agent-image-citation Aug 23, 2026
4 checks passed
@seonghobae

Copy link
Copy Markdown
Contributor Author

Reviewed both current info threads at exact head eb77477948aca956b69683b1f961bd22563fb5b6. The evidence-layer stale-id path is unreachable while the modal focus trap/backdrop is active, so no speculative state effect was added. The login change is the shared OIDC root fix, not an accidental feature change. @opencode-agent please perform an independent exact-head review.

seonghobae added a commit that referenced this pull request Aug 24, 2026
* feat(ask): cite persisted image evidence for cited posts

An Ask answer citing a post whose evidence actually came from an
embedded picture (a screenshot, a diagram) read as an unmarked text
claim -- no way to tell the citation was image-sourced. Raw image bytes
are never sent to the client anywhere in this codebase (only persisted
OCR/caption/tags -- see lineageweave/image_content.py); this reuses that
same never-raw-bytes description GET /api/posts/{id}/content already
renders, scoped to already-cited posts.

Backend: cited_post_images (backend/app/post_chat_ingestion.py) reads
post_content_image/post_content_image_tag for the cited post ids, no
extra ABAC check needed (cited_post_ids only ever come from
gather_global_chat_sources's already-authorized source set, same trust
boundary cited_post_evidence/cited_post_summaries rely on). Wired into
POST /api/ask as a new cited_post_images response field.

Frontend: AskAgentPanel renders an "Image evidence" line under a cited
post when present, with the persisted caption and OCR text. Adds the ko
/ zh / ja / vi translations for the two new strings.

Part of the Ask Agent temporal/lineage/evidence goal (checkpoint 3 of 4).

* feat(ask): show cited-post evidence in a Layer Popup (#420)

* feat(ask): show cited-post evidence in a Layer Popup

Reading an Ask answer's evidence today means either scanning the inline
fact list or leaving the answer entirely to open the full post popup.
Add AskEvidenceLayerPopup (frontend/src/components/), a focused modal
layer -- opened via a new "View evidence" button per citation -- showing
that post's text evidence facts (checkpoint 3's cited_post_evidence) and
image evidence (checkpoint 3's cited_post_images) without navigating
away from the answer. Proper dialog semantics: role="dialog",
aria-modal, Escape-to-close, backdrop-click-to-close, initial focus on
the panel -- stricter accessibility than the existing PostDetailPopup,
which has none of these.

Extracted chatEvidenceKindLabel into evidenceKindLabels.ts so both
App.tsx and the new component share one label map instead of drifting.

Stacked on #419 (checkpoint 3): the popup's image-evidence section needs
that PR's cited_post_images field to be meaningful.

Part of the Ask Agent temporal/lineage/evidence goal (checkpoint 4 of 4).

* test(ask): cover evidence dialog edge cases

* fix(ask): contain evidence dialog focus

* docs(storybook): cover blank evidence caption

* docs(ask): trace modal accessibility standard

* docs(storybook): inventory Ask evidence layer

* docs(changelog): record Ask evidence layer

* fix(changelog): restore historical entries

* test(ask): cover modal exit focus and source transition

* fix(ask): restore focus when evidence modal exits

* fix(frontend): drop stray pre-login AdminPanel, restore return-URL persistence

The pre-login screen rendered AdminPanel with a possibly-undefined
accessToken (a TS6192/TS2322 build break) and never used the persisted
return-URL helpers on the login redirect. Same fix as LineageWeave#456
on main, applied here since this stack predates that fix.

* fix(ask): fall back to Untitled image on blank caption in AskAgentPanel

image.caption ?? t("Untitled image") only substitutes for null/undefined,
so a persisted empty-string caption rendered a blank label ("Image
evidence:  — ..."). Match the blank-aware fallback already used in
AskEvidenceLayerPopup.tsx (image.caption?.trim() ? image.caption : ...)
so the same evidence renders consistently in both surfaces.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B5M79L945DMyMs3sg5yJ14

* fix: hide empty image evidence citations

* fix(frontend): render cited image tags

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
seonghobae added a commit that referenced this pull request Aug 24, 2026
)

* test(e2e): add a Playwright harness for the Ask Agent capabilities

No Playwright config existed despite the package already being a
devDependency. Add playwright.config.ts (points at the running
docker-compose stack, not a Playwright-managed dev server -- the app
needs Postgres/Keycloak/Valkey/orchestrator alongside it), a real
Keycloak-login helper (drives the actual OIDC redirect form with the
synthetic demo.analyst credentials, not a token injected into storage),
a validated smoke spec, and ask-agent.spec.ts covering all four Ask
Agent capabilities (relative-time retrieval #415, multi-lineage graphs
#418, image citation #419, Layer Popup #420).

The login flow is verified passing against a live stack right now.
ask-agent.spec.ts needs #415/#418/#419/#420 merged and the images
rebuilt from main before it can pass -- verified during development
that the currently-running ad-hoc stack is built from an unrelated,
more advanced branch (its own conversation-history UI), not main, so
it cannot validate this spec; that requires a proper CI/deployment
rebuild, out of this checkpoint's scope.

Part of the Ask Agent temporal/lineage/evidence goal (checkpoint 5 of
6 -- e2e harness).

* fix(frontend): repair the inherited login/admin-panel build break

Two TypeScript build errors on main (blocking every open PR's
"Frontend lint, test, build" check, including this repo's own review
bot's ability to approve them):

- App.tsx imported rememberOidcReturnUrl/returnUrlFromLocation from
  oidcReturnUrl.ts but never called them -- the login button built its
  own unsanitized returnUrl inline instead of using the safe helper
  (oidcReturnUrl.ts's isSafeReturnUrl guard against an open-redirect-
  shaped value) or persisting it as the sessionStorage/localStorage
  fallback restoreOidcReturnUrl (already wired up on the callback side
  in main.tsx) reads when the OIDC state round-trip drops it.
- The unauthenticated login screen unconditionally rendered
  <AdminPanel accessToken={accessToken} /> when destination === "admin"
  -- accessToken is string | undefined here (always undefined while
  unauthenticated), a real type error, and the render was unreachable
  through normal navigation (destination only changes via the
  authenticated nav) -- dead code, removed.

uv run --frozen python -m pytest -q: 753 passed, 17 skipped.
pnpm run test: 140 passed. pnpm run lint / build: clean.

* test(frontend): keep Playwright specs out of Vitest

* fix(e2e): stop Ask Agent lineage/image tests silently skipping their assertions

The git-branch-lineage and image-citation Ask Agent tests wrapped their
only real assertions in an `if (count > 0)` guard, so a run where the
LLM's answer happened not to produce that citation shape would report
PASS without exercising the behavior the test claims to cover. Assert
the precondition itself so the test fails loudly instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B5M79L945DMyMs3sg5yJ14

* fix(e2e): stabilize Ask Agent locale and multi-match checks

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
seonghobae added a commit that referenced this pull request Aug 24, 2026
)

* docs: record ADRs for the Ask Agent temporal/lineage/evidence goal

Four new ADRs, one per checkpoint of the Ask Agent temporal/lineage/
evidence goal:

- 0119: Korean relative-time expression resolution (#415)
- 0120: multi-thread Event Lineage graphs in Ask answers (#418)
- 0121: image citation without a new image-serving surface (#419)
- 0122: the evidence Layer Popup (#420)

Update CHANGELOG.md's Unreleased section and add an "Ask Agent Gaps"
section to docs/product-technical-gap-baseline.md marking all four
gaps (plus e2e coverage, #421) resolved, following that file's
existing "(Resolved)" convention.

Part of the Ask Agent temporal/lineage/evidence goal (checkpoint 6 of
6 -- documentation).

* docs: renumber Ask Agent ADRs 0119-0122 to 0150-0153

Cross-session coordination surfaced a widespread ADR-numbering
collision: at least ten numbers between 0119 and 0143 are
independently claimed by concurrent unmerged branches across other
sessions (0127/0128/0129/0131/0132 each claimed 2-4x, per
`git log --all --diff-filter=A -- docs/adr`). This PR's own
0119-0122 was a three-way collision (also claimed by the TEPP
topic-lineage PR and a quantity-superscript PR). Since this PR only
holds 4 ADRs against another's 14 (0119-0132), renumbering here is
the smaller diff. Moved clear of every number seen across all
branches (highest observed: 0143), leaving buffer room.

No content changes -- only the ADR number in each file's title,
their mutual cross-references, and every CHANGELOG.md /
gap-baseline.md citation of the old numbers.

* docs: refresh product technical gap baseline

* docs: record armed acceptance queue

* fix(frontend): repair the inherited login/admin-panel build break

Two TypeScript build errors on main (blocking every open PR's
"Frontend lint, test, build" check, including this repo's own review
bot's ability to approve them):

- App.tsx imported rememberOidcReturnUrl/returnUrlFromLocation from
  oidcReturnUrl.ts but never called them -- the login button built its
  own unsanitized returnUrl inline instead of using the safe helper
  (oidcReturnUrl.ts's isSafeReturnUrl guard against an open-redirect-
  shaped value) or persisting it as the sessionStorage/localStorage
  fallback restoreOidcReturnUrl (already wired up on the callback side
  in main.tsx) reads when the OIDC state round-trip drops it.
- The unauthenticated login screen unconditionally rendered
  <AdminPanel accessToken={accessToken} /> when destination === "admin"
  -- accessToken is string | undefined here (always undefined while
  unauthenticated), a real type error, and the render was unreachable
  through normal navigation (destination only changes via the
  authenticated nav) -- dead code, removed.

uv run --frozen python -m pytest -q: 753 passed, 17 skipped.
pnpm run test: 140 passed. pnpm run lint / build: clean.

---------

Co-authored-by: seonghobae <seonghobae@users.noreply.github.com>
seonghobae added a commit that referenced this pull request Aug 24, 2026
#420 (focused citation evidence Layer Popup, ADR 0153) is referenced in
prose but was absent from the stack table because it has already
merged; mark it explicitly so the table and prose agree.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant