Skip to content

2026-05-10 — Phase 8: server-side governance audit (MR-4, MR-7, MR-10)

Date: 2026-05-10 Status: closed Supersedes: none Superseded-by: none — current

petrova.governance.audit was a v0 stub returning status: "not-run" with the note that real MR audits “run via the petrova CLI; server-side audit is v1.” The dashboard’s /console/governance consequently rendered an empty page until today’s interim fix that grouped registry+state by phase. The MR rules themselves are mechanically encoded in core/templates/.github/workflows/docs-invariants.yml — every consumer repo runs them in CI, but the control plane had no aggregate view.

Implement a server-side AuditSource in host/src/sources/audit.ts that walks each registered repo’s docs/decisions/ and docs/findings/ via Octokit (App auth, same path as GithubEvaSource and ActsSource) and runs three MR checks per repo. Results are returned by petrova.governance.audit as one row per (slug, mr). Dashboard renders a repo × MR grid with a per-finding detail table.

Initial check set:

MRWhat is checked
MR-4Every docs/decisions/*.md matches YYYY-MM-DD-<slug>.md; every docs/findings/*.md matches YYYYMMDD[-HHMM]-<slug>.md.
MR-7Every decision doc with **Status:** superseded carries a non-empty **Superseded-by:** link.
MR-10Every phase-N-(close|complete) decision has a corresponding verification-round artefact in docs/findings/.

Status values: pass, warn (non-blocking, e.g. MR-10’s heuristic miss), fail (blocking, e.g. MR-4 filename violation), skip (couldn’t run — repo unreachable, no docs dir).

  • Lift the consumer-side workflow into the control plane verbatim (Python validators in docs-invariants.yml). Rejected: that workflow runs over a checked-out repo with all branches, which doesn’t fit the host’s per-request remote-fetch model. Re-implementing the same rules in TypeScript over Octokit reads is cheaper and matches the rest of the host (GithubEvaSource, ActsSource).
  • Fold audit results into petrova.context. Rejected: audit is expensive (multiple Octokit calls per repo, body fetches for MR-7); the /context bundle is on the request-latency-critical path. Audit gets its own tool with a 5-minute in-memory cache.

For code:

  • New host/src/sources/audit.ts with the three checks and a per-call cache.
  • governance.audit rewritten — now returns {scanned_at, rows[]} instead of the v0 single-row stub.
  • host/tests/tools/governance.test.ts updated to match the new shape.
  • /console/governance rebuilt as a repo × MR matrix + findings table.

For docs:

  • This doc.

For in-flight phases:

  • Phase 6 (state freshness) is complementary, not blocking.

For invariants:

  • No MR-N changes. The audit enforces MR-4/7/10 from the control plane; the rules themselves live in META-RULES.md.
  • core/templates/.github/workflows/docs-invariants.yml — the consumer-side reference implementation.
  • host/src/sources/audit.ts — the server-side translation.
  • Earlier governance dashboard fix: 1e2c53b.
  • Subagent: Claude Code (main direct-push under standing approval)
  • Human: alex@devarno.com — 2026-05-10