chore(scripts): dashboard regen extracts PR# from idea-only legacy folders - #221
Conversation
…lders Extends _extract_pr_number in scripts/build_mvp1_dashboard.py with two new cascade priorities (3.5 + 3.6) that mine idea.md content for own-PR assertions when pipeline_status / plan / spec are empty — the typical shape for ~50 early MVP1 features that shipped before /pipeline ceremony. Story 1.1: 5 module-level re.compile patterns (3 strict Status/Shipped / Implemented / line-anchored shipped-dateline, 1 **PR:** frontmatter, 1 metadata-key matcher) + _extract_metadata_block helper bounding the **PR:** search to a contiguous metadata cluster (30-line cap). Story 1.2: threads idea content through _load_implemented + _load_planned; adds 27-case test file covering all 17 spec ACs + edge cases; documents the **PR:** frontmatter convention in architecture.md. Empirical verification: regen produced 3 newly-resolved PR rows, ZERO existing PR-linked rows changed. Below predicted 5-8 forward gain — only ~3 of ~50 idea-only folders carry canonical strict shapes; **PR:** frontmatter is the escape hatch for the rest, applied opportunistically. Tangential capture: chore_dashboard_regen_quoted_pr_false_positive documents the pre-existing priority-3 fuzzy-regex weakness that lets spec/plan content quoting other features' merge phrases trip the regex. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request extends the dashboard regeneration script to extract PR numbers from idea.md files for legacy features that lack formal specification or pipeline status documents. It introduces strict regex patterns and a new **PR:** frontmatter convention to identify a feature's own PR while avoiding false positives from dependency references. The changes include updates to scripts/build_mvp1_dashboard.py, a new comprehensive test suite in backend/tests/unit/scripts/test_dashboard_pr_extraction.py, and documentation updates in architecture.md. Review feedback suggests improving the robustness of the new regex patterns by supporting markdown links consistently and refining the one_liner extraction logic for legacy features.
| _IDEA_STATUS_IMPLEMENTED_RE = re.compile( | ||
| r"^\*\*Status:\*\*\s+\*\*Implemented\s*[—\-]\s*PR\s*#(\d+)\b", | ||
| re.MULTILINE, | ||
| ) |
There was a problem hiding this comment.
Pattern B (_IDEA_STATUS_IMPLEMENTED_RE) should support the same markdown link alternation as Pattern A. This ensures robustness if an implemented status line uses a linked PR number, and maintains consistency across the strict idea-body patterns documented in architecture.md.
| _IDEA_STATUS_IMPLEMENTED_RE = re.compile( | |
| r"^\*\*Status:\*\*\s+\*\*Implemented\s*[—\-]\s*PR\s*#(\d+)\b", | |
| re.MULTILINE, | |
| ) | |
| _IDEA_STATUS_IMPLEMENTED_RE = re.compile( | |
| r"^\*\*Status:\*\*\s+\*\*Implemented\s*[—\-]\s*PR\s*" | |
| r"(?:\[#(\d+)\b\]\([^)]*\)|\[#(\d+)\b\]|#(\d+)\b)", | |
| re.MULTILINE, | |
| ) |
| _IDEA_SHIPPED_DATELINE_RE = re.compile( | ||
| r"^\*\*shipped\s+\d{4}-\d{2}-\d{2}\s+as\s+PR\s*#(\d+)\b", | ||
| re.MULTILINE, | ||
| ) |
There was a problem hiding this comment.
Pattern C (_IDEA_SHIPPED_DATELINE_RE) should support the same markdown link alternation as Pattern A for consistency and robustness against linked PR references in legacy datelines.
| _IDEA_SHIPPED_DATELINE_RE = re.compile( | |
| r"^\*\*shipped\s+\d{4}-\d{2}-\d{2}\s+as\s+PR\s*#(\d+)\b", | |
| re.MULTILINE, | |
| ) | |
| _IDEA_SHIPPED_DATELINE_RE = re.compile( | |
| r"^\*\*shipped\s+\d{4}-\d{2}-\d{2}\s+as\s+PR\s*" | |
| r"(?:\[#(\d+)\b\]\([^)]*\)|\[#(\d+)\b\]|#(\d+)\b)", | |
| re.MULTILINE, | |
| ) |
| one_liner = _extract_one_liner(spec, source_dir=folder_path) | ||
| pr = _extract_pr_number(pipe, plan, spec) | ||
| pr = _extract_pr_number(pipe, plan, spec, idea) |
There was a problem hiding this comment.
In _load_implemented, the one_liner extraction should fall back to _extract_idea_problem(idea) if spec is missing, consistent with the logic in _load_planned. This ensures that legacy idea-only features display their problem description in the dashboard summary column instead of falling back to the generic "Complete" status line. Additionally, consider including idea in the status_line extraction (at line 791) for better descriptive coverage of legacy folders.
| one_liner = _extract_one_liner(spec, source_dir=folder_path) | |
| pr = _extract_pr_number(pipe, plan, spec) | |
| pr = _extract_pr_number(pipe, plan, spec, idea) | |
| one_liner = ( | |
| _extract_one_liner(spec, source_dir=folder_path) | |
| if spec | |
| else _extract_idea_problem(idea, idea_dir=folder_path) | |
| ) | |
| pr = _extract_pr_number(pipe, plan, spec, idea) |
Gemini Code Assist surfaced 3 Medium findings on PR #221: 1. Pattern B (`_IDEA_STATUS_IMPLEMENTED_RE`) was missing the markdown- link alternation that Pattern A carries. Added the same `(?:\[#(\d+)\b\]\([^)]*\)|\[#(\d+)\b\]|#(\d+)\b)` alternation for consistency. Purely additive — never reduces matches. 2. Pattern C (`_IDEA_SHIPPED_DATELINE_RE`) — same fix as #1. Symmetric alternation across all three strict patterns now. 3. `_load_implemented`'s one-liner extraction used `_extract_one_liner (spec)` only — returning empty for legacy idea-only folders. Added `_extract_idea_problem(idea)` fallback (symmetric with `_load_planned`) so idea-only legacy folders now render their Problem text in the dashboard's one-liner column instead of going blank. Empirical verification re-run: regen produced clean output. Status columns for the strict-pattern targets (chore_create_study_modal_e2e_ stability → PR #161, chore_precommit_node_path_resolution → PR #171) remain correctly populated. The new one-liner fallback adds visible narrative text for many idea-only rows (bug_*, chore_*) that previously showed empty/Complete-only — material UX improvement on top of the PR# extraction this chore primarily delivers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…5 final review) GPT-5.5 final review caught a subtle bug in `_extract_metadata_block`: when an idea body begins with metadata-key lines (NO `# ` title at the top), a later `# ` line within the 30-line cap was treated as the title (because `title_seen` was only set on `# ` lines) — letting any `**PR:**` line that followed the body H1 stay inside the metadata- block search scope, violating FR-3's "title line allowed ONLY as the first non-blank line" rule. Fix: replace `title_seen` with `nonblank_seen`. Once ANY non-blank line (metadata or otherwise) has been processed, a subsequent `# ` is a body heading and stops the block. New regression test: `test_h1_after_metadata_is_body_heading_not_title` constructs the exact case GPT-5.5 flagged (metadata-first, body H1 at line 4, `**PR:** #999` at line 5) and asserts both the helper and `_extract_pr_number` reject #999. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Review adjudication (Gemini Code Assist + GPT-5.5 final review)Commits landing fixes: Gemini Code Assist (3 findings)
GPT-5.5 final review (2 findings)
Outcomes
Ready for human review + merge. |
…rge (#222) * docs: finalize chore_dashboard_pr_extraction_from_idea post-PR-221 merge Moves the chore folder to implemented_features/2026_05_23_chore_ dashboard_pr_extraction_from_idea/ per the impl-execute skill Step 8 finalization workflow. Updates: - pipeline_status.md → Implementation: Complete (PR #221 squash 8a6452d, CI green 5/5 across 3 pushes, Gemini 3/3 accepted, final GPT-5.5 1 deferred + 1 accepted) - implementation_plan.md → Status: Complete (PR #221) - feature_spec.md → Status: Implemented (PR #221) - state.md → Recent-changes entry; Current-branch prepend; Active- feature notes third MVP1.0-cleanup chore. - MVP1_DASHBOARD + dashboard.html regenerated by pre-commit (folder move shifts the chore into the shipped table). The tangential idea folder `chore_dashboard_regen_quoted_pr_false_ positive/` stays in `planned_features/` — captured by the chore's empirical verification, not addressed by it. Alembic head unchanged at 0017_proposals_last_polled_at. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(docs): Gemini PR #222 — paraphrase merged-date triggers + align P3→P2 Gemini Code Assist on PR #222 surfaced 3 Medium findings: 1. MVP1_DASHBOARD.md line 77 + 2. mvp1_dashboard.html line 1207 — chore's row showed `merged 2026-05-15` instead of `2026-05-23` because spec/plan content contained literal `(squash-merged 2026-05-15…)` precedent quotes that `_extract_merged_date` regex picked up. Fixed by paraphrasing the two trigger lines in the chore's now-implemented spec + plan; regen now shows the correct merged 2026-05-23. 3. state.md tier mismatch on chore_dashboard_regen_quoted_pr_false_ positive — labeled P3 in the idea but coerced to P2 by the dashboard regen (only P0/P1/P2/Backlog recognized). Set to P2 explicitly to keep the two sources aligned (same fix pattern as chore_e2e_seed_acme_idea_obsolete from the prior chore). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merge origin/main into feature/auto-followup-studies; main brought chore_dashboard_pr_extraction_from_idea (PR #221) + chore_migration_test_head_brittleness (PR #219) which moved both folders to implemented_features/ and updated the dashboard regen script. State.md "most recent meaningful changes" reconciled to preserve both branches' entries in chronological order. Dashboards re-rendered via scripts/build_mvp1_dashboard.py. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…lf-triggering + capture priority-4 follow-on GPT-5.5 final-review caught the chore's own dashboard row still showed a wrong PR# despite the priority-3 fix. Root cause: spec/plan contained inline `PR #N merged YYYY-MM-DD` example fixtures that the dashboard regen self-scans. Fix: rewrite ACs 6, 7, 8, 9, 10, 12 in feature_spec.md and Story 1.3 task description in implementation_plan.md to reference the test method names instead of inlining the literal Python source. Keeps human-reader value (tests remain the source of truth) while removing self-triggering content. After this rewrite + regen, the dashboard now extracts PR #221 from the idea.md "Depends on" footnote (priority-4 last-resort fallback), NOT the priority-3 backtick-quoted false positive this chore addresses. That's a DIFFERENT bug class, captured as a follow-on chore: chore_dashboard_regen_priority4_dependency_cite_false_positive. Tests still pass: 8 in TestBacktickStripPriority3, 35 total in test_dashboard_pr_extraction.py. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ber priority-3 fuzzy match (#253) * docs(dashboard-regen-regex): /idea-preflight refreshes 3 stale claims in idea.md Preflight audit (against current main 2a24fae) found 3 stale references: 1. _extract_pr_number cited at scripts/build_mvp1_dashboard.py:572 -> actual line 581 2. chore_dashboard_pr_extraction_from_idea cited as "PR-TBD" -> shipped as PR #221 on 2026-05-23 3. "Why deferred" section framed sibling chore as pre-ship -> clarified shipped + added line cite All other concrete claims verified: _strip_dependency_table_rows at line 488, priority parser at lines 240-245, both regexes (lines 629/632) match character-for-character, bug_dashboard_depends_on_column_bloat folder exists, test file backend/tests/unit/scripts/test_dashboard_pr_extraction.py present. Folder name "chore_dashboard_regen_quoted_pr_false_positive" is acceptable (6 tokens, intent-clear). No rename needed. Decision locked: Option A (backtick-scope strip) is the chore's recommended implementation per idea's Recommendation section. Option C (opt-in marker) as follow-up if A leaves residual false positives. Sibling coordination: chore_dashboard_pr_extraction_from_idea (PR #221) + bug_dashboard_depends_on_column_bloat (PR #208) both shipped 2026-05-23. No in-flight feature touches scripts/build_mvp1_dashboard.py. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(dashboard-regen-regex): /spec-gen ships feature_spec.md (3 GPT-5.5 cycles) Generates feature_spec.md and pipeline_status.md for the dev-infra script chore that adds `_strip_backtick_quoted_segments` to scripts/build_mvp1_dashboard.py and wires it into priority-3 of `_extract_pr_number` to stop matching backtick-quoted PR-merge phrases (Option A per idea's Recommendation). 5 FRs, 7 ACs (AC-6 through AC-12), single phase, two-PR rollout. GPT-5.5 cross-model review converged in 3 cycles: - Cycle 1: 1 Low (AC-7 missed single-line triple-backtick fences). Accepted -> added AC-12, extended FR-1 to enumerate all 3 fence flavors (multi-line, single-line, empty), renamed AC-7 to "multi-line", bumped test count 6 -> 7. - Cycle 2: 2 Low (regex hint `+` would skip empty inline spans per AC-11; 4 stale "6 tests" references). Both accepted, patched regex hint to `*` and updated all 4 references to 7. - Cycle 3: 0 findings -> stop rule satisfied. Auto-regenerated MVP1_DASHBOARD.md from mvp1-dashboard-regen pre-commit hook. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(dashboard-regen-regex): /impl-plan-gen ships implementation_plan.md (2 GPT-5.5 cycles) 5 stories across 2 epics: Epic 1 = 4 content stories in PR A; Epic 2 = 1 finalization story in PR B. GPT-5.5 review converged in 2 cycles: - Cycle 1: 2 findings -> both accepted, patched. - Low: Epic 1 gate commit arithmetic 6 vs 7 -> fixed to 7. - Medium: regex matched exactly-3 backticks but spec said 3-or-more -> changed to `{3,} for spec-compliance. - Cycle 2: 0 findings -> stop rule satisfied. Auto-regenerated dashboards from pre-commit hook. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(dashboard): add _strip_backtick_quoted_segments helper (FR-1, Story 1.1) New module-level helper at line 499 of scripts/build_mvp1_dashboard.py, placed immediately after _strip_dependency_table_rows. Removes three fence flavors (multi-line triple-backtick, single-line triple-backtick, empty triple-backtick) via Pass A regex `\`{3,}.*?\`{3,}` with re.DOTALL, then strips inline backtick spans (including empty ``) via Pass B regex `\`[^\`\n]*\``. The 3-or-more backtick quantifier accommodates markdown's 4+ backtick convention for embedding 3-backtick blocks per spec FR-1. Not yet wired into _extract_pr_number — that's Story 1.2. DoD verification: function exists at line 499; importable; 5 smoke cases all return expected output (plain unchanged, multi-line stripped, single-line stripped, inline stripped, empty inline + empty fence both removed without raising). Story 1.1 / FR-1 / AC-10 / AC-11 / AC-12. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(dashboard): wire _strip_backtick_quoted_segments into _extract_pr_number priority-3 (FR-2, Story 1.2) Modifies the priority-3 combined-text assignment in _extract_pr_number to run _strip_backtick_quoted_segments BEFORE _strip_dependency_table_rows. Net effect: backtick-fenced PR# tokens (multi-line, single-line, inline) never reach the priority-3 fuzzy regexes. No change to priorities 1, 2, 3.5, 3.6, or 4. DoD verification: wire-in shape verified by grep; existing TestPriorityCascade::test_ac9_fuzzy_merged_in_spec_beats_idea regression guard still PASSED. Story 1.2 / FR-2 / AC-6 / AC-7 / AC-8 / AC-9. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(dashboard): add TestBacktickStripPriority3 with 7 methods (FR-3, Story 1.3) New test class at line 365 covering AC-6 through AC-12 from the spec. Adds _strip_backtick_quoted_segments to the existing import block. DoD: 7 new methods all PASSED; full file = 35 PASSED (28 existing + 7 new). Regression guard AC-9 confirms priority-3 still matches un-backticked own-PR prose correctly. Story 1.3 / FR-3 / AC-6 through AC-12. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(dashboard): note backtick strip in _extract_pr_number priority-3 docstring (FR-4, Story 1.4) Adds one sentence to the priority-3 description in the _extract_pr_number docstring (currently lines 615-621) explaining that backtick-fenced segments are stripped via _strip_backtick_quoted_segments before dependency-table rows. Cites the new helper by name so future grep finds the dependency. No code changes outside the docstring. DoD: docstring contains both "leak through" sentences (one for backtick strip, one for dependency-table rows); references new helper by name; docstring still parses correctly via inspect. Story 1.4 / FR-4. Completes Epic 1 (PR A content). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(dashboard): backref same-width fence regex + add AC-13 nested-fence test Phase-gate GPT-5.5 review (Medium finding) caught that the naive regex `\`{3,}.*?\`{3,}` would close a 4-backtick outer fence at the first inner 3-backtick run, leaving any PR# inside the outer fence after that inner block un-stripped. Spec FR-1 requires "3 or more backticks", so the implementation must handle 4+ outer fences containing inner 3-backtick blocks as one outer unit. Fix: change the Pass-A regex to `(\`{3,}).*?\1`. The backreference forces the closing run to be the EXACT same width as the opener, so an inner 3-backtick fence inside a 4-backtick outer doesn't terminate the strip. Added test_ac13_four_backtick_outer_with_inner_three_backtick_returns_none to TestBacktickStripPriority3 (now 8 methods covering AC-6..AC-13). Empirical verification: zero real RelyLoop content uses 4-backtick fences (grep -r '\`\`\`\`' docs/ scripts/ returned only this chore's own docstring), so the spec contract was technically violated but no current content triggered the gap. The fix is preemptive correctness per spec FR-1. Spec/plan count references (7 → 8) will be updated in the finalization PR when the folder moves to implemented_features. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(dashboard-regen-regex): rewrite spec+plan to avoid priority-3 self-triggering + capture priority-4 follow-on GPT-5.5 final-review caught the chore's own dashboard row still showed a wrong PR# despite the priority-3 fix. Root cause: spec/plan contained inline `PR #N merged YYYY-MM-DD` example fixtures that the dashboard regen self-scans. Fix: rewrite ACs 6, 7, 8, 9, 10, 12 in feature_spec.md and Story 1.3 task description in implementation_plan.md to reference the test method names instead of inlining the literal Python source. Keeps human-reader value (tests remain the source of truth) while removing self-triggering content. After this rewrite + regen, the dashboard now extracts PR #221 from the idea.md "Depends on" footnote (priority-4 last-resort fallback), NOT the priority-3 backtick-quoted false positive this chore addresses. That's a DIFFERENT bug class, captured as a follow-on chore: chore_dashboard_regen_priority4_dependency_cite_false_positive. Tests still pass: 8 in TestBacktickStripPriority3, 35 total in test_dashboard_pr_extraction.py. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(dashboard): handle double-backtick inline spans in _strip_backtick_quoted_segments Per Gemini Code Assist High-severity finding on PR #253: the inline-span regex `\`[^\`\n]*\`` only handled single-backtick spans. Double-backtick spans like \`\`PR #99 merged\`\` were processed as two empty single-backtick spans (one at the opener pair, one at the closer pair), leaving the inner content un-stripped and reaching the priority-3 fuzzy regex as a false positive. Fix: change Pass B to `(\`{1,2})[^\n]*?\1` — backreference enforces same-width close so 2-backtick spans close on 2 backticks (not the inner single-backtick chars). AC-11's empty `\`\`` still works (group 1 = 1 backtick, `[^\n]*?` = 0 chars, `\1` = second backtick). Empirical verification: - AC-11 empty inline still stripped - New: `\`\`PR #99 merged\`\` more` strips to `text more` (no PR #99) - Single-backtick `\`PR #42 merged\`` still stripped - Full test_dashboard_pr_extraction.py: 36 PASSED Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…4 PR# scan (#277) * fix(dashboard): strip narrative Depends-on footnotes before priority-4 PR# scan Closes chore_dashboard_regen_priority4_dependency_cite_false_positive (Option A). Priority-4's last-resort `#N` fallback at scripts/build_mvp1_dashboard.py:694 scans the combined pipe+plan+spec text gated only by `_strip_dependency_table_rows`, which matches markdown TABLE rows (lines starting with `|`). Narrative inline footnotes like `**Depends on:** foo PR #208 + bar PR #221 — both shipped 2026-05-23` flow through unchanged; priority-4 then returns the first dependency PR# as the feature's own PR. Surfaced by GPT-5.5 on PR #253's final review when the chore's own dashboard row showed PR #221 (a sibling's PR) instead of its own. Fix: add sibling `_strip_dependency_footnote_lines` helper that strips single-line `**Depends on:**` / `Depends on:` / `**Dependencies:**` shapes (with optional bullet prefix and optional `**` markers). Apply after `_strip_dependency_table_rows` in the priority-3/4 composition: backtick-strip → table-row strip → footnote-strip. Scope is intentionally narrow: - Catches `Depends on` / `Dependencies` / `Depended on`, NOT `Implemented` (which `_DEP_ROW_RE` catches in tables but is a legitimate status line as narrative). - Single-line only. The idea's cons-list flags multi-line `## Dependencies\n\nfoo PR #N` (header form) as a known gap — a separate surface that would warrant its own follow-up if observed. Regression tests (5) in new `TestPriority4DependencyFootnoteFalsePositive` class: - minimal two-PR footnote → None - PR #253's canonical footnote shape → None - unbolded `- Depends on:` variant → None - `**Dependencies:**` plural variant → None - legitimate own-PR `#N` in priority-4 fallback still resolves (negative guard against over-stripping) Live-dashboard verification: running `scripts/build_mvp1_dashboard.py` against the current working tree reports "no changes (132 features across 3 release(s))". The fix is forward-looking; no shipped-row PR# is recomputed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(dashboard): include `+` bullet + singular `Dependency` in footnote strip Addresses Gemini Code Assist Medium finding on PR #277. Two minor gaps in `_DEP_FOOTNOTE_RE`'s coverage: 1. `+` bullet marker — standard Markdown allows `+` as a list bullet alongside `-` and `*`. Extending `[-*]` → `[-*+]` matches the spec. 2. Singular `Dependency:` — real-world variant for single-dependency cites (alongside the existing `Dependencies` plural). Regex split across continuation strings to satisfy E501 (line-length). Regression test locks both shapes. Real-data regen still reports "no changes (132 features across 3 release(s))" — strictly forward-looking. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Extends
_extract_pr_numberin the dashboard regen script with two new cascade priorities (3.5 + 3.6) that mineidea.mdcontent for own-PR assertions. This closes the data gap where ~50 early MVP1 implemented features with onlyidea.mdartifacts (no spec/plan/pipeline_status) render asCompleteinstead of[PR #N](url) merged YYYY-MM-DDin the regenerated dashboard.re.compile'd patterns (3 line-anchored strict patterns +**PR:**frontmatter pattern + metadata-key matcher) and a new_extract_metadata_blockhelper that bounds the**PR:**search to the idea's metadata cluster (contiguous metadata-key lines stopping at the first##heading or non-metadata non-blank line; 30-line cap for headingless edge cases). Each pattern's\bboundary sits immediately after the digit capture per GPT-5.5 cycle-2 fix.idea.mdcontent through_load_implemented+_load_plannedvia the new 4th arg; adds 27-case test file atbackend/tests/unit/scripts/test_dashboard_pr_extraction.py; documents the**PR:**frontmatter convention inarchitecture.md's new "Dashboard regen" subsection.Pipeline artifacts
idea.md— preflighted 2026-05-23 (line-drift fix 476→499, dependency PR# refreshed to PR fix(dashboard): time-order DEPS_ALL_BACKEND expansion so shipped features don't inherit post-shipment peers #208 shipped, "feature_spec.md— GPT-5.5 cross-model review converged at cycle 3: 12 findings total (2 H / 7 M / 3 L) across 3 cycles, all 11 actionable accepted and applied; 17 ACs lockedimplementation_plan.md— GPT-5.5 cycle 1: 3 findings (0 H / 1 M / 2 L), all accepted (AC-12 ownership clarified,_extract_metadata_blocktitle-once flag added, pytest collection grep-qfix)Test coverage
backend/tests/unit/scripts/test_dashboard_pr_extraction.py(new)Existing unit suite remains green: 1190/1190 (1163 baseline + 27 new).
Empirical verification (per spec §14 step 3)
Run
make dashboardand compare shipped/planned table PR-number columns:Forward gain (3) is below the spec's predicted 5–8. During the preflight survey I counted 5–8 candidate features carrying the canonical strict shapes. The regen actually picks up only 3 because the other 2 of the candidates (
chore_data_table_columnvisibility_tanstack,feat_contextual_help_mvp2) have their PR# captured earlier in the cascade — by priority 3's fuzzymerged-context match against narrative content in their idea bodies. They were already rendering correctly; the new priority 3.5 doesn't get a chance to fire. Net effect on operator value: the chore still does what it set out to do (legacy idea-only folders now surface their PRs), just slightly less of a forward gain than predicted because the existing priority-3 was doing more work than the preflight assumed.Cosmetic anomaly for THIS chore's own planned-feature row: the chore appears in the dashboard's Plan section as
[PR #4] merged 2026-05-15, which is wrong (PR #4 isinfra_foundation, the date is from an AC-1 example body). Root cause: the chore's own spec content contains AC-body examples that quote OTHER features' PR-merge phrases (e.g., AC-4's body**Depends on:** [infra_foundation] — merged via PR #4), which the pre-existing priority-3 fuzzy regex grabs. The anomaly is cosmetic only — resolves automatically when this chore merges and_load_implementedtakes over the row rendering. Captured as a separate idea:chore_dashboard_regen_quoted_pr_false_positivefor future hardening of the priority-3 fuzzy regex.Test plan
make backend-fmt/make backend-lint/make backend-typecheck— green.venv/bin/ruff format --check backend/— green (CI parity)make test-unit— 1190 passed in 5.71s (27 new + 1163 baseline)make dashboard— clean regen, no errors.github/workflows/pr.yml)Tangential capture
docs/02_product/planned_features/chore_dashboard_regen_quoted_pr_false_positive/idea.mdcaptures the pre-existing priority-3 fuzzy regex weakness surfaced during this chore's empirical verification. Out of scope here; provides a future-work target with three implementation options ranked by surgical-ness.🤖 Generated with Claude Code