Backfill and translate executive briefs; enforce H1 gate v4.4#2518
Conversation
Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/432600fa-f77e-41ff-a815-93179557c0d8 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
🏷️ Automatic Labeling SummaryThis PR has been automatically labeled based on the files changed and PR metadata. Applied Labels: documentation,size-m Label Categories
For more information, see |
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
…ract Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/06fa90f6-02ad-4090-8332-3a70e8fc5a1e Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/2cf7206a-ba3b-4858-b24b-fcb53ac7e0bd Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
…honest) Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/fa8626cc-6ad0-4047-8174-2a5ac33391e3 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/a62f80a7-a9fa-4cc1-a20e-b373a20b62b6 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
There was a problem hiding this comment.
Pull request overview
This PR combines three deliverables under one branch: (1) translating the seven 2026-05-15 executive briefs from Swedish to English so the canonical executive-brief.md H1 ships as the SERP <title>/og:title/JSON-LD headline across all 14 languages, (2) back-filling a missing analysis/daily/2026-05-04/realtime-pulse/executive-brief.md, and (3) introducing a new H1-quality gate (TypeScript + bash) that blocks template placeholders (REPLACE THIS H1, Executive Brief Template, AI_MUST_REPLACE, AI-generated political intelligence, and bare # Executive Brief), plus a v4.4 template rewrite (Headline-Candidates worksheet, 6-axis BLUF rubric, expanded 14-language seeds) and updated methodology / SEO contract docs.
Changes:
- Add H1 quality enforcement in
checkExecutiveBrief()(TS) and the inline bash gate, with 4 new placeholder patterns + bare-boilerplate detection and 5 new vitest cases. - Translate 7 × 2026-05-15 executive briefs to English (proper nouns preserved, retrofit notes appended) and backfill
2026-05-04/realtime-pulse/executive-brief.md. - Expand
executive-brief.mdtemplate,per-artifact-methodologies.md, andseo-metadata-contract.mdwith the rubric/worksheet/14-language guidance and refresh the test seed H1.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/agentic/analysis-gate.ts | Adds H1 placeholder/banned-phrase/bare-boilerplate checks to checkExecutiveBrief(). |
| tests/agentic-analysis-gate.test.ts | Updates valid-seed H1 and adds 4 new failure-mode cases + 1 emoji-tolerance case. |
| .github/prompts/05-analysis-gate.md | Mirrors the TS H1 scan in inline bash; expands Check 7 rule text. |
| .github/prompts/seo-metadata-contract.md | Cross-links the methodology and adds rubric / worksheet / nb checklist items. |
| analysis/methodologies/per-artifact-methodologies.md | Adds an authoritative executive-brief ⭐ section. |
| analysis/templates/executive-brief.md | Template v4.4: explicit placeholder H1, BLUF rubric, Headline-Candidates worksheet, expanded SEO seeds, self-audit additions. |
| analysis/daily/2026-05-15/committeeReports/executive-brief.md | English H1 + Mermaid labels + retrofit note. |
| analysis/daily/2026-05-15/evening-analysis/executive-brief.md | Full Swedish→English translation, new BLUF section, retrofit note. |
| analysis/daily/2026-05-15/interpellations/executive-brief.md | Story-anchored H1, table/timeline/risk translation, retrofit note. |
| analysis/daily/2026-05-15/motions/executive-brief.md | Glosses betänkanden / Lagrådet; retrofit note. |
| analysis/daily/2026-05-15/propositions/executive-brief.md | Full translation + retrofit note. |
| analysis/daily/2026-05-15/realtime-pulse/executive-brief.md | Full translation, Mermaid relabel, retrofit note. |
| analysis/daily/2026-05-15/week-ahead/executive-brief.md | English renderings of two source quotes with Swedish kept in italics. |
| analysis/daily/2026-05-04/realtime-pulse/executive-brief.md | New backfilled brief synthesised from existing Pass-2 artefacts. |
| const h1Match = content.match(/^#\s+(.+?)\s*$/m); | ||
| if (h1Match) { | ||
| const h1 = h1Match[1] | ||
| // Strip <p align="center"> / <h1 align="center"> wrappers (the | ||
| // template uses <h1 align="center">…</h1>; we extract the inner | ||
| // text in the fallback regex below). Markdown H1 is the primary | ||
| // path so this branch is mostly defensive. |
| EB_H1="$(grep -m1 -E '^#[[:space:]]+' "$ANALYSIS_DIR/executive-brief.md" || true)" | ||
| if [ -n "$EB_H1" ]; then | ||
| EB_H1_LOWER="$(printf '%s' "$EB_H1" | tr '[:upper:]' '[:lower:]')" | ||
| case "$EB_H1_LOWER" in | ||
| *replace\ this\ h1*|*replace*this*h1*) | ||
| echo "❌ executive-brief.md: H1 still contains 'REPLACE THIS H1' placeholder — write a story-oriented publishable title (see methodology #executive-brief)"; FAIL=1 ;; | ||
| *executive\ brief\ template*) | ||
| echo "❌ executive-brief.md: H1 still says 'Executive Brief Template' — replace with a publishable title"; FAIL=1 ;; | ||
| *ai_must_replace*|*ai-must-replace*) | ||
| echo "❌ executive-brief.md: H1 contains AI_MUST_REPLACE stub marker"; FAIL=1 ;; | ||
| *ai-generated\ political\ intelligence*) | ||
| echo "❌ executive-brief.md: H1 contains banned phrase 'AI-generated political intelligence'"; FAIL=1 ;; | ||
| esac | ||
| # Strip leading H1 marker + emoji/whitespace + trailing dashes to detect | ||
| # the bare-boilerplate `# Executive Brief` case. | ||
| EB_H1_PLAIN="$(printf '%s' "$EB_H1_LOWER" \ | ||
| | sed -E 's/^#[[:space:]]+//' \ | ||
| | sed -E 's/^[^[:alnum:]]+//' \ | ||
| | sed -E 's/[[:space:]—–-]+$//')" | ||
| if [ "$EB_H1_PLAIN" = "executive brief" ] || [ -z "$EB_H1_PLAIN" ]; then | ||
| echo "❌ executive-brief.md: H1 is bare boilerplate ('Executive Brief') — write a publishable story-oriented title (actor + active verb + instrument or number)" | ||
| FAIL=1 | ||
| fi | ||
| fi |
| // H1 quality check — block the template-placeholder and boilerplate-only | ||
| // headings that would ship as the SERP <title>. | ||
| const h1Match = content.match(/^#\s+(.+?)\s*$/m); | ||
| if (h1Match) { | ||
| const h1 = h1Match[1] | ||
| // Strip <p align="center"> / <h1 align="center"> wrappers (the | ||
| // template uses <h1 align="center">…</h1>; we extract the inner | ||
| // text in the fallback regex below). Markdown H1 is the primary | ||
| // path so this branch is mostly defensive. | ||
| .replace(/<[^>]+>/g, '') | ||
| .trim(); | ||
| const h1Lower = h1.toLowerCase(); | ||
| // Patterns that indicate the editor did not replace the template H1. | ||
| const placeholderPatterns: ReadonlyArray<{ pattern: RegExp; label: string }> = [ | ||
| { pattern: /replace\s*this\s*h1/i, label: "literal 'REPLACE THIS H1' placeholder" }, | ||
| { pattern: /executive\s+brief\s+template/i, label: "'Executive Brief Template' template heading" }, | ||
| { pattern: /ai[_\s-]*must[_\s-]*replace/i, label: "'AI_MUST_REPLACE' stub marker" }, | ||
| { pattern: /ai-generated\s+political\s+intelligence/i, label: "banned phrase 'AI-generated political intelligence'" }, | ||
| ]; | ||
| for (const { pattern, label } of placeholderPatterns) { | ||
| if (pattern.test(h1)) { | ||
| results.push({ | ||
| checkId: 'family-c-structure', | ||
| passed: false, | ||
| message: `executive-brief.md: H1 still contains ${label} — replace with a story-oriented publishable title (see methodology #executive-brief)`, | ||
| artifact: 'executive-brief.md', | ||
| }); | ||
| } | ||
| } | ||
| // Bare-boilerplate H1: just "Executive Brief" (optionally with | ||
| // emoji / leading icon). `cleanArticleTitle()` strips the | ||
| // `Executive Brief — ` prefix and trailing date; if the H1 is | ||
| // literally just `Executive Brief`, nothing remains and the | ||
| // renderer falls back to `titleFromBluf()`. | ||
| const h1Plain = h1Lower | ||
| .replace(/^[\p{Emoji_Presentation}\p{Extended_Pictographic}\s—–-]+/u, '') | ||
| .replace(/[\s—–-]+$/u, '') | ||
| .trim(); | ||
| if (h1Plain === 'executive brief' || h1Plain === '') { | ||
| results.push({ | ||
| checkId: 'family-c-structure', | ||
| passed: false, | ||
| message: | ||
| "executive-brief.md: H1 is bare boilerplate ('Executive Brief') — write a publishable story-oriented title (55–70 chars EN, actor + active verb + instrument or number)", | ||
| artifact: 'executive-brief.md', | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| if ( | ||
| hasBluf && | ||
| hasDecisions && | ||
| results.filter((r) => !r.passed && r.artifact === 'executive-brief.md').length === 0 | ||
| ) { |
|
@copilot apply changes based on the comments in this thread |
Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/aae83d02-a13b-4133-8792-1387cbf3164d Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Implemented the requested review follow-up in ebc7aae: the TS and bash H1 gates now fall back to HTML |
🔍 Lighthouse Performance Audit
📥 Download full Lighthouse report Budget Compliance: Performance budgets enforced via |
Combined executive-brief backfill, translation, and H1 gate rollout
This PR combines three related executive-brief deliverables:
analysis/daily/2026-05-04/realtime-pulse/executive-brief.md.analysis/daily/2026-05-15/*/executive-brief.mdbriefs to English while preserving identifiers, dates, evidence, and audit traceability.<title>,og:title, JSON-LDheadline, sitemap cards, RSS metadata, and downstream 14-language surfaces.Scope
scripts/agentic/analysis-gate.ts..github/prompts/05-analysis-gate.md.REPLACE THIS H1,Executive Brief Template,AI_MUST_REPLACE,AI-generated political intelligence, and bareExecutive Briefheadings.# ...headings and the template’s centered HTML<h1>...</h1>form.analysis/templates/executive-brief.mdwith the Headline-Candidates worksheet, six-axis BLUF rubric, and expanded 14-language H1 seed guidance.Translation and preservation notes
The seven 2026-05-15 executive briefs were translated to English canonical content while preserving every
dok_id, percentage, vote count, named MP/minister, and date. Swedish proper nouns and source terms remain where required, including party codes, committee abbreviations,Tidö,riksmöte,Riksdag, agencies, ministry names,Aurora 26, andRiksbank.Quoted Swedish source phrases are retained in italics with English translation alongside for audit traceability. Markdown structure, Mermaid graph topology, evidence tables, and retrofit notes are preserved.