Skip to content

feat(web-ui): Glitch Capture REQ detail view and sidebar entry point (#569)#578

Merged
frankbria merged 5 commits intomainfrom
feat/569-glitch-capture-req-detail
Apr 12, 2026
Merged

feat(web-ui): Glitch Capture REQ detail view and sidebar entry point (#569)#578
frankbria merged 5 commits intomainfrom
feat/569-glitch-capture-req-detail

Conversation

@frankbria
Copy link
Copy Markdown
Owner

@frankbria frankbria commented Apr 12, 2026

Summary

Closes #569

  • Backend: Exposes scope field in RequirementResponse via new ScopeOut Pydantic model, populated from the RequirementScope dataclass in _req_to_response()
  • Types: Adds ProofScope interface and scope: ProofScope | null field to ProofRequirement
  • REQ detail page (/proof/[req_id]):
    • Description rendered with ReactMarkdown (prose classes)
    • "Where found" metadata row from req.scope (comma-joined non-empty scope arrays)
    • Source, source_issue, and waiver expiry shown in metadata strip
    • Gate Obligations table gets a "Latest Run" column — status derives from the most-recent gate run evidence (latestRunByGate map), not stored ob.status
    • Evidence empty state replaced with styled block + "Run Gates →" CTA linking to /review
  • Sidebar: "Capture Glitch" button below nav items opens CaptureGlitchModal (from [Phase 3.5C] Glitch Capture: entry point and capture form #568), navigates to the new REQ on success

Test plan

  • npm test — 728 tests pass (28 new tests added across 3 files)
  • npm run build — TypeScript and build clean
  • uv run pytest tests/ui/test_proof_v2.py — 47 backend tests pass
  • uv run ruff check . — no issues
  • REQ detail page shows markdown description, "Where found" from scope, obligations with Latest Run column
  • Obligation status reflects most recent gate run result
  • Sidebar has Capture Glitch entry that opens the slide-over form

Summary by CodeRabbit

  • New Features

    • Markdown-rendered requirement descriptions
    • "Where found" scope display (routes, components, APIs, files, tags)
    • "Latest Run" column in obligations with clickable run IDs
    • "Capture Glitch" sidebar button and modal flow
  • Improvements

    • Obligation status reflects latest run evidence per gate
    • Enhanced empty-evidence card with "Run Gates" CTA linking to review
    • Minor UI metadata/label refinements
  • Tests

    • Expanded tests and mocks for markdown, scope, obligations, and capture flow
  • Documentation

    • Roadmap and phase docs updated to mark Glitch Capture UI complete

…569)

- Backend: expose scope field in RequirementResponse via new ScopeOut model
  populated from RequirementScope dataclass in _req_to_response()
- Types: add ProofScope interface and scope field to ProofRequirement
- REQ detail page (/proof/[req_id]):
  - Render description with ReactMarkdown (prose prose-sm classes)
  - Show 'Where found' from req.scope (comma-joined non-empty scope arrays)
  - Show 'source' and 'source_issue' in metadata row
  - Obligations table: add 'Latest Run' column deriving status from
    most-recent gate run evidence (latestRunByGate map)
  - Evidence empty state: replace plain text with styled CTA linking to /review
- Sidebar: add 'Capture Glitch' button that opens CaptureGlitchModal
  (implemented in #568) and navigates to new REQ on success
- Tests: full coverage for all new features across 3 test files
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds serialized requirement scope to the backend API and types, renders requirement descriptions as Markdown, shows scope on the proof detail page, derives obligation status from latest run evidence, and adds a "Capture Glitch" sidebar entry with modal and tests.

Changes

Cohort / File(s) Summary
Backend Scope Serialization
codeframe/ui/routers/proof_v2.py
Add ScopeOut Pydantic model; extend RequirementResponse with optional scope; populate scope in _req_to_response.
Frontend Types
web-ui/src/types/index.ts
Add ProofScope interface; add `scope: ProofScope
REQ Detail Page UI
web-ui/src/app/proof/[req_id]/page.tsx
Render req.description with ReactMarkdown; show conditional "Where found" concatenating req.scope arrays; compute per-gate latestRunByGate; add "Latest Run" column and derive obligation status from latest evidence; replace empty evidence with CTA linking to /review.
Sidebar + Modal
web-ui/src/components/layout/AppSidebar.tsx
Add Capture Glitch button with Add01Icon; manage showCaptureModal state; render CaptureGlitchModal when open; navigate to /proof/${req.id} on successful capture.
Tests & Mocks
web-ui/__mocks__/@hugeicons/react.js, web-ui/__tests__/app/proof/req_id/page.test.tsx, web-ui/__tests__/components/layout/AppSidebar.test.tsx, web-ui/src/__tests__/components/proof/ProofDetailPage.test.tsx
Add Add01Icon mock; extend test mocks with getRunDetail and SWR evidence handling; mock react-markdown; add tests for markdown rendering, scope-dependent "Where found", latest-run obligation behavior, evidence empty-state CTA, and sidebar Capture Glitch visibility.
Docs / Roadmap
CLAUDE.md, docs/PHASE_3_UI_ARCHITECTURE.md, docs/PRODUCT_ROADMAP.md
Mark Glitch Capture UI items complete; document PROOF9 changes (scope, markdown, obligations latest-run, sidebar entry).

Sequence Diagram(s)

sequenceDiagram
  participant User as Client (browser)
  participant UI as Frontend (Next.js)
  participant API as Backend API
  participant DB as Database

  rect rgba(0,128,0,0.5)
    User->>UI: Click "Capture Glitch" (sidebar)
    UI->>UI: Open CaptureGlitchModal
    User->>UI: Submit capture (description, scope, obligations)
    UI->>API: POST /api/proof (capture payload)
    API->>DB: Persist requirement + scope
    DB-->>API: Stored requirement (id)
    API-->>UI: 201 Created (requirement id)
    UI->>UI: Close modal, navigate to /proof/{id}
    UI->>API: GET /api/proof/{id} (requirement detail)
    API->>DB: Fetch requirement + runs/evidence
    DB-->>API: Requirement + evidence
    API-->>UI: RequirementResponse (includes scope)
    UI->>User: Render detail page (Markdown, Where found, obligations, latest runs)
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 I hopped to find where scopes abide,
Markdown fur and latest runs beside,
A sidebar button, a modal bright,
Capture a glitch, then watch its light,
🥕 Hop, proof made whole — what a ride!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely captures the main change: adding a glitch capture REQ detail view and sidebar entry point, matching the primary deliverables and issue #569.
Linked Issues check ✅ Passed All coding requirements from issue #569 are met: REQ detail page with markdown description, scope-derived 'Where found', obligations table with Latest Run column, evidence history with empty state CTA, and sidebar Capture Glitch entry point.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #569 objectives: backend scope exposure, frontend types, REQ detail page enhancements, sidebar button, and test/documentation updates supporting these features.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/569-glitch-capture-req-detail

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

@claude
Copy link
Copy Markdown

claude bot commented Apr 12, 2026

Review: Phase 3.5C — Glitch Capture REQ Detail & Sidebar Entry Point

Good implementation overall — this cleanly closes Phase 3.5C. The scope field flows end-to-end (backend → types → UI), the `latestRunByGate` useMemo correctly sources live status from evidence rather than stale obligation state, and the 28-test addition is well-structured with clear describe blocks. A few things worth addressing:


1. @tailwindcss/typography dependency for prose classes

`page.tsx` wraps the description in:
```tsx

{req.description}
\`\`\`

The `prose` and `prose-sm` classes come from the `@tailwindcss/typography` plugin. If it isn't already in `web-ui/tailwind.config.*`, these classes silently have no effect and the markdown output will be unstyled. Worth confirming with `grep -r '@tailwindcss/typography' web-ui/` and adding to both `package.json` and the tailwind config if missing.


2. Accessibility — sidebar icon-only button on small viewports

`AppSidebar.tsx`:
```tsx
<button type="button" onClick={() => setShowCaptureModal(true)} ...>

Capture Glitch

```

Below the `lg` breakpoint the label is hidden and only the icon is visible. Without an `aria-label`, screen readers have nothing to announce. Add `aria-label="Capture Glitch"` to the `` element.


3. IIFE in JSX is unconventional — prefer a variable

`page.tsx` uses an immediately-invoked function expression inline:
```tsx
{req.scope && (() => {
const parts = [...].filter(Boolean);
return parts.length > 0 ? (...) : null;
})()}
```

This works but reads awkwardly. A named variable above the return is clearer:
```tsx
const scopeParts = req.scope
? [...req.scope.routes, ...req.scope.components, ...req.scope.apis,
...req.scope.files, ...req.scope.tags].filter(Boolean)
: [];
// ...then in JSX:
{scopeParts.length > 0 && (

Where found: {scopeParts.join(', ')}
)} \`\`\`

Or a `useMemo` if performance is ever a concern. Either way, the IIFE pattern is a minor readability hit worth cleaning up.


4. Timestamp comparison relies on ISO 8601 lexicographic ordering (fine, but implicit)

```tsx
if (!existing || ev.timestamp > existing.timestamp) {
```

String comparison works correctly for ISO 8601 UTC timestamps — this is valid. A one-line comment like `// ISO 8601 strings sort lexicographically` would make the intent clear to future readers and prevent a well-intentioned "fix" that introduces a Date parse.


5. Backend — ScopeOut direct field access is safe but fragile to schema drift

```python
scope=ScopeOut(
routes=req.scope.routes,
components=req.scope.components,
...
) if req.scope else None,
```

If `RequirementScope` ever gains a new field (or if any field is unexpectedly `None` rather than an empty list), this silently drops or fails. Consider using `model_validate(vars(req.scope))` / `ScopeOut(**asdict(req.scope))` so the mapping stays in sync automatically and Pydantic validates field types. Not a blocker, but the current form will require a manual update here every time `RequirementScope` changes.


What's solid

  • `latestRunByGate` useMemo dependency array and guard (`!Array.isArray(evidence)`) are correct.
  • ReactMarkdown default behavior does not render raw HTML — no XSS concern.
  • `{showCaptureModal && workspacePath && <CaptureGlitchModal ...>}` correctly narrows the type for TypeScript even though `workspacePath` is always set when the component renders.
  • `setShowCaptureModal(false)` before `router.push()` in `onSuccess` is the right order.
  • Mocking `CaptureGlitchModal` in the sidebar test avoids Radix UI portal issues in jsdom — correct approach.
  • Test for the "no workspace, no button" branch is a nice edge case to have.

Items 1 and 2 are worth fixing before merge; 3–5 are lower priority but worth noting.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
codeframe/ui/routers/proof_v2.py (1)

106-113: Consider Field(default_factory=list) for ScopeOut arrays for Pydantic best practice.

While the current code passes Ruff checks in this repository's configuration, using Field(default_factory=list) is the recommended Pydantic v2 pattern for mutable defaults and avoids potential linting issues if Ruff rules are later tightened. Field is already imported, so the change is straightforward.

♻️ Suggested change
 class ScopeOut(BaseModel):
     """Serialized requirement scope."""
 
-    routes: list[str] = []
-    components: list[str] = []
-    apis: list[str] = []
-    files: list[str] = []
-    tags: list[str] = []
+    routes: list[str] = Field(default_factory=list)
+    components: list[str] = Field(default_factory=list)
+    apis: list[str] = Field(default_factory=list)
+    files: list[str] = Field(default_factory=list)
+    tags: list[str] = Field(default_factory=list)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@codeframe/ui/routers/proof_v2.py` around lines 106 - 113, The ScopeOut model
uses mutable default lists; change each field declaration in class ScopeOut
(routes, components, apis, files, tags) to use Field(default_factory=list)
instead of literal [] so Pydantic v2 handles mutable defaults correctly—update
the field definitions in the ScopeOut class (which inherits BaseModel) to call
Field(default_factory=list) for each list-typed attribute.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web-ui/src/app/proof/`[req_id]/page.tsx:
- Around line 315-320: The Latest Run cell currently renders latestEv.run_id as
plain text; make it actionable by converting it into a link or button that
navigates to the run details page (use the same route used by your run
detail/history view). Update the JSX where latestEv is rendered (the <td>
showing latestEv.run_id) to wrap the id in a Link or clickable element and wire
its onClick or href to the run detail route using latestEv.run_id (and preserve
the satisfied coloring logic: className={latestEv.satisfied ? 'text-green-600' :
'text-red-600'}). Ensure accessibility (aria-label) and that navigation uses the
app's client-side routing so the drill-down to the run history/detail works from
this cell.

In `@web-ui/src/components/layout/AppSidebar.tsx`:
- Around line 147-154: The collapsed "Capture Glitch" button in AppSidebar.tsx
lacks an accessible name; update the button element (the one that calls
setShowCaptureModal(true) and renders Add01Icon) to include an accessible label
such as aria-label="Capture Glitch" or aria-labelledby pointing to a visually
hidden text node so screen readers can discover it; ensure the label text
matches the visible "Capture Glitch" string and keep the existing hidden
lg:inline span for visual behavior.

---

Nitpick comments:
In `@codeframe/ui/routers/proof_v2.py`:
- Around line 106-113: The ScopeOut model uses mutable default lists; change
each field declaration in class ScopeOut (routes, components, apis, files, tags)
to use Field(default_factory=list) instead of literal [] so Pydantic v2 handles
mutable defaults correctly—update the field definitions in the ScopeOut class
(which inherits BaseModel) to call Field(default_factory=list) for each
list-typed attribute.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2311a733-fc90-4bdb-8608-e0b56951a556

📥 Commits

Reviewing files that changed from the base of the PR and between 24b59d6 and 04146ab.

📒 Files selected for processing (8)
  • codeframe/ui/routers/proof_v2.py
  • web-ui/__mocks__/@hugeicons/react.js
  • web-ui/__tests__/app/proof/req_id/page.test.tsx
  • web-ui/__tests__/components/layout/AppSidebar.test.tsx
  • web-ui/src/__tests__/components/proof/ProofDetailPage.test.tsx
  • web-ui/src/app/proof/[req_id]/page.tsx
  • web-ui/src/components/layout/AppSidebar.tsx
  • web-ui/src/types/index.ts

…#578)

- Make obligations Latest Run run_id a clickable button that sets the
  evidence history search filter to show that run's evidence
- Add aria-label and aria-hidden to Capture Glitch sidebar button for
  accessibility in collapsed sidebar (below lg breakpoint)
- Use Field(default_factory=list) for ScopeOut mutable defaults
  per Pydantic v2 best practice
@claude
Copy link
Copy Markdown

claude bot commented Apr 12, 2026

Follow-up Review

Checking back after the latest push.

Retracting a previous false positive: My concern about @tailwindcss/typography being absent was wrong — the plugin is already imported in tailwind.config.ts (line 2) and listed in package.json. The prose/prose-sm classes will work as intended.

Addressed from my prior review:

  • aria-label="Capture Glitch" is now on the sidebar button. Screen readers on small viewports will announce it correctly. ✓
  • Field(default_factory=list) is used for all ScopeOut list fields. ✓
  • The "Latest Run" cell is a clickable <button> that calls updateSearch(latestEv.run_id) — functional as a filter entry point. ✓

Still outstanding (lower priority, not blockers):

  1. IIFE in JSX (page.tsx, the req.scope && block) — the pattern works but remains unconventional. A named scopeParts variable computed before the return would be cleaner. No functional issue.

  2. Timestamp comparisonev.timestamp > existing.timestamp is correct for ISO 8601, but a short inline comment would prevent a future "fix" that introduces an unnecessary Date parse.

  3. Backend schema drift_req_to_response() still accesses req.scope.routes, req.scope.components, etc. directly. If RequirementScope ever changes shape, this will silently diverge. ScopeOut(**asdict(req.scope)) or a model_validate call would stay in sync automatically.

The two items I flagged as "worth fixing before merge" (typography plugin and aria-label) are both resolved. The remaining items are style/robustness preferences. No blockers.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web-ui/src/app/proof/`[req_id]/page.tsx:
- Around line 317-320: The "Latest Run" button only calls
updateSearch(latestEv.run_id), which can leave existing gate/result filters
active and hide the run; change the click handler to also clear incompatible
filters by resetting the gate and result filter state before persisting the run
filter — e.g., call the existing setters (or a single search-update helper) to
set gateFilter and resultFilter to their default/empty values and then call
updateSearch(latestEv.run_id) (or extend updateSearch to accept a full filter
object) so that drilling into a run always clears gate/result filters and
reliably shows the run.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9571fbcc-9293-4ebc-9c08-ccda01c616df

📥 Commits

Reviewing files that changed from the base of the PR and between 04146ab and 989cfe0.

📒 Files selected for processing (3)
  • codeframe/ui/routers/proof_v2.py
  • web-ui/src/app/proof/[req_id]/page.tsx
  • web-ui/src/components/layout/AppSidebar.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • codeframe/ui/routers/proof_v2.py

@claude
Copy link
Copy Markdown

claude bot commented Apr 12, 2026

Follow-up Review (latest commit: 94d1702e)

New commit reviewed: fix(web-ui): clear gate/result filters when drilling into a run from obligations table

The focusRun function added in page.tsx is correct:

function focusRun(runId: string) {
  setFilterGate('');
  setFilterResult('');
  setSearch(runId);
  saveSessionFilters(reqId, '', '', runId);
}

Clearing gate + result filters before setting the run ID search is exactly right — otherwise a user clicking a run from the obligations table might get an empty evidence list if those filters excluded the run's entries. The saveSessionFilters call keeps the filter state durable across navigation. No issues here.


Status of outstanding items from previous reviews:

The 3 lower-priority items remain unchanged:

  • IIFE in JSX (req.scope && (() => {...})()) — still present, still works, still a readability note
  • Timestamp comparison — still lacks the ISO 8601 comment, still functionally correct
  • Backend _req_to_response() direct field access — still present, no new schema drift introduced

None are blockers. The two items I originally flagged as must-fix-before-merge (typography plugin and aria-label) remain resolved.

Ready to merge. No new issues introduced by this commit.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web-ui/src/app/proof/`[req_id]/page.tsx:
- Around line 118-129: latestRunByGate currently compares ev.timestamp and
existing.timestamp as raw strings which can produce incorrect "latest" picks if
timestamps aren't lexically sortable; update the comparison in the useMemo so it
parses timestamps to a comparable numeric form (e.g., Date.parse or new
Date(...).getTime()) before comparing, and handle invalid/missing timestamps by
falling back to 0 or another safe sentinel; ensure you update references to
ev.timestamp and existing.timestamp in the map population logic (in the
latestRunByGate computation over evidence / ProofEvidence) so the comparison
uses the parsed numeric values.
- Around line 254-256: ReactMarkdown is rendering images from user-provided
req.description which can trigger remote fetches; prevent that by disabling
image/embed elements when rendering descriptions: update the ReactMarkdown usage
(the JSX that renders req.description) to supply a components prop that
overrides img/image/iframe (and other embed tags you deem risky) to render
nothing or a safe placeholder, and also enable HTML-skipping/disable raw HTML if
your ReactMarkdown version supports skipHtml or disallowedElements to avoid
embedded HTML; target the ReactMarkdown element that consumes req.description in
page.tsx to apply these changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a2df4f05-329e-4fcc-8304-3b6cdfafa2e7

📥 Commits

Reviewing files that changed from the base of the PR and between 989cfe0 and 94d1702.

📒 Files selected for processing (1)
  • web-ui/src/app/proof/[req_id]/page.tsx

- Use Date.parse() for timestamp comparison in latestRunByGate to handle
  varying ISO 8601 offset formats correctly
- Disable img element in ReactMarkdown to prevent remote resource fetches
  from user-authored requirement descriptions (security fix)
@claude
Copy link
Copy Markdown

claude bot commented Apr 12, 2026

Follow-up Review (3rd pass)

Reviewing the latest commit (86fa12a7).

Resolved since last review

Filter-clearing on Latest Run click — CodeRabbit raised that the previous version left gate/result filters active when clicking a run ID, which could hide the run. The new focusRun helper correctly clears both filterGate and filterResult before setting the search, fully addressing that concern. ✓

Timestamp comparison — now uses Date.parse(ev.timestamp) > Date.parse(existing.timestamp) instead of direct string comparison. Both are valid for ISO 8601; Date.parse is marginally more explicit about intent.


Still outstanding (style/robustness, not blockers)

  1. IIFE in JSX — the req.scope && (() => { ... })() pattern remains. A scopeParts variable before the return would be cleaner, but this does not affect correctness.

  2. Backend schema drift_req_to_response() still explicitly accesses each field of req.scope by name. Using ScopeOut(**asdict(req.scope)) would stay in sync automatically if RequirementScope gains new fields. Still not a blocker.


No blockers. All items flagged as "worth fixing before merge" in the initial review have been resolved. Ready to merge.

@claude
Copy link
Copy Markdown

claude bot commented Apr 12, 2026

Follow-up Review (4th pass — docs-only commit)

The latest commit updates only documentation: CLAUDE.md, docs/PHASE_3_UI_ARCHITECTURE.md, and docs/PRODUCT_ROADMAP.md. No functional code changes.

Docs accuracy check:

  • CLAUDE.md — Phase 3.5C marked complete, focus advanced to Phase 4A. Accurate.
  • PRODUCT_ROADMAP.md — Milestone C flipped from ❌ to ✅, issues [Phase 3.5C] Glitch Capture: entry point and capture form #568 and [Phase 3.5C] Glitch Capture: REQ detail view and sidebar entry point #569 cited, Phase 4A listed as current focus. Accurate and consistent with the shipped feature.
  • PHASE_3_UI_ARCHITECTURE.md — Component tree updated to reflect RequirementHeader, ObligationsTable with Latest Run column, EvidenceHistory with FilterBar, and WaiveDialog. Sidebar entry updated to include PROOF9 (item 7), Sessions (item 8), and the Capture Glitch action button. Matches the implementation.

No discrepancies between the doc updates and the code that shipped in earlier commits.


Status of all prior items:

Item Status
@tailwindcss/typography present ✅ (was never missing)
aria-label on sidebar button ✅ Fixed
Field(default_factory=list) on ScopeOut ✅ Fixed
Filter-clearing on Latest Run click (focusRun) ✅ Fixed
Timestamp comparison uses Date.parse ✅ Fixed
IIFE in JSX (req.scope && (() => {...})()) ⚠️ Still present — readability note only, not a blocker
Backend schema drift in _req_to_response ⚠️ Still present — robustness note only, not a blocker

Nothing new to flag. Ready to merge.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/PHASE_3_UI_ARCHITECTURE.md`:
- Line 137: Update the documentation entry that currently reads "PROOF9" to
match the implementation by changing the navigation label to "Proof"; the
implemented label is defined in AppSidebar.tsx as label: 'Proof', so replace the
"PROOF9" string in the docs with "Proof" to keep docs and code consistent.
- Around line 373-388: The docs claim named exports (RequirementHeader,
ObligationsTable, EvidenceHistory, GateEvidencePanel, WaiveDialog) exist for
/proof/[req_id], but the actual implementation uses inline JSX sections in
web-ui/src/app/proof/[req_id]/page.tsx (commented as {/* Header */}, {/*
Obligations */}, {/* Evidence history */} etc. Fix by either: 1) updating
PHASE_3_UI_ARCHITECTURE.md to describe the inline implementation and list the
documented sections as inline JSX blocks found in page.tsx, or 2) refactor
page.tsx by extracting the commented sections into discrete exported components
named RequirementHeader, ObligationsTable, EvidenceHistory, GateEvidencePanel,
and WaiveDialog, preserving existing props/hooks/state and replacing the inline
JSX with imports/usages so the documented component hierarchy matches the code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c73b78e2-b5c9-41b8-afba-84dec83bff44

📥 Commits

Reviewing files that changed from the base of the PR and between 86fa12a and 0c48d1c.

📒 Files selected for processing (3)
  • CLAUDE.md
  • docs/PHASE_3_UI_ARCHITECTURE.md
  • docs/PRODUCT_ROADMAP.md
✅ Files skipped from review due to trivial changes (2)
  • CLAUDE.md
  • docs/PRODUCT_ROADMAP.md

4. **Execution** (play/monitor icon) - only visible when runs are active
5. **Blockers** (alert icon) - badge count for open blockers
6. **Review** (git branch icon)
7. **PROOF9** (checkmark icon)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Correct the navigation label from "PROOF9" to "Proof".

The documentation claims the navigation item is labeled "PROOF9", but the actual implementation in AppSidebar.tsx uses "Proof" as the label (line 37: label: 'Proof'). Update the documentation to match the implemented label.

📝 Proposed fix
-7. **PROOF9** (checkmark icon)
+7. **Proof** (checkmark icon)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
7. **PROOF9** (checkmark icon)
7. **Proof** (checkmark icon)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/PHASE_3_UI_ARCHITECTURE.md` at line 137, Update the documentation entry
that currently reads "PROOF9" to match the implementation by changing the
navigation label to "Proof"; the implemented label is defined in AppSidebar.tsx
as label: 'Proof', so replace the "PROOF9" string in the docs with "Proof" to
keep docs and code consistent.

Comment on lines 373 to +388
ProofRequirementPage (/proof/[req_id])
├── RequirementDetail
│ ├── ObligationsList
│ └── EvidenceHistory
└── WaiveForm
├── RequirementHeader
│ ├── Title, severity badge, ProofStatusBadge
│ ├── MarkdownDescription (ReactMarkdown, images disallowed)
│ ├── MetadataRow (created_at, source, source_issue, created_by, waiver expiry)
│ └── ScopeChips (files, routes, components, APIs, tags from ProofScope)
├── ObligationsTable ← new (Phase 3.5C)
│ └── ObligationRow[] (gate name, Latest Run pass/fail badge, link to evidence)
│ └── Latest Run column: shows most-recent run result per gate
├── EvidenceHistory
│ ├── FilterBar (gate select, result select, search input, Reset Filters)
│ ├── EvidenceTable (sortable: gate, result, run_id, timestamp, artifact)
│ │ └── EvidenceRow[] (click run_id → focusRun filter)
│ └── EmptyState CTA: "Capture a Glitch" link when no evidence exists
├── GateEvidencePanel (loads artifact content for latest run)
└── WaiveDialog (modal, opens via Waive button in header)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Architectural mismatch: Documented components don't exist as discrete exports.

The documentation describes the /proof/[req_id] page as using named components (RequirementHeader, ObligationsTable, EvidenceHistory, GateEvidencePanel, WaiveDialog), but the actual implementation in web-ui/src/app/proof/[req_id]/page.tsx uses inline JSX sections (marked with comments like {/* Header */}, {/* Obligations */}, {/* Evidence history */}) without separate component exports.

While the described functionality is correctly implemented, developers looking for these named components will not find them in the codebase. Update the documentation to accurately reflect the inline implementation pattern or refactor the implementation to match the documented component hierarchy.

📝 Proposed documentation fix to match actual implementation
 ProofRequirementPage (/proof/[req_id])
-├── RequirementHeader
-│   ├── Title, severity badge, ProofStatusBadge
-│   ├── MarkdownDescription (ReactMarkdown, images disallowed)
-│   ├── MetadataRow (created_at, source, source_issue, created_by, waiver expiry)
-│   └── ScopeChips (files, routes, components, APIs, tags from ProofScope)
-├── ObligationsTable      ← new (Phase 3.5C)
-│   └── ObligationRow[]   (gate name, Latest Run pass/fail badge, link to evidence)
-│       └── Latest Run column: shows most-recent run result per gate
-├── EvidenceHistory
-│   ├── FilterBar (gate select, result select, search input, Reset Filters)
-│   ├── EvidenceTable (sortable: gate, result, run_id, timestamp, artifact)
-│   │   └── EvidenceRow[] (click run_id → focusRun filter)
-│   └── EmptyState CTA: "Capture a Glitch" link when no evidence exists
-├── GateEvidencePanel (loads artifact content for latest run)
-└── WaiveDialog (modal, opens via Waive button in header)
+├── Header section (inline JSX)
+│   ├── Title, severity badge, ProofStatusBadge
+│   ├── Description (ReactMarkdown, images disallowed)
+│   ├── Metadata row (created_at, source, source_issue, created_by, waiver expiry)
+│   └── Scope chips (files, routes, components, APIs, tags from ProofScope)
+├── Obligations section (inline JSX table)
+│   └── Obligation rows (gate name, status, Latest Run link)
+│       └── Latest Run column: clickable run_id that filters evidence history
+├── Evidence History section (inline JSX)
+│   ├── Filter controls (gate select, result select, search input, Reset Filters)
+│   ├── Evidence table (gate, result, run_id, timestamp, artifact)
+│   │   └── Evidence rows (click run_id → focusRun filter)
+│   └── Empty state with "Run Gates →" CTA linking to /review
+└── Waiver section (inline JSX with modal dialog)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ProofRequirementPage (/proof/[req_id])
├── RequirementDetail
│ ├── ObligationsList
│ └── EvidenceHistory
└── WaiveForm
├── RequirementHeader
│ ├── Title, severity badge, ProofStatusBadge
│ ├── MarkdownDescription (ReactMarkdown, images disallowed)
│ ├── MetadataRow (created_at, source, source_issue, created_by, waiver expiry)
│ └── ScopeChips (files, routes, components, APIs, tags from ProofScope)
├── ObligationsTable ← new (Phase 3.5C)
│ └── ObligationRow[] (gate name, Latest Run pass/fail badge, link to evidence)
│ └── Latest Run column: shows most-recent run result per gate
├── EvidenceHistory
│ ├── FilterBar (gate select, result select, search input, Reset Filters)
│ ├── EvidenceTable (sortable: gate, result, run_id, timestamp, artifact)
│ │ └── EvidenceRow[] (click run_id → focusRun filter)
│ └── EmptyState CTA: "Capture a Glitch" link when no evidence exists
├── GateEvidencePanel (loads artifact content for latest run)
└── WaiveDialog (modal, opens via Waive button in header)
ProofRequirementPage (/proof/[req_id])
├── Header section (inline JSX)
│ ├── Title, severity badge, ProofStatusBadge
│ ├── Description (ReactMarkdown, images disallowed)
│ ├── Metadata row (created_at, source, source_issue, created_by, waiver expiry)
│ └── Scope chips (files, routes, components, APIs, tags from ProofScope)
├── Obligations section (inline JSX table)
│ └── Obligation rows (gate name, status, Latest Run link)
│ └── Latest Run column: clickable run_id that filters evidence history
├── Evidence History section (inline JSX)
│ ├── Filter controls (gate select, result select, search input, Reset Filters)
│ ├── Evidence table (gate, result, run_id, timestamp, artifact)
│ │ └── Evidence rows (click run_id → focusRun filter)
│ └── Empty state with "Run Gates →" CTA linking to /review
└── Waiver section (inline JSX with modal dialog)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/PHASE_3_UI_ARCHITECTURE.md` around lines 373 - 388, The docs claim named
exports (RequirementHeader, ObligationsTable, EvidenceHistory,
GateEvidencePanel, WaiveDialog) exist for /proof/[req_id], but the actual
implementation uses inline JSX sections in
web-ui/src/app/proof/[req_id]/page.tsx (commented as {/* Header */}, {/*
Obligations */}, {/* Evidence history */} etc. Fix by either: 1) updating
PHASE_3_UI_ARCHITECTURE.md to describe the inline implementation and list the
documented sections as inline JSX blocks found in page.tsx, or 2) refactor
page.tsx by extracting the commented sections into discrete exported components
named RequirementHeader, ObligationsTable, EvidenceHistory, GateEvidencePanel,
and WaiveDialog, preserving existing props/hooks/state and replacing the inline
JSX with imports/usages so the documented component hierarchy matches the code.

@frankbria frankbria merged commit 6166e0f into main Apr 12, 2026
16 checks passed
@frankbria frankbria deleted the feat/569-glitch-capture-req-detail branch April 12, 2026 22:08
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.

[Phase 3.5C] Glitch Capture: REQ detail view and sidebar entry point

1 participant