Skip to content

Align spec details view with enriched requirement metadata#433

Merged
nndn merged 2 commits into
mainfrom
spec-ui-outcome-alignment
Jul 3, 2026
Merged

Align spec details view with enriched requirement metadata#433
nndn merged 2 commits into
mainfrom
spec-ui-outcome-alignment

Conversation

@BrhKmr23

@BrhKmr23 BrhKmr23 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR updates the spec details page to better reflect the current specification shape returned by workflows.

What changed

  • surfaces requirement priority in the spec detail cards
  • adds a dedicated verification section for acceptance criteria
  • shows file impact with path, action, and purpose
  • preserves structured guardrail details including rationale and consequences
  • keeps streamed spec output formatting stable while lightly normalizing malformed bolded subheading markers for readability

##Screenshot
Screenshot 2026-06-26 at 8 03 28 PM

Why

The latest spec output includes richer requirement metadata and more outcome-oriented descriptions. This update makes the spec page reflect that structure more clearly and keeps important implementation and verification context visible during review.

Validation

  • tested locally on the spec page
  • verified enriched requirement fields render correctly
  • ran ESLint on the changed file

@BrhKmr23 BrhKmr23 requested a review from nndn June 26, 2026 15:01
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The spec page now normalizes priority, guardrails, acceptance criteria, and impacted-file purpose metadata from plan output, renders that metadata in plan cards, and formats streamed thinking content before it reaches the timeline.

Changes

Spec plan metadata and rendering

Layer / File(s) Summary
Plan item fields
app/(main)/task/[taskId]/spec/page.tsx
FileItem and PlanItem gain optional purpose, priority, guardrails, and acceptanceCriteria fields.
Plan normalization
app/(main)/task/[taskId]/spec/page.tsx
normalizePlanItem and specOutputToPlan map file purpose, priority, structured guardrails, and acceptance criteria from API output into PlanItem data.
Plan details UI
app/(main)/task/[taskId]/spec/page.tsx
PlanTabs renders requirement and priority chips, impacted files with purpose, verification content, and guardrail cards in the accordion body.
Stream markdown display
app/(main)/task/[taskId]/spec/page.tsx
Stream chunk content is formatted with formatSpecThinkingMarkdown before StreamTimeline renders the items.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • potpie-ai/potpie-ui#352: Touches the same spec regeneration and stream-state code path in app/(main)/task/[taskId]/spec/page.tsx.
  • potpie-ai/potpie-ui#363: Uses the same spec/plan metadata surface that this PR adds for export rendering.

Suggested reviewers

  • ASCE-D

Poem

A rabbit hopped through specs so bright,
With guardrails, chips, and text alight.
Acceptance carrots lined the way,
While streams of thinking danced all day.
Thump! The plan now feels just right. 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: updating the spec details view to reflect richer requirement metadata.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch spec-ui-outcome-alignment

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 left a comment

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.

🧹 Nitpick comments (4)
app/(main)/task/[taskId]/spec/page.tsx (4)

516-520: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the cn utility for the conditional priority-chip classes.

The priority chip concatenates priorityChipClass(...) into a template literal. Per the project convention, conditional class composition should go through cn. Note cn isn't currently imported in this file, so add it to the existing @/lib/utils import.

♻️ Proposed change
-                    {item.priority && (
-                      <span className={`inline-flex h-5 items-center rounded-full border px-2 text-[10px] font-medium leading-none capitalize ${priorityChipClass(item.priority)}`}>
+                    {item.priority && (
+                      <span className={cn("inline-flex h-5 items-center rounded-full border px-2 text-[10px] font-medium leading-none capitalize", priorityChipClass(item.priority))}>
                         {item.priority}
                       </span>
                     )}

And add cn to the import at Line 48:

-import { getStreamEventPayload, normalizeMarkdownForPreview } from "`@/lib/utils`";
+import { cn, getStreamEventPayload, normalizeMarkdownForPreview } from "`@/lib/utils`";
As per coding guidelines: "Use Tailwind CSS for styling and the `cn` utility for conditional classes".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/`(main)/task/[taskId]/spec/page.tsx around lines 516 - 520, The priority
chip in the task spec page is building classes with a template literal instead
of the project’s `cn` utility. Update the conditional priority-chip rendering to
compose the static classes with `priorityChipClass(item.priority)` through `cn`,
and add `cn` to the existing `@/lib/utils` import in this component so the class
concatenation follows the shared styling convention.

Source: Coding guidelines


115-137: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the guardrail/acceptance-criteria normalization into shared helpers.

The guardrail mapping (Lines 122-136) and acceptance-criteria mapping (Line 137) are duplicated almost verbatim in specOutputToPlan (Lines 186-204). The same typeof c === "string" ? c : (c?.text ?? JSON.stringify(c)) pattern also recurs in FunctionalRequirementCard (Line 297). Centralizing avoids the two copies drifting apart as the API shape evolves.

♻️ Suggested shared helpers
function normalizeGuardrails(raw: any): GuardrailItem[] | undefined {
  const list = (Array.isArray(raw) ? raw : [])
    .map((g: any) => {
      if (typeof g === "string") return { statement: g };
      const statement = g?.statement ?? g?.text;
      if (!statement) return null;
      return {
        type: typeof g?.type === "string" ? g.type : undefined,
        statement: String(statement),
        rationale: typeof g?.rationale === "string" ? g.rationale : undefined,
        consequences: Array.isArray(g?.consequences) ? g.consequences.map((c: any) => String(c)) : undefined,
      };
    })
    .filter((g): g is GuardrailItem => g !== null);
  return list.length > 0 ? list : undefined;
}

function normalizeAcceptanceCriteria(raw: any): string[] {
  return (Array.isArray(raw) ? raw : []).map((c: any) =>
    typeof c === "string" ? c : (c?.text ?? JSON.stringify(c))
  );
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/`(main)/task/[taskId]/spec/page.tsx around lines 115 - 137, The guardrail
and acceptance-criteria normalization logic is duplicated in multiple places, so
extract it into shared helpers and reuse them. Move the mapping/filtering
currently in the spec page’s normalization block into functions like
normalizeGuardrails and normalizeAcceptanceCriteria, then update
specOutputToPlan and FunctionalRequirementCard to call those helpers instead of
inlining the same conversions. Keep the behavior identical, including string
handling and fallback serialization, so the API-shape logic stays consistent in
one place.

1298-1306: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Memo reformats the full (growing) chunk content on every stream update.

Chunk content is appended in place during streaming (consecutive chunks are merged into the last item at Line 1010), so this memo re-runs formatSpecThinkingMarkdown's regex passes over the entire, ever-growing chunk string on each chunk event — roughly quadratic in content length for long "thinking" outputs. For typical lengths this is fine, but consider formatting per item only when its content changes (e.g., caching by content) if you observe jank on long streams.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/`(main)/task/[taskId]/spec/page.tsx around lines 1298 - 1306, The current
useMemo over displayedStreamItems repeatedly re-runs formatSpecThinkingMarkdown
on the full accumulated chunk text whenever streamItems changes, which can
become quadratic for long streaming outputs. Update the rendering path around
displayedStreamItems so chunk formatting is cached or applied only when an
individual chunk’s content changes, rather than remapping and reformatting the
entire growing string on every stream update. Use the existing streamItems
mapping logic and formatSpecThinkingMarkdown as the key symbols to adjust.

457-461: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

isSpecThinkingHeading is defined but never used.

This helper isn't referenced by formatSpecThinkingMarkdown or anywhere else in the file. It looks like leftover from an earlier heuristic that the regex approach replaced. Remove it to avoid dead code (and a likely lint warning).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/`(main)/task/[taskId]/spec/page.tsx around lines 457 - 461, The helper is
dead code: isSpecThinkingHeading is defined but not referenced anywhere in the
file, including formatSpecThinkingMarkdown. Remove the unused function and any
related import or leftover heuristic code so the module only keeps the active
heading parsing logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@app/`(main)/task/[taskId]/spec/page.tsx:
- Around line 516-520: The priority chip in the task spec page is building
classes with a template literal instead of the project’s `cn` utility. Update
the conditional priority-chip rendering to compose the static classes with
`priorityChipClass(item.priority)` through `cn`, and add `cn` to the existing
`@/lib/utils` import in this component so the class concatenation follows the
shared styling convention.
- Around line 115-137: The guardrail and acceptance-criteria normalization logic
is duplicated in multiple places, so extract it into shared helpers and reuse
them. Move the mapping/filtering currently in the spec page’s normalization
block into functions like normalizeGuardrails and normalizeAcceptanceCriteria,
then update specOutputToPlan and FunctionalRequirementCard to call those helpers
instead of inlining the same conversions. Keep the behavior identical, including
string handling and fallback serialization, so the API-shape logic stays
consistent in one place.
- Around line 1298-1306: The current useMemo over displayedStreamItems
repeatedly re-runs formatSpecThinkingMarkdown on the full accumulated chunk text
whenever streamItems changes, which can become quadratic for long streaming
outputs. Update the rendering path around displayedStreamItems so chunk
formatting is cached or applied only when an individual chunk’s content changes,
rather than remapping and reformatting the entire growing string on every stream
update. Use the existing streamItems mapping logic and
formatSpecThinkingMarkdown as the key symbols to adjust.
- Around line 457-461: The helper is dead code: isSpecThinkingHeading is defined
but not referenced anywhere in the file, including formatSpecThinkingMarkdown.
Remove the unused function and any related import or leftover heuristic code so
the module only keeps the active heading parsing logic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1c92f2ac-9c94-464f-bb09-3cbebe3ba2ee

📥 Commits

Reviewing files that changed from the base of the PR and between 3722332 and 2a3f03a.

📒 Files selected for processing (1)
  • app/(main)/task/[taskId]/spec/page.tsx

@nndn nndn merged commit 6a73f9c into main Jul 3, 2026
4 of 5 checks passed
@nndn nndn deleted the spec-ui-outcome-alignment branch July 3, 2026 10:56
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.

2 participants