This directory holds 50 workflow files (22 standard .yml + 14 agentic Markdown sources + 14 compiled .lock.yml siblings) that power Riksdagsmonitor's CI/CD, security, data pipeline, agentic news generation, and monitoring.
Canonical long-form workflow reference:
WORKFLOWS.mdat the repository root — version matrices, Mermaid pipeline diagrams, ISMS control mapping, troubleshooting, and KPIs. Agentic workflow contract (imports, analysis gate, 23-artifact baseline):.github/prompts/README.md.
| File kind | Count | Notes |
|---|---|---|
Standard GitHub Actions (*.yml, not *.lock.yml) |
22 | Run natively on the GitHub Actions runner |
Agentic workflow sources (news-*.md) |
14 | Authored in Markdown with gh-aw frontmatter + prompt imports |
Agentic workflow compiled lock files (news-*.lock.yml) |
14 | Auto-generated by compile-agentic-workflows.yml — these are what actually execute |
| Total | 50 | Verify with `ls .github/workflows/ |
Only the compiled .lock.yml files run. The .md sources are the source of truth and are reviewed in PRs; lock files are regenerated via the gh aw compile CLI.
| File | Trigger | Purpose |
|---|---|---|
codeql.yml |
Push, PR, weekly | CodeQL SAST — javascript-typescript matrix |
dependency-review.yml |
Pull requests | SCA gate — blocks PRs on critical/high vulnerabilities |
scorecards.yml |
Push to main, weekly |
OpenSSF Scorecard supply-chain assessment |
setup-labels.yml |
Manual dispatch | Repository label management (.github/labeler.yml source) |
labeler.yml |
Pull requests | Auto-label PRs from .github/labeler.yml patterns |
| File | Trigger | Purpose |
|---|---|---|
javascript-testing.yml |
Push/PR on TS/JS/HTML/config | TypeScript type-check + Vitest (2 890 tests) + Vite build |
jsdoc-validation.yml |
Manual dispatch | TypeDoc generation + coverage report |
quality-checks.yml |
Push/PR to main |
ESLint + HTMLHint + linkinator (parallel jobs) |
knip.yml |
Push/PR to main |
Knip dead-code detector — blocks on unused files / dependencies / binaries / duplicate exports; reports unused exports & types informationally |
translation-validation.yml |
Push/PR on HTML | 14-language completeness + RTL + hreflang |
test-dashboard.yml |
Push/PR on dashboards | Cypress E2E for dashboard pages |
test-homepage.yml |
Push/PR on homepage | Cypress E2E for the 14 index*.html homepages |
test-news.yml |
Push/PR on news/** |
Cypress E2E for news article pages |
| File | Trigger | Purpose |
|---|---|---|
release.yml |
Tag v*, manual |
SLSA provenance + SBOM + dual deploy (S3 + GitHub Pages) |
deploy-s3.yml |
Push to main |
AWS S3 sync + CloudFront invalidation via OIDC |
lighthouse-ci.yml |
Push/PR, weekly | Lighthouse CI: performance, a11y, SEO, best practices |
| File | Trigger | Purpose |
|---|---|---|
update-cia-csv-data.yml |
Nightly 03:30 UTC, manual | Refresh every tracked data/cia/** + cia-data/** CSV from upstream Hack23/cia; refresh production-stats.json; inject counts into 14× index*.html; open a single PR on changes |
Each agentic workflow is a pair: an authored .md source + a compiled .lock.yml. The source imports bounded-context prompt modules from .github/prompts/. The compiled lock file is hardened (SHA-pinned actions, egress firewall, five-layer safe-outputs) and is what GitHub Actions actually runs.
| # | Source (.md) |
Lock (.lock.yml) |
Schedule | Primary MCP data |
|---|---|---|---|---|
| 1 | news-committee-reports.md |
news-committee-reports.lock.yml |
Mon–Fri 04:00 UTC | get_betankanden, search_voteringar, search_anforanden, get_propositioner |
| 2 | news-propositions.md |
news-propositions.lock.yml |
Mon–Fri 05:00 UTC | get_propositioner, search_dokument_fulltext, search_anforanden |
| 3 | news-motions.md |
news-motions.lock.yml |
Mon–Fri 06:00 UTC | get_motioner, search_dokument_fulltext, search_anforanden |
| 4 | news-interpellations.md |
news-interpellations.lock.yml |
Mon–Fri 07:00 UTC | get_interpellationer, search_anforanden, get_calendar_events |
Aggregation & prospective workflows (Tier-C, 23-artifact baseline; year-ahead gate-blocking = 24, mandated = 26; election-cycle gate-blocking = 28)
| # | Source (.md) |
Lock (.lock.yml) |
Schedule | Purpose |
|---|---|---|---|---|
| 5 | news-realtime-monitor.md |
news-realtime-monitor.lock.yml |
Mon–Fri 10:00 + 14:00 UTC, weekends 12:00 | Breaking events, urgency classification |
| 6 | news-evening-analysis.md |
news-evening-analysis.lock.yml |
Mon–Fri 18:00, Sat 16:00 UTC | Daily parliamentary pulse, coalition cohesion |
| 7 | news-week-ahead.md |
news-week-ahead.lock.yml |
Fri 07:00 UTC | Prospective week preview; IMF WEO T+5 economic outlook |
| 8 | news-month-ahead.md |
news-month-ahead.lock.yml |
1st of month 08:00 UTC | Monthly legislative pipeline + pinned IMF projection vintage |
| 9 | news-quarter-ahead.md |
news-quarter-ahead.lock.yml |
1st + 15th of month 09:00 UTC | 90-day parliamentary-season + Riksbank/SCB calendar; long-horizon-forecasting × 1.7 |
| 10 | news-year-ahead.md |
news-year-ahead.lock.yml |
5 Jan + 5 Jul 09:00 UTC | 365-day annual outlook anchored in IMF WEO Apr/Oct vintage; PESTLE gate-blocking (LH-4); wildcards + SWOT mandated by registry; × 2.0 |
| 11 | news-election-cycle.md |
news-election-cycle.lock.yml |
workflow_dispatch (cron 0 9 13 3,9 * declared but disabled until runtime measured) |
Full 4-year mandate; current Tidö + next post-2026 cycle; 28-artifact contract (23 + 5 blocking supplementary via LH-4 + LH-5); × 2.5 |
| 12 | news-weekly-review.md |
news-weekly-review.lock.yml |
Sat 09:00 UTC | Week-over-week trends, throughput metrics |
| 13 | news-monthly-review.md |
news-monthly-review.lock.yml |
28th 10:00 UTC | Monthly retrospective, party productivity rankings |
| # | Source (.md) |
Lock (.lock.yml) |
Schedule | Purpose |
|---|---|---|---|---|
| 14 | news-translate.md |
news-translate.lock.yml |
Daily 09:00 + 14:00 + 19:00 UTC | Translate analysis/daily/**/executive-brief.md into executive-brief_<lang>.md for the 13 non-English target languages (default batch: 3 sources × 13 languages = 39 files/run) |
Every news workflow imports the bounded-context prompt modules in this exact order (full contract in .github/prompts/README.md):
../prompts/00-base-contract.md— role, ethics, GDPR/ISMS, AI-FIRST rule../prompts/01-bash-and-shell-safety.md— AWF-safe shell patterns, UTF-8../prompts/02-mcp-access.md— MCP server inventory + health gate../prompts/03-data-download.md— download pipeline, manifest../prompts/04-analysis-pipeline.md— methodologies, templates, 23 required artifacts (Family A–D), Pass 1 + Pass 2../prompts/05-analysis-gate.md— single blocking gate — no article until it passes../prompts/06-article-generation.md— article sections, banned patterns, visualisation, translations../prompts/07-commit-and-pr.md— stage → commit → exactly onecreate_pull_request- (Tier-C workflows only)
../prompts/ext/tier-c-aggregation.md— depth multipliers, cross-type synthesis, higher article floor (same 23 artifacts)
Every news workflow declares the same tool & runtime surface for parity, resilience, and full gh-aw v0.74.3 capability coverage:
| Field | Value | Purpose |
|---|---|---|
runtimes.node.version |
"26" |
Pinned Node 26 for IMF CLI + render scripts |
engine.id / engine.model |
copilot / claude-opus-4.8 (13 analysis/article workflows); claude-sonnet-4.6 (news-translate only) |
Opus reasoning model for the 23-artifact analysis pipeline; the high-volume translation fan-out keeps the faster Sonnet model. (Sonnet was the repo-wide baseline through v0.74.3; GPT-5.4 / GPT-5.4-mini eligibility resolved upstream per release notes #31695 + #32197 but not yet A/B-tested here.) |
engine.mcp.session-timeout |
1h |
Was added in gh-aw v0.71.3 and rejected by MCP Gateway v0.3.1. v0.74.3 lock files now ship MCP Gateway v0.3.9; re-acceptance has not yet been validated on this repo, so the field stays removed until verified. |
tools.github.toolsets |
[all] |
Full GitHub MCP surface (issues, PRs, repos, code-search, actions, releases, discussions, …); see github-tools.md |
tools.bash / tools.edit / tools.web-fetch / tools.agentic-workflows |
enabled | Full local tool surface; web-fetch reaches non-MCP public sources (statskontoret.se, riksdagsmonitor.com) through the AWF firewall |
tools.cache-memory |
keyed by news-${workflow}-${article_date}; best-effort cache persistence aligned with a 14-day recovery window |
Resilience knob — analysis artifacts persisted at /tmp/gh-aw/cache-memory/; may be restored on the next run if the previous PR failed and the cache entry is still available (see 07-commit-and-pr.md §Cache-memory recovery) |
tools.playwright |
enabled in news-evening-analysis + news-realtime-monitor only |
Live HTML validation for tier-C aggregation runs |
features.mcp-gateway |
true |
Routes all MCP traffic through the gh-aw mcp-gateway (single audit point) |
timeout-minutes |
60 |
Job ceiling measured from job start; agent phases target completion by agent minute 40, PR by agent minute 42 (hard 45) to reserve setup/safe-output headroom |
safe-outputs.create-pull-request.fallback-as-issue |
true (explicit) |
If org disables Actions PR creation, fall back to an issue + branch link instead of failing |
safe-outputs.create-pull-request.if-no-changes |
warn |
Empty patches emit a warning instead of failing the run (e.g. duplicate-date dispatches) |
network.allowed |
node, github, defaults + explicit Docker Hub hosts (docker.io, registry-1.docker.io, auth.docker.io, production.cloudflare.docker.com) + IMF/SCB/Riksdag/Statskontoret/site domains |
Ecosystem identifiers preferred per upstream network.md. The broad containers ecosystem (which would also permit ghcr.io, quay.io, gcr.io, mcr.microsoft.com, pkgs.k8s.io, …) is deliberately omitted to keep least-privilege egress; only the minimal Docker Hub hosts actually required to resolve node:26-alpine for the SCB and World Bank MCP servers are enumerated. Any future switch to ghcr.io, quay.io, or other registries must add the specific hosts and be reviewed against the egress allowlist policy before merge. |
permissions |
contents: read, issues: read, pull-requests: read, actions: read, discussions: read, security-events: read, copilot-requests: write |
Least-privilege agent token; write capabilities live exclusively in the safe-outputs runner job. copilot-requests: write enables GitHub Actions token-based Copilot inference (COPILOT_GITHUB_TOKEN: ${{ github.token }} in the compiled lock file) so the Copilot engine no longer needs a personal-access-token secret. Requires org-level centralized Copilot billing — see gh-aw billing reference. |
gh aw compile reports one expected, reviewed warning per news-*.md workflow (14 total). Compilation is green — 0 error(s) — and these warnings are an accepted design decision, not a defect:
⚠ Warning: secrets expressions detected in 'steps' section may be leaked to the agent job.
Found: ${{ secrets.IMF_SDMX_SUBSCRIPTION_KEY }}.
Consider moving operations requiring secrets to a separate job outside the agent job.
Why it is expected. Every news workflow forwards secrets.IMF_SDMX_SUBSCRIPTION_KEY to the news-prewarm composite action via a with: input in the steps: section. The key is deliberately propagated into the agent job (exported to $GITHUB_ENV, then inherited by the firewalled agent shell via awf --env-all) because the agent's bash tool makes live authenticated IMF SDMX 3.0 calls (tsx scripts/imf-fetch.ts sdmx … for IFS / BOP / DOTS / GFS_COFOG / MFS_IR / PCPS / ER). This is the documented economic-data architecture — see .github/aw/ECONOMIC_DATA_CONTRACT.md, .github/prompts/02-mcp-access.md, and analysis/imf/agentic-integration.md.
gh-aw emits this warning unconditionally for any secrets.* reference in an injected step section when strict: false (every news workflow sets strict: false to permit the trusted custom MCP egress domain riksdag-regering-ai.onrender.com). In strict mode a with: binding on a uses: step would instead be treated as a "safe binding" and clear the warning, but strict mode also forbids the custom network domain, job write permissions, and the bash wildcard tools these workflows require — so flipping strict is not viable.
Why it is safe. The key is masked in logs (::add-mask:: inside news-prewarm) and registered in gh-aw's GH_AW_SECRET_NAMES redaction list (the compiled Redact secrets in logs step), so it is scrubbed from artifacts and run logs. It is the only non-engine secret in the agent job and is required for the workflow's core function.
If you ever need a zero-secrets-in-agent posture (gh-aw "Layer 2"), the warning can be removed legitimately only by moving all authenticated SDMX fetching into a separate pre-fetch job that uploads data/imf-*.json artifacts for the agent to consume — a re-architecture that retires agent-side live SDMX calls and requires coordinated updates to the IMF contract and prompts.
Tracking grid for the features called out in the gh-aw v0.74.3 release notes. All 14 news-*.lock.yml files compile against v0.74.3 today; the rows below classify each new capability as adopted, planned (follow-up PR), or non-applicable.
| v0.74.3 feature | Status | Notes |
|---|---|---|
Glob patterns in add-labels safe outputs (#32022) |
Planned | Replace hard-coded labels: [agentic-news, analysis-data] with agentic-* glob to allow agent-driven self-labelling of agentic-tier-c, agentic-long-horizon, agentic-election-cycle. |
| Issue Fields in safe outputs (#30846) | Planned | Move severity / horizon-band / election-cycle metadata off labels into issue fields on uptime-monitor and PIR roll-forward issues. |
Stable slash_command / label_command triggers (#32348) |
Planned | Add /regen-news <date> <type> and regen-news label triggers to news-propositions / news-motions / news-committee-reports / news-interpellations. |
aw-compat codemods (#32341): run-expression hoisting, engine pinning, toolset-permission synthesis |
Adopted | Verified clean: gh aw fix (dry-run) reports "No fixes needed" against all 14 news workflows on v0.74.3 (validated 2026-05-15). gh aw fix --list-codemods shows the highest registered codemod targeting our migration range introduced in v0.68.4 — there are no v0.71→v0.74 codemods that apply. |
| Warn-mode threat guardrails for safe outputs (#32399) | Planned | Tighten safe-outputs.threat-detection.continue-on-error: true → warn-mode with structured warning ingested into analysis-quality.md. |
| Agent compatibility matrix and validation (#32396) | Planned | Declare agent-compatibility: matrix: claude-sonnet-4.6 accepted; gpt-5.4, gpt-5.4-mini opt-in after A/B test. |
| Enhanced OTel spans + Grafana MCP shared component (#32425, #32340) | Planned | Add Grafana MCP to news-evening-analysis + news-realtime-monitor; pipe agent-phase timings and gate-pass/fail counts. |
excessivefuncparams linter (#32402) |
Planned | Run against scripts/imf-fetch.ts, scripts/aggregate-analysis.ts, scripts/render-articles.ts; refactor opportunity, non-blocking. |
experiments.* valid in runtime-import expressions (#32375) |
Planned | Expose experiments.tier_c_compression, experiments.lh_pestle_blocking, experiments.cycle_rollover_window. |
MCP Gateway upgrade to ghcr.io/github/gh-aw-mcpg:v0.3.9 |
Adopted | Now present in every news-*.lock.yml manifest. Field-level effects (e.g. engine.mcp.session-timeout re-acceptance) still pending re-validation. |
| GPT-5.4 / GPT-5.4-mini fixes (#31695, #32197) | Available | Models now compatible; not yet A/B-tested against claude-sonnet-4.6 on this repo. |
gh aw compile --staged (v0.74.2) |
Planned | Adopt in compile-agentic-workflows.yml for PR previews of the compiled .lock.yml. |
| REST API for agent session task creation (v0.74.2) | Adopted | Default in compiled .lock.yml files. |
Higher default max-runs (100 → 500, v0.74.2) |
Adopted | Inherited from compiler defaults; no explicit cap needed for current scheduling fan-out. |
Tracker: Article-Generation.md §"Modularization roadmap" carries the per-feature follow-up PR titles.
| File | Trigger | Purpose |
|---|---|---|
compile-agentic-workflows.yml |
Push/PR touching news-*.md, manual |
Run gh aw compile → regenerate .lock.yml; enforce firewall + safe-outputs + SHA-pinning |
agentics-maintenance.yml |
Scheduled + manual | Hygiene of the agentic environment: stale branch cleanup, secret-rotation hooks, runtime-cache eviction |
copilot-setup-steps.yml |
Push, manual | Bootstrap GitHub Copilot coding-agent environment for this repo |
| File | Trigger | Purpose |
|---|---|---|
uptime-monitor.yml |
Every 15 minutes | Availability checks for all 14 language homepages; auto-creates/closes GitHub issues on outage/recovery; validates HSTS/CSP/X-Frame-Options headers |
flowchart LR
subgraph "⏰ Cron"
C1[Every 15 min → uptime-monitor]
C2[Nightly 03:30 UTC → update-cia-csv-data]
C3[Mon-Fri 04:00-18:00 → news-* article + analysis]
C4[Daily 09 + 14 + 19 UTC → news-translate (exec-brief markdown)]
C5[Fri 07:00 → news-week-ahead]
C6[Sat 09:00 → news-weekly-review]
C7[28th 10:00 → news-monthly-review]
C8[1st 08:00 → news-month-ahead]
C9[1st + 15th 09:00 → news-quarter-ahead]
C10[5 Jan + 5 Jul 09:00 → news-year-ahead]
C11[Weekly → codeql + scorecards + lighthouse-ci]
end
subgraph "🔀 Event"
E1[push/PR → quality-checks + knip + javascript-testing + translation-validation + codeql + test-*]
E2[Tag v*.*.* → release]
E3[push main → deploy-s3]
E4[PR → dependency-review + labeler]
end
subgraph "👆 Manual"
M1[workflow_dispatch → any workflow]
M2[news-election-cycle → dispatch-only initially, until runtime measured]
end
style C3 fill:#0a0e27,stroke:#00d9ff,color:#e0e0e0
style E2 fill:#1a1e3d,stroke:#ffbe0b,color:#e0e0e0
Every workflow in this directory implements defence-in-depth — see WORKFLOWS.md §"Workflow Security Architecture" for the full matrix.
| Control | How it's enforced |
|---|---|
step-security/harden-runner |
First step of every job; egress audit/allow-list |
SHA-pinned uses: |
100 % coverage — any third-party Action pinned to commit SHA |
Least-privilege permissions: |
Default contents: read; only required scopes added |
| OIDC for AWS | id-token: write + role-to-assume (no long-lived keys) |
| Five-layer safe outputs (agentic) | Sanitise → schema-validate → policy-check → human-review → merge |
| Squid + iptables egress firewall (agentic) | Only domains in network.allowed: reach the internet |
| I want to… | Read |
|---|---|
| Understand a specific pipeline stage end-to-end | WORKFLOWS.md |
| Author or modify an agentic news workflow | .github/prompts/README.md + .github/skills/gh-aw-workflow-authoring/ |
| Understand how safe outputs and the firewall work | .github/skills/gh-aw-safe-outputs/ + .github/skills/gh-aw-firewall/ |
Compile .md → .lock.yml locally |
Run gh aw compile .github/workflows/<name>.md (workflow compile-agentic-workflows.yml does this in CI) |
| See ISMS control mapping | WORKFLOWS.md §"ISMS Compliance Mapping" |
| Trace the analysis artifact contract | analysis/README.md + analysis/methodologies/README.md + analysis/templates/README.md |
📋 Document owner: CEO | 🏷️ Classification: Public | 🔄 Review cycle: Quarterly