---
id: 12213
title: Portal Pull Request view — Portal.view.news.pulls (two-section parser)
state: CLOSED
labels:
  - enhancement
  - ai
assignees:
  - neo-opus-ada
createdAt: '2026-05-30T17:26:21Z'
updatedAt: '2026-06-01T08:52:23Z'
githubUrl: 'https://github.com/neomjs/neo/issues/12213'
author: neo-opus-ada
commentsCount: 0
parentIssue: 12204
subIssues: []
subIssuesCompleted: 0
subIssuesTotal: 0
blockedBy:
  - '[x] 12210 Portal index generators for Pull Requests + Discussions (chunked output)'
blocking: []
closedAt: '2026-06-01T08:52:22Z'
---
# Portal Pull Request view — Portal.view.news.pulls (two-section parser)

## Context
Part of epic #12207. PR conversations carry the richest architectural context (review scores, diffs, Fat-Ticket metadata) but are invisible to humans + SEO.

## The Fix
New `pulls` section (copy the release/tickets pattern). The Component implements the PR-specific parser:
- two-section extract of `## Comments` + `## Reviews`;
- entry-split **only** at the `` ### `@user` ... `` header boundary (NOT bare `---` — bodies contain their own `###` sub-headers and `---` rules);
- two header grammars (`commented on <ts>` / `(STATE) reviewed on <ts>`);
- **merge-sort by timestamp** (the two sections are not globally ordered);
- review STATE → color (APPROVED green, CHANGES_REQUESTED red, neutral fallback for unknown/COMMENTED/DISMISSED — do not throw);
- dependabot zero-section degrade via `super.modifyMarkdown` (body-only PRs still render).

Plus a 3-state **OPEN / MERGED / CLOSED** badge (the issue 2-way version mislabels MERGED) + `base ← head` / `url` / `mergedAt` frontmatter renderers. Consumes `pulls.json`.

## Acceptance Criteria
- [ ] Pull Requests tab renders PR body + comments + reviews on the shared timeline + canvas.
- [ ] Reviews entry-split correctly (no shredding on inner `###`/`---`); MERGED state rendered distinctly.

## Related
Epic #12207. Depends on: generators (sub 6), shared-contract extraction (foundation 4), per-type URLs (foundation 5). Grammar source-of-truth: sub 9.

## Timeline

- 2026-05-30T17:26:21Z @neo-opus-ada added the `enhancement` label
- 2026-05-30T17:26:22Z @neo-opus-ada added the `ai` label
- 2026-05-30T17:30:17Z @neo-opus-ada added parent issue #12207
- 2026-05-30T17:31:33Z @neo-opus-ada marked this issue as blocking #12214
- 2026-05-30T17:31:34Z @neo-opus-ada marked this issue as blocking #12215
- 2026-05-30T17:34:59Z @neo-opus-ada removed parent issue #12207
- 2026-05-30T17:35:00Z @neo-opus-ada added parent issue #12204
- 2026-05-30T17:35:51Z @neo-opus-ada removed the block on #12214
- 2026-05-30T17:35:52Z @neo-opus-ada removed the block on #12215
- 2026-05-30T17:35:58Z @neo-opus-ada marked this issue as being blocked by #12210
- 2026-05-30T19:31:22Z @neo-opus-ada cross-referenced by PR #12223
- 2026-05-30T21:49:07Z @neo-opus-ada cross-referenced by PR #12233
- 2026-05-31T18:28:40Z @neo-gpt cross-referenced by #12204
- 2026-05-31T18:51:48Z @neo-opus-ada cross-referenced by PR #12266
- 2026-05-31T19:05:04Z @neo-gpt cross-referenced by PR #12268
- 2026-05-31T21:04:28Z @neo-opus-ada cross-referenced by #12209
- 2026-06-01T04:29:18Z @neo-opus-ada assigned to @neo-opus-ada
- 2026-06-01T04:46:45Z @neo-opus-ada cross-referenced by PR #12287
- 2026-06-01T05:13:35Z @neo-gpt cross-referenced by PR #12288
- 2026-06-01T05:15:52Z @neo-opus-ada referenced in commit `f4453a3` - "test(portal): unit-cover PR-view parser entry-split + merge-sort + badges (#12213)"
- 2026-06-01T05:58:43Z @neo-opus-ada referenced in commit `1ee5fb5` - "fix(portal): make Pulls tab route-driven, not a hardcoded index (#12213)"
- 2026-06-01T07:18:01Z @neo-opus-ada referenced in commit `c73b010` - "feat(portal): pulls view adopts per-type cross-link issuesUrl (#12213)

#N refs in PR bodies are issue numbers → resolve to the portal tickets view. Sets issuesUrl
explicitly so the pulls view keeps correct cross-links once #12209 (PR #12292) removes the
tickets-specific default from the generic content base. Harmless no-op until then (same value
previously inherited)."
- 2026-06-01T08:44:50Z @neo-opus-ada referenced in commit `310c27f` - "feat(portal): add Portal.view.news.pulls PR markdown parser (#12213)"
- 2026-06-01T08:44:50Z @neo-opus-ada referenced in commit `67ec5fa` - "feat(portal): wire Portal.view.news.pulls view, tab + theming (#12213)"
- 2026-06-01T08:44:51Z @neo-opus-ada referenced in commit `0abc253` - "test(portal): unit-cover PR-view parser entry-split + merge-sort + badges (#12213)"
- 2026-06-01T08:44:51Z @neo-opus-ada referenced in commit `db04f89` - "feat(portal): pulls view adopts per-type cross-link issuesUrl (#12213)

#N refs in PR bodies are issue numbers → resolve to the portal tickets view. Sets issuesUrl
explicitly so the pulls view keeps correct cross-links once #12209 (PR #12292) removes the
tickets-specific default from the generic content base. Harmless no-op until then (same value
previously inherited)."
- 2026-06-01T08:52:22Z @tobiu referenced in commit `c35256b` - "feat(portal): Pull Requests news view — Portal.view.news.pulls (#12213) (#12287)

* feat(portal): add Portal.view.news.pulls PR markdown parser (#12213)

* feat(portal): wire Portal.view.news.pulls view, tab + theming (#12213)

* test(portal): unit-cover PR-view parser entry-split + merge-sort + badges (#12213)

* feat(portal): pulls view adopts per-type cross-link issuesUrl (#12213)

#N refs in PR bodies are issue numbers → resolve to the portal tickets view. Sets issuesUrl
explicitly so the pulls view keeps correct cross-links once #12209 (PR #12292) removes the
tickets-specific default from the generic content base. Harmless no-op until then (same value
previously inherited).

---------

Co-authored-by: tobiu <tobiasuhlig78@gmail.com>"
- 2026-06-01T08:52:23Z @tobiu closed this issue
- 2026-06-01T09:00:42Z @neo-opus-ada cross-referenced by #12297
- 2026-06-01T09:05:29Z @neo-opus-ada cross-referenced by PR #12298
- 2026-06-01T09:29:40Z @neo-opus-ada cross-referenced by #12300

