Skip to main content

Operations Runbook

How to view findings, triage them, and keep the registry up-to-date in steady-state operations.

Part 1 — Where findings live​

Findings live in two complementary places:

1. Raw YAML files (source of truth)​

hmp-docs/registry/findings/FD-<YYYY-MM-DD>-<NNN>.yaml

Every finding has its own YAML. File naming: FD-<date>-<seq>.yaml.

Example finding:

id: FD-2026-04-23-001
title: api AP-sample-login missing from code but still referenced by 1 story
created: 2026-04-23
detector: drift-checker
severity: high
context:
entityKind: apis
entityId: AP-sample-login
direction: missing-with-refs
referencedBy:
- ST-901-001
status: detected

Key fields:

  • detector — which tool emitted it (drift-checker, coverage-check, manual-sp2-triage, etc.)
  • severity — blocker | high | medium | low
  • context.direction — the rule that fired:
    • new — scanner found an entity not in registry
    • missing — registry has entity but scanner can't find it
    • missing-with-refs — missing AND referenced by a story (upgraded to high)
    • stale-built-status — story claims built but has 0-1 implementations
    • story-unclaimed — entity exists but no story references it
  • status — detected (fresh) | triaged (decision recorded) | resolved (fix shipped)
  • triageDecision (added after triage) — confirmed-drift | invalid | feature-gap | needs-developer | wontfix etc.
  • context.triageNote (added after triage) — human rationale

2. Drift Dashboard (visual)​

Web view at /docs/platform-registry/drift in the Docusaurus build. Reads docs/platform-registry/_data/drift-report.json (regenerated by every drift-check run). Shows findings sorted by severity in a filterable table.

To regenerate the dashboard locally:

cd hmp-docs
npx tsx tools/registry/src/cli.ts drift-check
npm start # Docusaurus dev server at http://localhost:3000

3. Nightly CI​

The Azure Pipeline .azuredevops/pipelines/registry-nightly.yml runs at 18:00 UTC daily, scans all 23 repos, regenerates findings, and commits any changes. So the findings directory is kept fresh automatically overnight.


Part 2 — How to triage & act on findings​

Triage decision tree​

For each finding, ask:

1. Is the entity real (exists in code today)?
NO → Entity was deleted. Either:
(a) Remove the registry YAML (if truly gone): git rm registry/<kind>/<id>.yaml
(b) Annotate finding as invalid-fixture (for sample/test entities)
(c) Annotate as confirmed-drift + open cleanup task
YES → go to 2.

2. Does the finding say it's "missing"?
YES → Scanner regressed or entity was renamed. Either:
(a) Update the entity YAML with the new id/path
(b) Investigate why scanner can't find it (common: file moved to new repo)

3. Is the finding "missing-with-refs"?
YES → Story's implementations.* block points to a deleted entity. Either:
(a) Fix the story YAML: remove the stale ref
(b) Restore the entity in code if removal was accidental
(This is HIGH severity — resolve within the same sprint.)

4. Is the finding "stale-built-status"?
YES → Story claims built but has fewer than 2 implementations. Either:
(a) Flip status: built → in-progress (if not actually shipped)
(b) Add the missing implementations.* refs (if shipped but under-curated)
(c) Flip status: built → deprecated (if story was rolled back)

5. Is the finding "story-unclaimed"?
YES → Entity exists but no story owns it. Either:
(a) Add entity id to a relevant story's implementations.*
(b) If entity is tangential (test fixture, dev-only route), ignore with
triageDecision: wontfix + a short reason

Recording a triage decision​

Edit the finding YAML in-place. Add or update these fields:

# finding.yaml
status: triaged # was: detected
triageDecision: confirmed-drift # or: invalid | feature-gap | needs-developer | wontfix
context:
# ... existing fields ...
triageNote: "Rolled back in PR #123; story marker not updated. Owner to fix this week."

Commit the annotation:

git add registry/findings/FD-<id>.yaml
git commit -m "triage(registry): FD-<id> marked as <decision>"

Resolving a finding (not just annotating)​

After the fix ships:

# finding.yaml
status: resolved # was: triaged
resolvedAt: 2026-04-30
resolvedBy: @ajay
resolvedIn: PR#456 # or commit sha

Or delete the YAML entirely if it's obsolete:

git rm registry/findings/FD-<id>.yaml

Either is fine. Keeping resolved findings gives audit history; deleting keeps the directory lean. Pick one convention and stick to it.


Part 3 — Steady-state audit cadence​

Weekly (first 4-6 weeks of SP-4)​

Owner: reviewer-on-rotation (developer who owns registry that week)

Monday:

  1. Pull latest master: git pull origin master
  2. Run: npx tsx tools/registry/src/cli.ts drift-check
  3. Open the Drift Dashboard at /docs/platform-registry/drift
  4. Sort by severity. Focus on blocker → high → medium.

Monday-Thursday:

  1. Triage the top-20 findings per the decision tree in Part 2
  2. For each: edit finding YAML with triageDecision + triageNote; commit
  3. For fixable ones: also fix the referenced story/entity and commit

Friday:

  1. Re-run drift-check. Confirm finding count dropped.
  2. Commit + push the week's triage batch. PR title: triage(registry): week <N> (<date>)
  3. Update docs/platform-registry/drift.mdx weekly-cadence section with your notes.

After 4-6 weeks​

Evaluate whether weekly is still worthwhile:

  • If finding volume is steady-low (fewer than 10 new per week), downshift to biweekly.
  • If 0 new findings for 2 weeks, downshift to monthly.
  • If ever 20+ new findings in a week, escalate — something's drifting faster than the ops cadence can absorb.

Monthly / Quarterly​

  1. Stale story audit — any status: built story with no implementations.* growth for 90 days → flip to deprecated or investigate why.
  2. Gate promotion review — watch bake metrics for report-only gates. Promote when stable.
  3. UI adoption check — update uiAdoption counts in docs/platform-registry/_data/dashboard.json. Track wave progress.

Part 4 — Keeping the registry up-to-date​

When you WRITE code​

Follow the discipline in /docs/platform-registry/workflow:

  • Added an API route? → Add/update registry/apis/AP-<service>-<METHOD>-<path>.yaml Or run npx tsx tools/registry/src/cli.ts scan-routes to auto-write from code.
  • Added a screen? → registry/screens/SC-<app>-<route>.yaml or scan-screens.
  • Added an event? → registry/events/EV-<topic>.yaml or scan-events.
  • Added a Prisma model? → registry/tables/TB-<service>-<model>.yaml or scan-tables.
  • Added a test? → registry/tests/TS-<path>.yaml or scan-tests.
  • Shipped a story? → flip status: in-progress → built in registry/stories/ST-*.yaml.
  • Added the entity's owning story? → update story implementations.<kind> to include the new entity's id.

When you REVIEW a PR​

  • CI is blocking on validate-yaml + check-cross-links (SP-6 gates). If either fails, don't merge until fixed.
  • PR comment shows drift + coverage summary for registry-touching PRs. Scan it.
  • For major features, verify the PR updated the relevant story YAML's implementations.* — if a dev shipped code but didn't update the registry, leave a comment.

When you SHIP a release​

  1. Run npx tsx tools/registry/src/cli.ts drift-check on the release branch.
  2. Triage any new findings before merging the release PR.
  3. Update the parent epic's lastVerified: <today> after the release is stable.

Periodic refresh​

Nightly (automated): scans regenerate entity YAMLs. No action needed.

After large refactors (manual): run all scanners:

cd hmp-docs
for cmd in scan-routes scan-screens scan-events scan-tables scan-tests; do
npx tsx tools/registry/src/cli.ts $cmd
done
git add registry/ && git commit -m "chore(registry): refresh scans after <refactor>"

Part 5 — Common scenarios​

"I added a new API, what do I update?"​

  1. Scan auto-emits the YAML: npx tsx tools/registry/src/cli.ts scan-routes writes registry/apis/AP-<service>-<METHOD>-<path>.yaml.
  2. If the new API implements an existing story, edit registry/stories/ST-<id>.yaml and add the new API id to implementations.apis.
  3. If the API is a new feature that doesn't fit any existing story, either:
    • Create a new story, OR
    • Leave the entity unclaimed (coverage-check will flag it, triage can assign later).

"I deleted an API, what do I update?"​

  1. Delete the entity YAML: git rm registry/apis/AP-<id>.yaml
  2. Grep for the id in stories: grep -rl "AP-<id>" registry/stories/
  3. Remove the id from each story's implementations.apis array.
  4. validate-yaml + check-cross-links will refuse to let you merge if you miss step 3.

"validate-yaml is failing in my PR, what do I do?"​

  1. Run locally: npx tsx tools/registry/src/cli.ts validate-yaml
  2. Read the error — it tells you which file and which schema rule failed.
  3. Common cause: unquoted colons in acceptance strings (YAML mis-parses as mapping). Wrap the string in double quotes.
  4. Fix + commit + push.
  1. Run locally: npx tsx tools/registry/src/cli.ts check-cross-links
  2. Error says: ST-<id> references AP-<x> but AP-<x> not found
  3. Either fix the typo in the story YAML, or check whether the entity was renamed / deleted (maybe you're the one who deleted it).

"I see a finding but it's wrong / not actionable, what do I do?"​

Annotate it as triageDecision: wontfix with a triageNote explaining why:

status: triaged
triageDecision: wontfix
context:
triageNote: "Sample fixture — never in real code. Kept for SP-1 schema tests."

Commit. Don't delete — keeping the annotation documents the decision for future triages.


Part 6 — Current finding state (as of 2026-04-24)​

Total findings: 45
- drift-checker: 19 (0 high, 19 medium, 0 low, 0 blocker — post-SP-4 triage)
- manual-sp2-triage: 25 (legacy findings from Frontdesk pilot, already triaged)
- coverage-check: 0 (only ever run --dry-run)

Blocking gates enforced:
- validate-yaml ✅ on every PR
- check-cross-links ✅ on every PR

Non-blocking (PR comment):
- drift-check report-only
- coverage-check report-only

The next thing that will change this state:

  1. A developer makes a PR that touches code/registry → PR comment appears
  2. Nightly pipeline runs → scans regenerate → new drift findings may appear
  3. Weekly SP-4 cycle runs → triage top-20 → state shifts