ADR-067: Playbooks as a unified primitive
Status: Accepted Date: 2026-04-23 Related: ADR-065 (persona-aware-ia-and-niceties), ADR-066 (placeholder — successor to ADR-065 niceties framework), ADR-059 (project-first-ia), ADR-060 (catalog-driven-infrastructure)
Decision (one sentence)
A Playbook is a unified primitive — one schema, one front-matter, one
catalogue — with a kind: discriminator that selects kind-specific
extension fields; every existing shape of operational procedure (journey,
experiment, incident response, service runbook, release flow, onboarding
flow) is retrofitted onto this primitive.
Context
Six distinct artifacts, written by different humans at different times, are drifting into the same shape:
| Artifact | Current home | Status today |
|---|---|---|
| Journeys (red routes per persona) | ai-frontend/docs/journeys/ |
In flight — directory drafted, 00-overview.md being written; not yet merged at 2026-04-23 |
| Experiments | ai-research/experiments/exp-N-slug/ + index at dark-factory/docs/specs/experiments-progress-plan.md |
316 numbered experiments shipped, each a self-contained shell script with a declared input/output contract (exp-315 Hetzner audit, exp-316 GitHub audit cited in the plan) |
| Incident responses | dark-factory/docs/incident-response-playbook.md (generic) + ad-hoc Slack threads |
Generic procedure exists; per-service paging / escalation lives nowhere formal |
| Service runbooks | dark-factory/docs/runbooks/ (sparsely populated), observability-runbook.md, security-runbook.md, disaster-recovery-runbook.md |
Mixed — some services have one, most don't; no shared shape |
| Release flows | gyrum-complete-pr is the release flow; the record of what was released, with what rollback, is scattered across PR descriptions and finding-journal entries |
Executable but not catalogued |
| Onboarding flows | Not yet modelled | A new developer's first-hour path is tribal knowledge |
Every one of the six fits the same four-part skeleton:
- Trigger — what event starts the procedure
- Steps — the ordered (or branching) set of actions
- Outcome — what "done" looks like, and how it's verified
- Retro / gaps — what went wrong, what's missing, what to sharpen next time
That coincidence is not noise. It is the evidence that these are not six kinds, they are six projections of one kind. Treating them as six separate kinds has a cost that is already visible:
- Cross-kind aggregation is impossible today. "Show me every
operational procedure owned by
@jonthat hasn't been reviewed in 90 days" requires six separate greps across six separate directories with six separate schemas — so it is never asked. - A runbook that quotes an experiment is a copy-paste link, not a typed reference. The experiments-progress-plan cites exp-315 / exp-316 as prose; if their IDs change, nothing warns the plan. Conversely, if a runbook is deleted, the dashboard does not notice the incident playbook that depended on it.
- Onboarding and release flows are load-bearing but invisible. The
gyrum developer loop (
gyrum-start-work → commit → gyrum-complete-pr) is a playbook in everything but name. It has no ID, no owner, no review cadence. It works because one person holds it in their head. - ADR-065's
/teamand Owner dashboards want a "gaps KPI" — what fraction of our operational procedures have a known gap? — and there is no primitive to count.
This ADR resolves the drift before the sixth kind (onboarding) is written from scratch in yet another shape.
Why not just keep tagging (Option B)?
Option B — agree on shared vocabulary (persona:, trigger:, tags:,
status:, owner:) across independently-schema'd files — is the
minimum-disruption move. It solves the discovery problem (you can
grep by persona) without the retrofit cost.
It loses three things:
- Typed references across kinds. If a journey can
related: [runbooks:sre-triage-alert], that's only true if the runbook's ID is typed and resolvable. Tag-level agreement gives you strings, not references. - A shared catalogue. "List everything
@jonowns, across kinds, with its last-reviewed date" requires one loadable index. Six directories with similar-but-not-identical front-matter resist a single index. - A shared review cadence. If each kind has its own staleness rules, the 90-day review becomes six policies. One primitive → one policy.
Option B is the right answer if we expected the six kinds to diverge over time. The evidence (common skeleton, cross-kind citations already appearing in prose) says the opposite: they are converging. We take Option A.
Decision
1. A Playbook is a Markdown file with typed YAML front-matter
Front-matter is the contract. Body is the human-readable content. Tooling consumes front-matter; humans read the body. Both live in one file so a playbook is never out-of-sync with its own index.
2. The schema (front-matter, required fields)
---
kind: journey | experiment | incident_response | service_runbook | release_flow | onboarding
id: sre-triage-alert # kebab-case, globally unique within kind
title: "SRE: first five minutes on an active alert"
persona: sre | dev | manager | owner | boss | none
owner: "@jon" # GitHub handle, single owner (groups are hell)
status: proposed | active | archived | superseded
trigger: "Alertmanager page to on-call phone"
success_metric: "Alert acknowledged within 5 min; mitigation started within 15 min"
tags: [alerting, on-call, first-response]
related:
- journeys:dev-review-inbound-pr # typed cross-reference: kind:id
- runbooks:alertmanager-debug
- adrs:049 # ADRs are referenced, never claimed as playbooks
created: 2026-04-23
last_reviewed: 2026-04-23
---
Field notes:
kindis the discriminator. Unknown values fail validation.idis kebab-case, alphanumeric, globally unique within its kind. Cross-kind collisions are allowed (runbook:focus≠journey:focus); references always carry the kind prefix.personareuses ADR-065's persona vocabulary exactly (dev | sre | manager | owner | boss) +nonefor persona-neutral playbooks. Adding a persona is an ADR-065 amendment, not a playbook schema change.owneris a single GitHub handle. Group ownership ("@platform-team") is rejected — groups don't respond to pings.statusgoverns the review cadence (§11) and the "gaps" KPI (§9).triggeris free-text but should be one sentence. It is the first thing a reader sees when grepping.success_metricis what "done" looks like. For a journey this is the red-route success condition; for an experiment it is the falsifiable outcome; for a runbook it is "service back to green".tagsare lowercase kebab-case. Unbounded vocabulary; the Owner dashboard surfaces the top-N.relateduses typedkind:idreferences. Validation: each reference resolves or CI fails. ADR references useadrs:NNN. References to non-playbook artifacts (a PR, a Slack thread) are string URLs underreferences:in the body, notrelated:.createdandlast_reviewedare ISO dates. The 90-day cadence (§11) readslast_reviewed.
3. Kind extensions — per-kind required body sections
Every playbook has the four skeleton sections — Trigger, Steps, Outcome, Retro / gaps — as H2 headings in the body. On top of that, each kind requires a kind-specific set of H2s:
| Kind | Required extension H2s | Rationale |
|---|---|---|
journey |
## Entry, ## Path, ## Exit, ## Gaps |
Matches the red-route vocabulary in the in-flight ai-frontend/docs/journeys/00-overview.md draft — entry is "where the persona starts", path is "what they click", exit is "what they walk away with", gaps is "what's broken today" |
experiment |
## Hypothesis, ## Method, ## Findings, ## Decision |
Matches the exp-N-slug structure in ai-research/experiments/; run-report.json auto-populates Findings on successful runs |
service_runbook |
## Symptoms, ## Diagnostics, ## Mitigations |
Matches the observability-runbook.md and security-runbook.md shape; mitigation is distinct from fix (short-term vs permanent) |
incident_response |
## Paging source, ## Escalation path, ## Comms |
Encodes who's paged, who's called if they don't answer, and what template goes in the customer-facing update |
release_flow |
## Gate stack, ## Rollback |
References docs/shared/gate-stack.md; rollback is the distinguishing feature (a release without a rollback plan isn't a release flow) |
onboarding |
## Start state, ## First-value step, ## Completion |
"First-value step" is the one thing the new person does in their first hour that proves the system works end-to-end |
All other H2s in the body are optional and author-chosen (Related reading, Decision log, Appendix). The required set is the floor, not the ceiling.
Per-kind extension notes:
journey. Entry is "what brought the persona here" — the URL they landed on, the notification they clicked, the question they asked. Path is the expected click-path (not the UI spec; the narrative). Exit is the "walk-away state" — what did they leave with? Gaps enumerates what a real user today would trip over, with enough specificity to become a ticket. The journey kind explicitly borrows the red route concept: a small number of paths the persona takes every day, not the long tail.experiment. Hypothesis is a falsifiable claim (not "we'll see what happens"). Method is the runnable script reference — for the ~316 existing experiments this is justrun-*.sh. Findings are the aggregatedrun-report.jsoninterpretation. Decision is what we changed as a result — "shipped a change", "filed an ADR", "rejected the hypothesis". An experiment with no Decision section is an experiment we learned nothing from.service_runbook. Symptoms are observable — log lines, metric patterns, user reports — not causes. Diagnostics bisect symptoms to causes using named commands (copy-pasteable, with expected output). Mitigations bring the service back to green without necessarily fixing the root cause. A runbook whose Mitigations section jumps straight to "rebuild the service" is a runbook that doesn't understand the service.incident_response. Paging source names the actual alerting channel (Alertmanager route, UptimeRobot webhook, customer email inbox). Escalation path is a ladder, not a list — primary, then secondary after N minutes, then tertiary after M. Comms is the exact template (public status-page prose, internal Slack prose, customer-support script). Incident-response playbooks that only say "notify stakeholders" are failing at their one job.release_flow. Gate stack referencesdocs/shared/gate-stack.mdas the canonical list of gates (lint/test/build/review/merge/deploy), with the playbook adding any kind-specific gates. Rollback is the required section that separates a release flow from a deploy script: every release flow explicitly documents how to undo itself, and within what time window, and with what data implications.onboarding. Start state is "what the new person has when they begin" — laptop, SSH key, GitHub access, nothing else. First-value step is the one action inside the first hour that produces a visible result (a merged PR, a running service, a passing test). Completion is the boundary condition — the new person has graduated from the playbook and is now operating independently. Onboarding playbooks are short; five steps is a lot.
4. File layout
Playbooks live next to the thing they describe, except for playbooks that are cross-cutting (spanning multiple projects / services), which live centrally.
gyrum-labs/ai-frontend/docs/journeys/
├── _index.yaml # auto-generated, see §6
├── 00-overview.md # (in flight) — canonical journey doc
├── dev-review-inbound-pr.md # kind=journey
├── sre-first-five-minutes.md # kind=journey
├── owner-weekly-scan.md # kind=journey
└── manager-release-readout.md # kind=journey
gyrum-labs/ai-research/experiments/
├── exp-315-hetzner-audit/
│ └── PLAYBOOK.md # kind=experiment, colocated with run-*.sh
└── exp-316-github-audit/
└── PLAYBOOK.md
gyrum-labs/dark-factory/docs/playbooks/
├── _index.yaml # cross-cutting catalogue
├── incident-response/
│ ├── alertmanager-page.md # kind=incident_response
│ └── data-loss.md
├── runbooks/
│ ├── alertmanager-debug.md # kind=service_runbook
│ ├── caddy-routing.md
│ └── observability-stack.md
├── release-flows/
│ └── gyrum-complete-pr.md # kind=release_flow (codifies the existing flow)
└── onboarding/
├── first-commit.md # kind=onboarding
└── first-review.md
Rules for where a playbook lives:
- Journeys live in
ai-frontend/docs/journeys/— they are intrinsically tied to the Platform UI persona routes (ADR-065). - Experiments live with their script at
ai-research/experiments/exp-N-slug/PLAYBOOK.md. The front-matter'sidmatches the directory slug. - Everything else cross-cutting lives under
dark-factory/docs/playbooks/<kind>/. Dark-factory is the meta-repo so cross-repo concerns belong there. - Per-service runbooks live with the service if the service owns
its own repo; else under
dark-factory/docs/playbooks/runbooks/. The front-matter'srelated:lists the service's catalog ID (ADR-060) so the two stay linked.
5. Typed references
related: entries are kind:id pairs. Validation rules:
- Every
kind:idmust resolve to a playbook file somewhere in the fleet. adrs:NNNresolves againstdark-factory/docs/decisions/NNN-*.md.- Unresolved references fail CI (loud, not silent). This is the "deleted runbook warns its dependents" property that prose links don't give us.
- Reverse lookup is free: a playbook's "who references me?" list is
a one-pass scan of every
_index.yaml.
References to non-playbook artifacts go in the body under ## References as plain Markdown links; related: is reserved for typed
fleet artifacts.
6. _index.yaml
Every playbook-bearing directory has an _index.yaml auto-generated
by scripts/regen-playbooks-index.sh (to be written as a follow-up).
The index is the load-bearing artifact for the (future) browser (§8)
and for cross-kind aggregation today.
Shape:
# _index.yaml — AUTO-GENERATED, do not edit by hand
generated: 2026-04-23T14:00:00Z
playbooks:
- kind: journey
id: dev-review-inbound-pr
path: dev-review-inbound-pr.md
title: "Dev: review an inbound PR"
persona: dev
owner: "@jon"
status: active
tags: [code-review, pull-request]
last_reviewed: 2026-04-23
gaps_count: 2
gaps_count is the number of items in the Gaps (or Retro/gaps)
section of the body — the KPI input for §9.
7. Mapping existing artifacts
This is a retrofit, not a greenfield. Existing content is mapped, not rewritten.
| Existing artifact | Becomes | Work required |
|---|---|---|
Journey drafts being authored at ai-frontend/docs/journeys/ (in flight as of 2026-04-23) |
kind: journey playbooks, one per red route |
Add front-matter; the red-route sections already match the required H2s |
ai-research/experiments/exp-N-slug/ |
kind: experiment playbook per directory — PLAYBOOK.md beside the run-*.sh |
316 directories; migrate in batches of ~50 per PR, auto-generated from existing run-report.json where possible |
dark-factory/docs/specs/experiments-progress-plan.md |
Stays as an index/narrative; stops being the primary description of each experiment. Each "exp-XXX" line in the plan becomes a one-line pointer to the playbook | Split: the plan keeps its narrative; per-experiment details move to the playbook |
dark-factory/docs/incident-response-playbook.md |
Split into one kind: incident_response playbook per incident type (alertmanager-page, data-loss, security-breach, etc.) |
Five playbooks, not one mega-doc; the mega-doc becomes an overview that links to them |
dark-factory/docs/runbooks/ + *-runbook.md at docs root |
Per-service kind: service_runbook playbooks under dark-factory/docs/playbooks/runbooks/ |
Rename + add front-matter; most existing runbooks already have symptoms/diagnostics/mitigations shape |
gyrum-complete-pr flow |
kind: release_flow playbook at dark-factory/docs/playbooks/release-flows/gyrum-complete-pr.md |
New file; codifies gate stack + rollback steps that are currently tribal |
| (None yet) | kind: onboarding playbooks |
New: first-commit.md and first-review.md are the starting set |
ADRs (dark-factory/docs/decisions/*.md) |
Not playbooks. ADRs are decisions; playbooks are operations. An ADR that changes on its own is broken; a playbook that changes on its own is being maintained. The two primitives stay disjoint. related: [adrs:NNN] is the bridge. |
None |
7a. Worked example — a full playbook
To ground the schema in a concrete artifact, here is the SRE journey playbook in full, exactly as it would land on disk:
---
kind: journey
id: sre-first-five-minutes
title: "SRE: first five minutes on an active alert"
persona: sre
owner: "@jon"
status: active
trigger: "Alertmanager page to on-call phone"
success_metric: "Alert acknowledged within 5 min; mitigation started within 15 min"
tags: [alerting, on-call, first-response]
related:
- runbooks:alertmanager-debug
- incident_response:alertmanager-page
- adrs:049
created: 2026-04-23
last_reviewed: 2026-04-23
---
## Trigger
The on-call phone receives an Alertmanager page. Severity
`critical` or `warning`.
## Entry
On-call arrives at `/ops` (ADR-065 SRE persona route) with phone
still buzzing. Sidebar shows the five-mode switcher; active-mode
underline is on Home, Operate badge has a red dot.
## Path
1. Click the Operate badge (or Cmd+2). Severity-ranked alert list
loads.
2. Top alert is the paging one. Click to open alert detail.
3. Alert detail shows service, metric, threshold, and a `Runbook`
quick-action linking to the relevant `service_runbook` playbook.
4. Click the quick-action — land on the runbook.
5. Follow the runbook's `## Diagnostics` and `## Mitigations`.
## Exit
Alert acknowledged in Alertmanager (one click from alert detail);
mitigation applied; `/ops` reflects the service returning to green
within 15 minutes.
## Outcome
Service back to green. Post-incident: on-call updates the incident
response playbook's Retro section with anything the playbook didn't
cover.
## Gaps
- Quick-action linking alert → runbook is not implemented; today the
runbook lookup is tribal (see ADR-065 Nicety #6, not yet shipped).
- Alertmanager's acknowledgement round-trip to the Platform UI is
~30s today; feels stale during a live page.
- No mobile layout for `/ops` — on-call reads it on a laptop.
## Retro / gaps
Same as Gaps above (journey kind conventionally merges Retro with
Gaps; other kinds keep them separate).
This is ~60 lines. The front-matter is ~12 lines; the body is the rest. Diff-reviewable, grep-friendly, typed-referenceable.
8. Browser UI — punted, gated
A Platform UI surface that lists playbooks, filters by persona / kind
/ owner / status, and surfaces stale ones (last_reviewed > 90 days)
is obviously desirable. It is explicitly out of scope for this
ADR and will not be built until 15 playbooks exist in the
catalogue — the threshold where a browser stops being a
gold-plating exercise and starts being a load-bearing tool. Until
then, grep + _index.yaml + a shell one-liner are the UI. A
follow-up ADR will define the browser when the threshold is crossed.
9. The gaps KPI
Every playbook's body has a Gaps (or Retro / gaps) H2.
scripts/regen-playbooks-index.sh counts bullet points in that
section and writes gaps_count into _index.yaml. The Owner
dashboard (ADR-065's / route) grows a tile:
% playbooks with known gaps — fraction of active playbooks where
gaps_count > 0. Baseline will be "high" (most playbooks are honest about being incomplete) and the useful signal is the trend: is the number going down as we fix gaps, or up as we discover new ones?
This is the "fraction of operational procedures with a known gap" metric that ADR-065's persona work wanted and could not build.
10. Owner field semantics
owner: is a single GitHub handle. Rules:
- No groups, no teams, no aliases.
@platform-teamgets ignored by everyone on the team;@jondoes not. - Owner rotation is a PR. When ownership changes, the change is a commit on the playbook file — the git history is the ownership-change log.
- Unowned playbooks fail CI.
owner:is required front-matter; empty or missing is a validation failure. - An owner's departure requires a sweep. Offboarding a human involves re-owning their playbooks to someone else. This is on-purpose friction — it makes abandoned playbooks visible.
11. Review cadence
Every status: active playbook is re-reviewed every 90 days.
Review means: the owner reads it, re-walks the steps if feasible,
updates last_reviewed, and either fixes gaps or adds new ones.
Staleness enforcement:
- CI warning at 75 days (
⚠ playbook <id> is approaching staleness). - CI failure at 120 days unless
status: archived. This is deliberate — a 4-month-old runbook that has not been re-walked is worse than no runbook, because the reader trusts it. - Owner dashboard flag at 90 days — a red dot next to the playbook in the (future) browser, a row in the "stale" table today.
Archived playbooks skip all checks but remain in the catalogue for reference (and for forward references from active playbooks — an incident playbook may cite an archived runbook to explain history).
Superseded playbooks must set related: [<kind>:<successor-id>] and
the successor must related: back.
Consequences
Easier.
- One index, one query surface, one KPI. "What does
@jonown?" is onegrepon_index.yaml, not six. - Cross-kind references are typed. Delete a runbook, CI warns its dependents. Promote an experiment to a runbook (new kind, same ID structure), dependents still resolve.
- Onboarding, release flows, and incident responses become first-class artifacts with the same discipline as experiments. The gyrum developer loop is no longer tribal.
- The gaps KPI lights up the "we know this is broken" surface area of the fleet. Priya (security) and Marcus (architecture) get a single place to see what's under-documented.
Harder.
- Retrofit cost is real. 316 experiments + existing runbooks + the incident playbook split is roughly 30-40 PRs of migration. We accept this up front and batch it: ~50 experiments per PR (they auto-generate cleanly), one PR per kind for the remaining shapes.
- Every new operational procedure now carries a front-matter tax. Authors who would have written a quick .md now write a quick .md plus seven required fields. The 7 fields are the price of the catalogue; we pay it deliberately.
- The 90-day review cadence is a standing commitment. A 20-playbook catalogue implies a review every ~4.5 days on average. If nobody does them, the CI staleness gate becomes noise and gets ignored, and the primitive collapses.
owner:as single handle is opinionated. When a playbook is genuinely co-owned, the author has to pick one; the other is credited in the body. This is friction, on purpose.- The kind set (six) becomes a governance surface. Adding a seventh
kind (e.g.
cost_model,experiment_series,capability_map) is an ADR amendment. We expect one such amendment in the next year; more than that suggests the primitive is wrong and we should revisit.
What we sign up to maintain.
- The schema. Schema changes are backwards-compatible where possible
and versioned otherwise (a
schema_version:field joins the front-matter when we need it). - The
_index.yamlregeneration script. A broken regen script blocks the Owner dashboard. - The 90-day cadence. If the cadence drifts, the KPI lies.
- The "ADRs are not playbooks" boundary. The pressure to make an ADR a playbook (or a playbook an ADR) will be real; we hold the line. Decisions and operations are different primitives.
Migration path
Shippable in the same small-PR rhythm ADR-062 and ADR-065 use. Each step is independently mergeable.
| Step | Where | What |
|---|---|---|
| 1 | dark-factory | This ADR merges. Cite nothing retrofitted yet. |
| 2 | dark-factory | docs/playbooks/ scaffold + first kind: release_flow playbook (gyrum-complete-pr.md) — codifying the existing release flow is the lowest-risk first test of the schema. |
| 3 | dark-factory | _index.yaml regeneration script + CI job that validates front-matter + typed references. Fails on unresolved related: refs. |
| 4 | ai-frontend | Journey draft merges (ADR-065 follow-up). Add front-matter; four journey playbooks ship (dev-review-inbound-pr, sre-first-five-minutes, owner-weekly-scan, manager-release-readout). |
| 5 | dark-factory | Split incident-response-playbook.md mega-doc into 4-5 kind: incident_response playbooks; original file becomes a linked overview. |
| 6 | dark-factory | Retrofit existing *-runbook.md files to kind: service_runbook playbooks under docs/playbooks/runbooks/. |
| 7 | ai-research | First batch of 50 kind: experiment playbooks auto-generated from run-report.json + existing README.md. |
| 8 | ai-research | Remaining ~266 experiment playbooks in batches of 50. |
| 9 | dark-factory | First kind: onboarding playbook — first-commit.md. |
| 10 | ai-frontend (Platform UI) | Owner-dashboard gaps KPI tile (reads from _index.yaml). |
| 11 | ai-frontend | Once catalogue crosses 15 playbooks, a follow-up ADR defines the browser (§8). |
Steps 1-4 are in-scope for this ADR's shipping cohort. Steps 5-9 are tracked follow-ups; step 10 waits on step 3 (CI green) and step 4 (first journeys merged). Step 11 is explicitly gated.
Throughout, existing documents continue to work — a reader grepping
docs/incident-response-playbook.md still finds it until step 5
splits it; a reader opening an experiment's directory still finds
its run-*.sh before and after it grows a PLAYBOOK.md.
Alternatives considered
Option B — shared tagging vocabulary only, each kind keeps its own schema. Rejected — see the Context section. Gives discovery without references, without a shared catalogue, without a shared review cadence. Optimises for the case where the six kinds diverge; the evidence says they are converging.
A Playbook is a YAML file with Markdown
content:field. Considered seriously. Rejected — Markdown as the primary format and YAML as front-matter keeps the body editable in any Markdown tool, keeps git diffs human-readable, and matches every other gyrum doc convention (ADRs, the journey draft, the experiment READMEs). A YAML-primary format would require a custom editor or tooling to stay sane.Per-kind tables in a shared database (SQLite, or rows in
gyrum-catalogper ADR-060). Rejected — the catalog library (ADR-064) is the right tool for inventory (servers, repos, services — machine-generated facts about infrastructure). Playbooks are human-authored narrative with embedded typed references. Narrative in a database is painful to edit and review; narrative in Markdown with a generated index gets both properties. The_index.yamlis the database projection; the playbook file is the source.Let the browser come first — build the UI, retrofit shapes to match what the UI reads. Rejected — ADR-065 explicitly values URL-as-contract and file-as-contract. A UI that owns the schema is a UI whose schema is invisible to anything except the UI. A file-first, index-second, UI-third ordering keeps the primitive usable by
grep, by a future human reader without the UI running, and by agents that read the filesystem directly.Split by persona, not by kind. Rejected — persona is orthogonal to kind. A journey, a runbook, and an onboarding flow can all be SRE-persona. Sorting the primary axis on persona would either duplicate playbooks across persona folders or force artificial single-persona assignments. Kind is the durable axis; persona is a facet.
Review cadence (for this ADR)
Re-review every 90 days (next: 2026-07-22) against:
- Playbook count — are we past the 15-playbook browser threshold (§8)?
- Gaps KPI — is the trend healthy?
- Retrofit progress — which of the seven kinds have migrated, which haven't?
- Staleness noise — is the 120-day CI fail firing on legitimate work or being bypassed?
- Kind inventory — has a seventh kind been proposed? If so, amend.
Stale flag on the Owner dashboard once last_reviewed on this ADR
passes 90 days.
References
- ADR-065 — persona vocabulary (
dev | sre | manager | owner | boss) is reused verbatim inpersona: - ADR-066 — (placeholder — the next ADR in line when niceties framework gets its follow-up; cross-reference if/when it lands)
- ADR-064 — gyrum-catalog library: playbooks are not catalog entries; the two primitives complement
- ADR-060 — catalog-driven infrastructure: service runbooks
related:service catalog IDs - ADR-059 — project-first IA: playbooks inherit the project class
vocabulary (product / restricted / platform) in their
tags:when relevant ai-frontend/docs/journeys/00-overview.md— in flight at 2026-04-23; the red-route vocabulary in that draft is the source of thejourneykind's required H2sdark-factory/docs/specs/experiments-progress-plan.md— the narrative index that continues to live alongside per-experiment playbooksdark-factory/docs/shared/gate-stack.md— referenced byrelease_flowplaybooks'## Gate stacksectiondark-factory/docs/incident-response-playbook.md— the mega-doc that splits into per-incident-typeincident_responseplaybooks
Supersedes: none Superseded by: leave blank until a later ADR reverses this one