Decisions

ADR-067: Playbooks as a unified primitive

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,…

#067

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:

  1. Trigger — what event starts the procedure
  2. Steps — the ordered (or branching) set of actions
  3. Outcome — what "done" looks like, and how it's verified
  4. 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 @jon that 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 /team and 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:

  1. 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.
  2. A shared catalogue. "List everything @jon owns, across kinds, with its last-reviewed date" requires one loadable index. Six directories with similar-but-not-identical front-matter resist a single index.
  3. 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:

  • kind is the discriminator. Unknown values fail validation.
  • id is kebab-case, alphanumeric, globally unique within its kind. Cross-kind collisions are allowed (runbook:focusjourney:focus); references always carry the kind prefix.
  • persona reuses ADR-065's persona vocabulary exactly (dev | sre | manager | owner | boss) + none for persona-neutral playbooks. Adding a persona is an ADR-065 amendment, not a playbook schema change.
  • owner is a single GitHub handle. Group ownership ("@platform-team") is rejected — groups don't respond to pings.
  • status governs the review cadence (§11) and the "gaps" KPI (§9).
  • trigger is free-text but should be one sentence. It is the first thing a reader sees when grepping.
  • success_metric is 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".
  • tags are lowercase kebab-case. Unbounded vocabulary; the Owner dashboard surfaces the top-N.
  • related uses typed kind:id references. Validation: each reference resolves or CI fails. ADR references use adrs:NNN. References to non-playbook artifacts (a PR, a Slack thread) are string URLs under references: in the body, not related:.
  • created and last_reviewed are ISO dates. The 90-day cadence (§11) reads last_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 just run-*.sh. Findings are the aggregated run-report.json interpretation. 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 references docs/shared/gate-stack.md as 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's id matches 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's related: lists the service's catalog ID (ADR-060) so the two stay linked.

5. Typed references

related: entries are kind:id pairs. Validation rules:

  1. Every kind:id must resolve to a playbook file somewhere in the fleet.
  2. adrs:NNN resolves against dark-factory/docs/decisions/NNN-*.md.
  3. Unresolved references fail CI (loud, not silent). This is the "deleted runbook warns its dependents" property that prose links don't give us.
  4. 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:

  1. No groups, no teams, no aliases. @platform-team gets ignored by everyone on the team; @jon does not.
  2. 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.
  3. Unowned playbooks fail CI. owner: is required front-matter; empty or missing is a validation failure.
  4. 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 @jon own?" is one grep on _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.yaml regeneration 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-catalog per 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.yaml is 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 in persona:
  • 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 the journey kind's required H2s
  • dark-factory/docs/specs/experiments-progress-plan.md — the narrative index that continues to live alongside per-experiment playbooks
  • dark-factory/docs/shared/gate-stack.md — referenced by release_flow playbooks' ## Gate stack section
  • dark-factory/docs/incident-response-playbook.md — the mega-doc that splits into per-incident-type incident_response playbooks

Supersedes: none Superseded by: leave blank until a later ADR reverses this one