2026-04-25 — Post-merge audit cron: closed-issue + weekly changelog drift
Adds two GitHub Actions workflows that audit changelog hygiene. closed-issue-audit runs daily at 06:17 UTC and flags any issue closed as completed without a matching changelog closes: reference. changelog-audit-weekly runs Mondays at 09:00 UTC and writes a 7-day summary to the workflow run page. Both default to DRY_RUN=true for the first 7 days; flip to false on 2026-05-02 once shake-out is done. Auto-creates the missing-changelog and no-changelog labels on first run.
What changed
.github/workflows/closed-issue-audit.yml— daily cron at 06:17 UTC that scans recently closed issues and flags any closed-as-completed issue lacking a matching changelogcloses:reference..github/workflows/changelog-audit-weekly.yml— Monday 09:00 UTC cron that writes a 7-day audit summary to the workflow run page.apps/docs/content/docs/changelog/2026-04-25-audit-cron.mdx— this entry.apps/docs/content/docs/changelog/meta.json— pages array updated to include the new entry at top.
Why
This closes the SSOT-discipline loop. docs-guard.yml (PR #650) blocks PRs that don't add a changelog entry. The inverse failure mode — issue closed without a changelog mention — was previously invisible. These two workflows surface that drift on a fixed cadence so it doesn't accumulate silently.
The daily job catches drift within 25 hours of close. The weekly job aggregates and produces a digest you can scan in one go.
Cadence rationale
- Daily 06:17 UTC — off-zero minute. Cron pulses at
:00are heavily load-aligned across global infrastructure;:17avoids that congestion and gives the runner faster scheduling. The hour06UTC lands before most timezones' workday so any flagged issues are visible at start-of-day. - Mondays 09:00 UTC — fixed weekly checkpoint. Mondays at the top of the hour is fine here because it fires once per week, not many-fires-per-hour, so load-alignment doesn't compound.
Permissions
Both workflows use the default GITHUB_TOKEN with this scope:
issues: write— to add labels and post comments on flagged issues (only whenDRY_RUN=false).contents: read— to checkout the changelog directory.pull-requests: read— defensively, for future cross-checking if needed.
No PAT. No write access to anything beyond issues. The GITHUB_TOKEN is short-lived (per-run) and scoped by the permissions: block, not org-wide.
DRY_RUN window
Both workflows ship with DRY_RUN: 'true' hard-coded in the job env block. For the first 7 days after merge, the daily audit will log what it would do but won't actually label or comment on anything. This is the shake-out window: any false positives surface in the run logs harmlessly.
After 2026-05-02, someone with repo write access edits closed-issue-audit.yml and changes DRY_RUN: 'true' → 'false'. From that point on the audit will write labels and comments for real.
The closed-issue-audit workflow also exposes a workflow_dispatch input so you can manually run with dry_run: false (override) or dry_run: true (force) regardless of what's in the env block.
Labels
The daily workflow auto-creates two labels on first non-dry-run execution (idempotent — uses getLabel then falls through to createLabel only on 404):
missing-changelog(colorf4b400, amber) — applied to issues flagged by the audit.no-changelog(colorededed, neutral grey) — applied manually when an issue is intentionally exempt (revert, typo fix, out-of-band, etc.). The audit skips issues already carrying this label.
Both labels are safe to re-create across runs because the workflow checks for existence first.
What's NOT in scope
- The audit only inspects
apps/docs/content/docs/changelog/*.mdxfrontmattercloses:arrays. It does not parse PR body text, commit messages, orCloses #Nmentions in those places. If a PR closes an issue via commit message but never adds a changelog entry, the audit will still flag the issue — which is the intended behavior, since the SSOT for shipped work is the changelog. - The audit does not modify, delete, or reorder changelog entries. It only flags issues.
- The audit does not post anything to issues during the 7-day dry-run window. All output is in workflow run logs only.
2026-04-25 — R-9 voice-agent Dockerfile fix + turn-detector image-bake
Fixes the voice-agent multi-stage build (deadsnakes PPA + ensurepip bootstrap + posix_local COPY path) and bakes the LiveKit turn-detector ONNX model into the image so docker compose --force-recreate no longer loses the runtime download. Closes R-9 #669, #527, RT-2 #674.
2026-04-25 — Repo root .md cleanup: PLAN/SPRINT/LAUNCH-AUDIT migrated, COMMIT discarded
Migrated three durable root-level markdown documents into apps/docs/content/docs/operations/ and discarded one session-scoped file. Repo root now holds only CLAUDE.md, README.md, configs, and .gitignore for *.md.