brief.md sibling tables — derived state lives in DB, not in the file
brief.md never gets mutated by the system. Derived data — asset versions, publish-verify state, auto-publications — lives in DB sibling tables that join to the brief by stable identifier and merge at render time.
Implementers building tools that mutate brand state need a clean separation between operator-authored brief.md and system-derived data.
The non-mutation principle
brief.md is operator-authored. The system reads it. The system never writes back to it. Any data the system needs to track that changes faster than the brief — published asset versions, last-verified state, auto-generated publication entries — lives in a sibling table keyed by brand identifier. At render time, the brief and the sibling tables join to produce the operator-facing view.
Why this matters
Mutating brief.md from the system breaks operator control. The brief is the source of truth; if the system writes back, the operator no longer has a single canonical artifact. Sibling tables preserve the principle that the operator owns the brand context outright. The system's view of the brand is a derivation; it is not authoritative.
Sibling table examples in PRAPI
`Marketing_Briefs` mirrors the canonical brief.md from Git into Azure SQL for join-friendly queries — but Git stays canonical. `BrandAutoPublications` tracks JWS signature events on each version. `BrandPublishVerify` tracks last-verified-at timestamps for downstream consumers. `Marketing_VoiceOverrides` audits per-call voice-validator overrides for drift detection. None of these mutate brief.md.
Render-time merge pattern
When PRAPI renders an operator-facing brand view, it (1) loads brief.md from Git-canonical, (2) loads sibling-table rows for the brand's identifier, (3) merges them into a unified view object, (4) renders. The merge is read-only on brief.md side. Edits flow back as Git PRs (per the "brief.md authoring is Git-canonical" rule); sibling-table writes flow through normal API endpoints.
PRAPI maintains 3+ sibling tables in marketing-agent (Marketing_Briefs, BrandAutoPublications, BrandPublishVerify) that all join to inputs/briefs/brands/{brand}/brand-brief.md by stable brand_id. None of those tables ever cause a write back to the markdown file.
FAQ
Why not just write to brief.md when something changes?
Two reasons. First, operator control — the operator authored the brief; the system shouldn't change it without explicit instruction. Second, brief.md changes velocity — operator changes are slow (positioning shifts), system-derived state changes fast (publish events, verify timestamps). Mixing the two timescales pollutes the canonical artifact.
How does PRAPI track asset versions then?
A sibling table (Asset_Versions or similar) tracks every asset version with timestamps, signatures, and the brand identifier. brief.md says "headshot: https://..."; the sibling table tracks "this URL was first published 2026-04-15, last verified 2026-05-08". The brief points; the sibling tracks state.
What if I want a system to update my brief automatically?
It can — by opening a PR against the canonical brief.md location. PRAPI's `/api/v1/briefs/*` authoring API does this for the bearer-authed flow: writes are explicit, auditable, and require the operator to merge. The non-mutation principle is "no silent writes," not "no automation."
How does this affect AI consumers?
AI consumers reading brief.md see the canonical, operator-authored version. Sibling-table data (publish state, asset versions) is a system-internal concern that consumers do not need to see. If a consumer needs derived state, the publisher renders it into the response separately.
Run brief.md in PRAPI.
PRAPI is the canonical brief.md implementation. Every brand in your portfolio gets its own brief.md, voice-validated drafts on every pitch, and Git-canonical authoring.
Sign in →