Skip to content

news-translate: pivot to executive-brief markdown across 14 languages, 3 runs/day#2519

Merged
pethers merged 6 commits into
mainfrom
copilot/update-news-translate-workflow
May 16, 2026
Merged

news-translate: pivot to executive-brief markdown across 14 languages, 3 runs/day#2519
pethers merged 6 commits into
mainfrom
copilot/update-news-translate-workflow

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 16, 2026

  • Review workflow/test state and inspect the files called out in the latest PR review
  • Fix executive-brief translation gate so validation failures block merges
  • Align file-ownership CLI help/category aliases with current ownership behavior
  • Harden executive-brief validator fence-count, source-marker, and docstring behavior
  • Fix news-translate worklist wording/path semantics without editing generated lock files
  • Revert generated lock-file deltas so the PR no longer changes *.lock.yml
  • Run targeted validator tests and ESLint
  • Run CodeQL security review and final verification

…SLATION_GUIDE section added, lock regenerated

Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/c214aa5b-d447-43ed-94f7-74cd922495f1

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
@github-actions github-actions Bot added documentation Documentation updates workflow GitHub Actions workflows i18n Internationalization/localization translation Translation updates ci-cd CI/CD pipeline changes news News articles and content generation agentic-workflow Agentic workflow changes size-l Large change (250-1000 lines) labels May 16, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🏷️ Automatic Labeling Summary

This PR has been automatically labeled based on the files changed and PR metadata.

Applied Labels: documentation,workflow,i18n,translation,ci-cd,size-l,news,agentic-workflow

Label Categories

  • 🗳️ Content: news, dashboard, visualization, intelligence
  • 💻 Technology: html-css, javascript, workflow, security
  • 📊 Data: cia-data, riksdag-data, data-pipeline, schema
  • 🌍 I18n: i18n, translation, rtl
  • 🔒 ISMS: isms, iso-27001, nist-csf, cis-controls
  • 🏗️ Infrastructure: ci-cd, deployment, performance, monitoring
  • 🔄 Quality: testing, accessibility, documentation, refactor
  • 🤖 AI: agent, skill, agentic-workflow

For more information, see .github/labeler.yml.

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

…dules and per-type workflow descriptions

Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/3680553b-1502-4360-bff0-d59ef3ff4dc3

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
@github-actions github-actions Bot added dependencies Dependency updates testing Test coverage refactor Code refactoring size-xl Extra large change (> 1000 lines) labels May 16, 2026
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Copilot AI requested a review from pethers May 16, 2026 09:31
Comment thread scripts/validate-executive-brief-translations.ts Fixed
Comment thread scripts/validate-executive-brief-translations.ts Fixed
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

@pethers pethers marked this pull request as ready for review May 16, 2026 09:53
Copilot AI review requested due to automatic review settings May 16, 2026 09:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request repurposes the news-translate workflow from HTML translation to executive-brief Markdown translation across 13 non-English target languages, and adds a defense-in-depth PR gate to enforce ownership and structural parity for those executive brief translations.

Changes:

  • Extend translation documentation and contracts for analysis/daily/**/executive-brief.mdexecutive-brief_<lang>.md.
  • Add/extend validators + unit tests for executive-brief translation parity and file-ownership boundaries.
  • Add a PR-check workflow (exec-brief-translation-checks.yml) to re-run ownership + parity validation on relevant PRs.

Reviewed changes

Copilot reviewed 40 out of 40 changed files in this pull request and generated 23 comments.

Show a summary per file
File Description
TRANSLATION_GUIDE.md Adds executive-brief markdown translation contract and acceptance checklist.
scripts/validate-file-ownership.ts Extends ownership validation to executive-brief markdown and adds file-list/category auto-detection.
scripts/validate-executive-brief-translations.ts Adds structural-parity validator for executive-brief translations.
tests/validate-file-ownership-exec-brief.test.ts Unit tests for new executive-brief ownership rules and category detection.
tests/validate-executive-brief-translations.test.ts Unit tests for executive-brief structural counters + validation checks.
.github/workflows/exec-brief-translation-checks.yml New PR gate that runs ownership + parity validation on PRs touching translation surfaces.
.github/workflows/news-*.lock.yml Recompiled agentic workflow lockfiles (safe-outputs + PR creation flow).

Comment thread TRANSLATION_GUIDE.md Outdated
Comment on lines +29 to +36
- `news/$DATE-$SUB-sv.html` (Swedish master)

The remaining 12 language variants (`da`, `nb`, `fi`, `de`, `fr`, `es`, `nl`, `ar`, `he`, `ja`, `ko`, `zh`) are produced **exclusively** by the standalone [`news-translate`](.github/workflows/news-translate.md) workflow, which:
For HTML article variants, the remaining 12 language renderings (`da`, `no`, `fi`, `de`, `fr`, `es`, `nl`, `ar`, `he`, `ja`, `ko`, `zh`) are emitted inline by the per-type workflows themselves via the per-language `article.<lang>.md` step inside `06-article-generation.md`. The standalone [`news-translate`](.github/workflows/news-translate.md) workflow no longer owns HTML translation; its current mission is **executive-brief Markdown translation** — see §"Executive Brief Markdown Translations" below.
Comment thread TRANSLATION_GUIDE.md
Comment on lines +186 to +188
- [ ] Every `dok_id`, intressent ID, vote ID, and external URL from the source appears in the translation.
- [ ] No verbatim English BLUF / "Decisions" / "Confidence" labels remain in non-English files (validator scans a banned-phrase list).
- [ ] `ar` / `he` files start with `<!-- dir: rtl -->`.
Comment thread TRANSLATION_GUIDE.md
Comment on lines +141 to +144
| Evidence-anchor table column headers present in expected order | exact |
| `dok_id` references preserved (set equality) | exact |
| Image / external-URL set preserved | exact |
| Top-level word count | source ±25 % (translations expand or contract by language; outside ±25 % flags drift) |
Comment thread scripts/validate-file-ownership.ts Outdated
Comment on lines +4 to +10
* Enforces a strict file-ownership contract between content and translation workflows:
* - Content workflows (news-committee-reports, news-propositions, etc.) own EN/SV files
* - Translation workflow (news-translate) owns all other language files (DA/NO/FI/DE/FR/ES/NL/AR/HE/JA/KO/ZH)
* - Content workflows (news-committee-reports, news-propositions, etc.) own
* EN/SV `news/*.html` files **and** the English-master executive brief
* `analysis/daily/$DATE/$SUB/executive-brief.md`.
* - Translation workflow (news-translate) owns the 13 non-English `news/*.html`
* files **and** all `analysis/daily/$DATE/$SUB/executive-brief_<lang>.md`
* files (for the 13 non-English target languages).
Comment on lines +217 to +252
/**
* Auto-detect the workflow category from a list of changed file paths.
*
* Detection rules:
* - If any file is an `executive-brief_<lang>.md` translation, OR
* any `news/*.html` for a non-English/non-Swedish language → `translation`.
* - Otherwise → `content` (English/Swedish HTML + English executive-brief source).
*
* Files outside the ownership surface (\`news/*.html\` and
* \`analysis/daily/(any)/executive-brief(_lang).md\`) are ignored for detection.
*
* Returns `null` if no ownership-surface files are present (caller should treat
* the check as a no-op pass).
*
* @param files - Array of repo-relative file paths to inspect
* @returns The inferred workflow category, or `null` if no surface files
*/
export function detectCategoryFromFiles(
files: readonly string[],
): WorkflowCategory | null {
let sawSurfaceFile = false;
for (const f of files) {
if (isExecutiveBriefTranslation(f)) return 'translation';
if (isEnglishExecutiveBriefSource(f)) {
sawSurfaceFile = true;
continue;
}
if (f.startsWith('news/') && f.endsWith('.html')) {
sawSurfaceFile = true;
const lang = extractLangFromPath(f);
if (lang && (TRANSLATION_LANGS as readonly string[]).includes(lang)) {
return 'translation';
}
}
}
return sawSurfaceFile ? 'content' : null;
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
fetch-depth: 1
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
fetch-depth: 1
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
fetch-depth: 1
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
fetch-depth: 1
Comment on lines +1586 to +1589
ref: ${{ steps.extract-base-branch.outputs.base-branch || github.base_ref || github.event.pull_request.base.ref || github.ref_name || github.event.repository.default_branch }}
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
fetch-depth: 1
@pethers
Copy link
Copy Markdown
Member

pethers commented May 16, 2026

@copilot apply changes based on the comments in this thread do not change lock files. generated when compiling

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

…ases, set equality

- Fix CodeQL shell injection: use execFileSync instead of execSync for git commands
- Fix CodeQL incomplete sanitization: loop stripFencesAndComments until stable
- Update file-ownership: per-type workflows own ALL news/*.html (all 14 langs)
- news-translate no longer owns any news/*.html — only executive-brief_<lang>.md
- Fix detectCategoryFromFiles: news/*.html no longer implies translation category
- Remove news/*.html from exec-brief-translation-checks.yml path trigger
- Add banned phrases: Decisions, Confidence, Key Takeaways, What Happened, What It Means
- Tighten dok_id/URL checks to set equality (flag extras, not just missing)
- Fix TRANSLATION_GUIDE.md: remove conflicting "exactly two" vs "all 14" statement
- Update tests to match new ownership model (all 38 ownership tests pass)
- Full test suite: 5845 passed, 0 failures

Agent-Logs-Url: https://github.com/Hack23/riksdagsmonitor/sessions/1e32bcff-0fbe-41ef-8740-736f3a78c44e

Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 16, 2026

@copilot apply changes based on the comments in this thread do not change lock files. generated when...

Applied all review feedback in 8a9df66f (no lock files touched):

  • CodeQL fixes: execFileSync replaces shell-interpolated execSync; stripFencesAndComments loops until stable.
  • Ownership model: per-type workflows now own ALL news/*.html (14 langs); news-translate only owns executive-brief_<lang>.md. Updated validator, detectCategoryFromFiles(), tests, and removed news/*.html from the PR-check path trigger.
  • Banned phrases: added "Decisions", "Confidence", "Key Takeaways", "What Happened", "What It Means".
  • Set equality: dok_id and URL checks now flag both missing AND extra values.
  • TRANSLATION_GUIDE.md: removed conflicting "exactly two rendered files" wording; clarified all 14 HTML are emitted by per-type workflows.

Full test suite: 5845 passed, 0 failures.

@pethers pethers requested a review from Copilot May 16, 2026 10:16
@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 40 out of 40 changed files in this pull request and generated 21 comments.

Comment on lines +142 to +148
if ! npx tsx scripts/validate-executive-brief-translations.ts --source "$src" --soft; then
FAIL=1
fi
done

# `--soft` keeps the per-source command exit code green so we can
# collect every failure in one report. Convert to a hard failure now.
Comment thread scripts/validate-file-ownership.ts Outdated
Comment on lines +253 to +276
// Parse flags: --files <comma-list>, --files-from <path|->, --category <c|t>, plain positional category.
let filesArg: string | undefined;
let filesFromArg: string | undefined;
let categoryArg: WorkflowCategory | undefined;
for (let i = 0; i < args.length; i++) {
const a = args[i];
if (a === '--files' && args[i + 1]) {
filesArg = args[++i];
} else if (a === '--files-from' && args[i + 1]) {
filesFromArg = args[++i];
} else if (a === '--category' && args[i + 1]) {
categoryArg = args[++i] as WorkflowCategory;
} else if (a === 'content' || a === 'translation') {
categoryArg = a;
} else if (a === '--help' || a === '-h') {
console.log(
'Usage:\n' +
' validate-file-ownership.ts <content|translation> # validate git working tree\n' +
' validate-file-ownership.ts --files <a.md,b.md> [--category <c|t>]\n' +
' validate-file-ownership.ts --files-from <path|-> [--category <c|t>]\n' +
'\nIf --category is omitted with --files / --files-from, it is auto-detected:\n' +
' any executive-brief_<lang>.md OR non-EN/SV news/*.html -> translation\n' +
' otherwise -> content',
);
Comment on lines +149 to +154
/** Count fenced code blocks (any info string). */
export function countCodeFences(md: string): number {
const matches = md.match(/^```/gm);
// Each fence is one of opening/closing; divide by 2.
return matches ? Math.floor(matches.length / 2) : 0;
}
Comment on lines +194 to +198
/** Extract the trailing `<!-- source-sha: <40-hex> -->` marker, or null if missing/malformed. */
export function extractSourceShaMarker(md: string): string | null {
const match = md.match(/<!--\s*source-sha:\s*([0-9a-f]{40})\s*-->/i);
return match?.[1] ?? null;
}
Comment on lines +20 to +27
* - fenced-code-block count parity (±0),
* - Mermaid fenced-block count parity (±0),
* - dok_id reference preservation (set equality, source ⊆ translation),
* - external URL preservation (set equality, source ⊆ translation),
* - RTL marker present for `ar` / `he`,
* - trailing `<!-- source-sha: <40-hex> -->` marker present and well-formed,
* - no banned English BLUF phrases in non-English files,
* - top-level word count within ±25% of the source.
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
fetch-depth: 1
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
fetch-depth: 1
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
fetch-depth: 1
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
fetch-depth: 1
token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
persist-credentials: false
fetch-depth: 0
fetch-depth: 1
@pethers
Copy link
Copy Markdown
Member

pethers commented May 16, 2026

@copilot apply changes based on the comments in this thread

@github-actions
Copy link
Copy Markdown
Contributor

🔍 Lighthouse Performance Audit

Category Score Status
Performance 85/100 🟡
Accessibility 95/100 🟢
Best Practices 90/100 🟢
SEO 95/100 🟢

📥 Download full Lighthouse report

Budget Compliance: Performance budgets enforced via budget.json

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 16, 2026

@copilot apply changes based on the comments in this thread

Addressed in 8d15dd3: the PR gate now hard-fails validation drift, file-ownership CLI help and aliases match behavior, malformed fences and non-trailing source-sha markers are rejected, worklist wording is repo-relative, and generated lock-file deltas are reverted. Targeted validator tests, ESLint, and CodeQL review passed.

@pethers pethers merged commit 854cf4c into main May 16, 2026
18 checks passed
@pethers pethers deleted the copilot/update-news-translate-workflow branch May 16, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agentic-workflow Agentic workflow changes ci-cd CI/CD pipeline changes dependencies Dependency updates documentation Documentation updates i18n Internationalization/localization news News articles and content generation refactor Code refactoring size-l Large change (250-1000 lines) size-xl Extra large change (> 1000 lines) testing Test coverage translation Translation updates workflow GitHub Actions workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants