Appendix A - 27. Operator runbook skill (positive map first, symptom index fallback)
The Structure of Operator runbook skill (positive map first, symptom index fallback) — its shape at a glance:
The skill leads with the positive lifecycle map, falls back to a symptom-keyed index, and is rendered from typed YAML; a reference-validity lint resolves every pointer's file and anchor on each build.
flowchart LR
YAML[(Typed YAML source)] -->|render| Skill[Operator skill]
Skill --> Map[Positive lifecycle map]
Skill --> Index[Symptom → resolving-doc]
Ref{{Ref-validity lint}} -.->|resolve file + anchor| Skill
Accessible description: a typed YAML source renders into the operator skill, which leads with a positive lifecycle map and falls back to a symptom-to-doc index; a reference-validity lint resolves every pointer's file and heading anchor on each build, so a moved doc is a build error.
Projected from the catalogue entry governance-doc-controls / Operator runbook skill (positive map first, symptom index fallback).
On this page: Intent · Motivation · Applicability · Structure · Sample Code · Consequences · Example use within DocAble · Related Patterns
Intent
Intent — A loadable skill that gives an operating agent the positive map of how the operational substrate works (its lifecycles and healthy baselines) first, and a symptom → resolving-doc catalog as the fallback when something breaks. Generate its content from a typed source-of-truth so a reference-validity lint (not tests; it executes nothing) keeps every pointer honest, and type each recovery step by how automatable it is (our instance: an operate-ada-tool-repo skill over the agent-fleet substrate, rendered from two typed YAML sources: a pointer catalog and a runbook catalog).
Motivation
An operator (a human or an orchestrator agent) running a complex substrate must know two things: how it works when healthy, and what to do when it breaks. Both live scattered across a house-rules doc, a docs index, and incident memories that a fresh or post-compaction operator does not reliably hold. So the operator re-derives the substrate's shape from scratch under load, and during an incident re-derives, badly and under time pressure, a recovery a doc already spells out. And the routing itself rots: a doc moves, the pointer dangles, the next operator is sent on a chase. The failure is re-derivation of known operations plus silent pointer rot, and it recurs every session and every incident.
Underneath is a stance: the fleet is cattle, not pets. You operate an agent fleet with repeatable runbooks, not by re-reasoning each incident from scratch or chatting the orchestrator toward a goal. That is the pet stance ("sysadmin-ing a pet server"), and it is a category error at fleet scale. This mechanism is the cattle stance made concrete for repo operations: a routed, lint-kept index of typed operations, so an operator runs the herd instead of nursing it.
Applicability
- A typed source-of-truth the skill renders from; hand-authored markdown drifts from the docs it points at, while the YAML is single-sourced and lint-checkable.
- A reference-validity lint that resolves file and anchor. File-exists alone lets a renamed section dangle.
- Typed step-kinds on runbook steps, so "which of these is runnable vs needs judgment" is declared, not guessed by the operator mid-incident.
- A partner failure-interpretation path, so a recurring failure becomes a designed mechanism rather than an inline patch.
Structure
The Structure diagram appears at the top of this page.
Sample Code
The skill is generated, so its correctness comes from a reference-validity lint rather than tests: it resolves every pointer's file and heading anchor against disk, catching a moved doc or renamed section a file-exists check would miss.
import re, sys
def anchor_exists(path: str, anchor: str, read) -> bool:
"""A pointer resolves only if the file exists AND the heading anchor is present."""
headings = {re.sub(r"[^a-z0-9]+", "-", h.lower()).strip("-")
for h in re.findall(r"^#+\s+(.+)$", read(path), re.M)}
return anchor in headings
def lint_pointers(pointers, file_exists, read) -> list[str]:
findings = []
for path, anchor in pointers: # each pointer is (file, heading-anchor)
if not file_exists(path):
findings.append(f"pointer target missing: {path}")
elif anchor and not anchor_exists(path, anchor, read):
findings.append(f"anchor '#{anchor}' not found in {path} (renamed section?)")
return findings
if __name__ == "__main__":
findings = [] # feed pointers parsed from the typed YAML source
print("\n".join(findings))
sys.exit(1 if findings else 0)
Consequences
- The skill is soft. It routes an operator to the right doc; it cannot execute or block. Its value is being loaded and heeded.
- Coverage is soft; validity is the hard half. The lint guarantees every listed pointer resolves; it cannot guarantee every real symptom is listed. Completeness rots unless new incidents are appended (the second-time-not-the-third discipline).
- Anchor-resolution is a maintenance tax. Resolving heading anchors (not only files) catches more rot but fires on every heading rename; that is the price of the higher fidelity.
- Generation adds a build step. The YAML→markdown render must run, or the served skill drifts from its source.
Example use within DocAble
- A skill leading with the substrate's lifecycles + healthy baselines, then a symptom→resolving-doc catalog for breaks.
- Runbooks with typed step-kinds (runnable / carried-brief / surface-to-user), making the judgment-automatable middle a lintable resource.
- A drift-audit runbook that reads a typed model to know what changed — the sharpest case of the step typing. Given a typed model and the code it claims, its runnable steps mechanize the determinizable work (enumerate every claim-to-code anchor, resolve each symbol to flag a broken one, batch-re-run the model's own owned checks for any gone red since the work closed) and its surface-to-user step reserves the one question a machine can't take: is a mismatch a real divergence, or an intended as-built gap the model should record rather than treat as an error? The judgment residual shrinks by one for a formally-anchored claim, where re-running its checker is the semantic verdict — so that slice's irreducible step becomes runnable. This is a runbook whose mechanizable steps are driven off the model the definition-of-done reads to learn what drifted (its instance: a DoD drift-audit over the system models, minted from an audit that harvested roughly two dozen drift instances at near-one signal-to-noise across recently-closed work).
- The reference-validity lint resolving every pointer's file and heading anchor from a typed YAML source-of-truth.
- The handoff to a failure-interpretation skill: recurring failure → classify → Epic → designed mechanism.
Related Patterns
- Counterpart — operational-playbooks: those are the situation-keyed runbooks themselves (the failure half); this skill is the operator-keyed map over them: positive-lifecycle-first, symptom-indexed, lint-kept. The named axis is the runbooks versus the indexed, generated map into them.
- See also — claude-md-rule-index: both treat a governance document as enforced infrastructure held honest by a lint; this one adds the operator-index shape and generation from a typed source.
- Enabler — the reference-validity lint is the same "every pointer ↔ a real target" discipline as the models' drift-parity gates, applied to a doc-skill instead of a typed model.