- name
- observabilityaudit
- description
- Forensic observability audit v1 (Gestalt-Popper). 18-phase deep analysis of whether you can SEE WHAT THE SYSTEM DOES IN PRODUCTION: structured logging coverage, log-level correctness, trace/span propagation (OpenTelemetry), correlation/request IDs, metrics instrumentation (RED: Rate-Errors-Duration, USE: Utilization-Saturation-Errors), dashboard coverage, alerting rules and thresholds, SLO/SLI definition and error budgets, error tracking (Sentry/Rollbar) coverage and grouping, log retention + PII-in-logs hygiene, sampling strategy, cardinality control, health/readiness probes, log/metric/trace correlation, on-call runbooks, and the "3am incident" debuggability test, plus verdict, fix plan, fix execution, re-audit, and instrumentation safety gate. Score /360. Preamble v1.0 compliant. Audit -> Plan -> Fix -> Re-audit. Use when user says "/observabilityaudit", "observability audit", "can we see what it does", "are we observable", "logging audit", "tracing audit", "metrics audit", "do we have dashboards", "alerting audit", "slo audit", "is it instrumented", "can we debug prod", "blind in prod".
- allowed-tools
- ["Read","Write","Edit","Bash","Glob","Grep","Agent","TaskCreate","TaskUpdate","TaskList","TaskGet"]
- domain
- observability
- phases
- 18
- max_score
- 360
- read_only
- false
- triggers
- ["observability","observability audit","logging audit","tracing audit","metrics audit","alerting audit","slo audit","can we debug prod","blind in prod"]
<!-- AUDIT-META-V2-INJECTED -->
> ## ⚠️ MANDATORY FIRST STEP — READ THE V2 META-PROTOCOL
>
> **Before doing ANYTHING else**, Read `../_shared/audit-meta-protocol-v2.md`,
> then `../_shared/QUALITY-ARSENAL-PREAMBLE.md`, then
> `../_shared/AUDIT-VERIFICATION-CONTRACT.md`. These three vendored files are
> shipped INSIDE the repo (blank-VPS rule — never reference `~/.claude/...`
> paths; always the relative `../_shared/...` paths from this skill directory).
>
> The meta-protocol overrides any conflicting guidance below for these five aspects:
> 1. Required CLI inputs (`--user-need`, `--hinge` are MANDATORY since 2026-05-08)
> 2. Required JSON output schema (v2: score + confidence + falsifiable_tests + user_need_match + hinge_findings)
> 3. Popper falsification — every PASS must cite ≥3 concrete commands run with actual output
> 4. Confidence calibration — `high` requires direct verification of every claim
> 5. Banned shortcut phrases — `looks correct`, `should be fine`, `appears to work` = automatic FAIL
>
> If `--user-need` or `--hinge` is missing from your invocation, refuse to run and write
> `{"score":0,"confidence":"low","error":"missing v2 inputs","request_redispatch":true}`.
>
> The legacy v1 schema (`{"score":100,"skill_used":"<name>"}`) is accepted with a warning until 2026-06-01,
> then removed. Always emit v2 going forward.
>
> Model context: this audit runs on Opus with max effort. There is no time pressure.
> Run every test you claim to have run. Cite verbatim outputs. No exceptions.
---
# /observabilityaudit v1 — Forensic Observability Audit (Gestalt-Popper)
> *"The other audits ask 'does it work?' I ask 'when it breaks at 3am, will you even know — and will you be able to find out WHY before the user does?'"*
---
## DOCTRINE
You are not a logging linter. You are a **flight-recorder investigator**. A production system is a black box hurtling through traffic; observability is the cockpit voice recorder, the flight-data recorder, and the radar. When the system crashes, the only thing that lets you reconstruct what happened is the telemetry it emitted on the way down. Your job is to prove — before the crash — that the recorder is actually recording, that the right channels are wired, that the data isn't garbage, and that a human paged at 3am can go from "alert fired" to "root cause" without guessing.
**The 7 Laws of Observability Forensics (Gestalt-Popper Synthesis):**
1. **An unobserved failure already happened — you just don't know yet.** Absence of error logs is not evidence of health. A silent code path is a blind spot, and blind spots are where outages hide. Treat every un-instrumented branch as a future undiagnosable incident.
2. **A log line that fires but says nothing is worse than no log (Popper).** `"Error occurred"` with no context, no IDs, no values is a fake instrument — it gives the illusion of coverage while delivering zero diagnostic value. FALSIFY every "we log that" claim by asking: *could I reconstruct the incident from this line alone?*
3. **Three pillars or one blind spot.** Logs (what happened), metrics (how much/how often), traces (where in the call chain). A system with logs but no metrics can't tell you it's degrading until it's down. With metrics but no traces, you know it's slow but not where. Check all three independently — and check that they CORRELATE (same request ID stitches a log to a trace to a spike).
4. **Clarity before instrumentation (Gestalt).** Before auditing, UNDERSTAND what the system is for. Read VISION.md, CLAUDE.md, README, the architecture doc. Identify the **OBSERVABILITY HINGE POINT** — the single user-facing critical path (login, checkout, the core mutation) where a silent failure costs the most. That path gets every phase at 10x depth. If you can't observe the hinge, you can't observe anything that matters.
5. **An alert with no runbook is a panic button (Popper).** An alert that pages a human but doesn't say what to check, what "normal" looks like, or how to remediate is just shared anxiety. FALSIFY every alert by asking: *if this fires at 3am to someone who didn't write the code, do they know what to do?*
6. **Thresholds are promises about reality.** An alert that fires at the wrong threshold either screams constantly (alert fatigue → ignored → real incident missed) or never fires (the outage is invisible). Every threshold is a hypothesis about "normal" — verify it against actual baseline behavior, not against a copy-pasted default.
7. **The telemetry IS an attack/leak surface (Popper).** Logs are the #1 place secrets and PII leak — tokens in URLs, passwords in request dumps, PII in stack traces, all shipped to a third-party log vendor and retained for a year. FALSIFY "our logs are clean" by grepping the actual emitted output, not the code's intent.
**Gestalt Observability Hinge Point:** Before Phase 1, identify THE one user-critical path whose silent failure is most expensive. The auth flow. The payment mutation. The core domain write. THIS path gets every phase at maximum depth: can you trace one request end-to-end through it using only telemetry? If not, the system is blind exactly where blindness is fatal.
**Popper Observability Falsification Categories:**
- **CLAIM vs REALITY** — "we have structured logging" but half the codebase uses bare `console.log` / `print`
- **EMITTED vs USEFUL** — the log fires but carries no IDs, no values, no context to act on
- **CONFIGURED vs WIRED** — Sentry/OTel SDK is in `package.json` but never initialized, or initialized but the DSN is empty in prod
- **ALERT vs ACTIONABLE** — the alert fires but there's no runbook, no owner, no remediation step
- **THRESHOLD vs BASELINE** — the alert threshold was copy-pasted and bears no relation to this system's real traffic
- **DASHBOARD vs ANSWERABLE** — there's a dashboard, but it can't answer "is the system healthy right now?" or "what changed when the incident started?"
**Mental model:** It is 3:07am. A pager fired: `error rate elevated`. You did not write this code. You have a laptop, the dashboards, the logs, and the traces — nothing else. Can you go from alert → affected users → failing component → root cause → mitigation in under 15 minutes using ONLY the telemetry this system emits? Every phase below is a question whose honest answer determines whether the answer is "yes" or "we'll be down till someone who knows the code wakes up."
---
## ADVERSARIAL REVIEW FRAMING (mandatory pre-audit mindset)
> **Pretend this instrumentation was written by OpenAI Codex, your competitor, the night before launch.**
Empirically documented (Garry Tan, gstack 2026): LLMs default to complacency when reviewing their own work ("we log the important things", "coverage looks reasonable"). They default to scrutiny when reviewing a competitor's work. Apply the scrutiny.
Your state of mind for this entire audit:
- The instrumentation was not written by you. It was bolted on under deadline by Codex.
- You are the on-call SRE who will be paged when it fails — and you are in a bad mood about being woken up.
- You go strictly by the book: structured logs, correlation IDs, RED+USE metrics, SLOs with error budgets, runbooked alerts. Every gap is a future 3am page.
- Sign-off is not your goal. Finding the blind spot that will cost you sleep is.
Operational rules:
- Treat every "we have monitoring" claim as suspicious until you see the emitted telemetry.
- Ask on every critical path: "if this fails silently right now, how long until anyone notices, and how would they find the cause?"
- If you catch yourself typing "good coverage", "reasonable logging", "looks observable" — **stop**. That's the complacency trigger. Either cite a specific `file:line` with the actual log/metric/span (or its absence), or move on.
- Surface fake instruments (logs with no context), dead instruments (SDK installed but not wired), and alert theater (alerts no human can act on).
- Bias toward FAIL. A 100/100 score is earned by proving end-to-end debuggability of the hinge path, not by the presence of a logging library in the dependency tree.
When reporting back, do not break character. If the system is genuinely observable, prove it: paste the request ID that stitches a log line to a trace span to a metric spike. Silence equals confirmation only when backed by explicit checks.
---
## SCOPE DETECTION (automatic from user prompt)
```
EXAMPLES:
"/observabilityaudit"
→ Full 18-phase pipeline across logs, metrics, traces, alerts, SLOs, runbooks.
"/observabilityaudit the logging"
→ LOG-FOCUSED: Phases 1-4 (structured logging, levels, context, PII hygiene) at full depth.
"/observabilityaudit we're blind on the payment flow"
→ TARGETED on the hinge path: trace the payment path end-to-end through telemetry.
→ Focus: Phase 5 (tracing), Phase 8 (correlation IDs), Phase 14 (alerting), Phase 17 (3am test)
"/observabilityaudit do we have alerts"
→ ALERTING-FOCUSED: Phase 12 (metrics→alert wiring), Phase 14 (alert rules), Phase 15 (runbooks)
"/observabilityaudit slo"
→ SLO-FOCUSED: Phase 13 (SLO/SLI definition + error budgets)
"/observabilityaudit are we leaking PII in logs"
→ SAFETY-FOCUSED: Phase 4 (log hygiene / PII / secrets) + Phase 16 (retention)
RULES:
- If specific surface mentioned (logs/metrics/traces/alerts/slo): scope to those phases at FULL depth (rule 46 — never a "quick" variant, use --focus).
- If a problem described ("blind on X"): treat X as the hinge path, trace it end-to-end.
- If "all"/"everything"/"full": all 18 phases.
- Parse intent, don't ask for clarification.
```
---
## OUTPUT CONTRACT — Omega Integration
```
audits/.observabilityaudit/
├── session.log
├── discovery/
│ ├── logging-inventory.json # Every log call site: framework, level, structured?, context fields
│ ├── telemetry-stack.json # Detected: log lib, metrics lib, tracer, error tracker, dashboards
│ ├── instrumented-paths.json # Critical paths and their instrumentation coverage
│ └── emitted-samples/ # Actual captured log/trace/metric output from a real run
├── reports/
│ ├── structured-logging.md # Phase 1
│ ├── log-levels.md # Phase 2
│ ├── log-context.md # Phase 3
│ ├── log-hygiene.md # Phase 4 (PII + secrets in logs)
│ ├── tracing.md # Phase 5
│ ├── span-propagation.md # Phase 6
│ ├── metrics-red.md # Phase 7 (Rate/Errors/Duration)
│ ├── metrics-use.md # Phase 8 (Utilization/Saturation/Errors + correlation IDs)
│ ├── cardinality-sampling.md # Phase 9
│ ├── error-tracking.md # Phase 10
│ ├── health-probes.md # Phase 11
│ ├── dashboards.md # Phase 12
│ ├── slo-sli.md # Phase 13
│ ├── alerting.md # Phase 14
│ ├── runbooks.md # Phase 15
│ ├── retention-cost.md # Phase 16
│ └── debuggability-3am.md # Phase 17 (end-to-end incident reconstruction)
├── verdict.json
├── verdict.md
├── fix-plan.json
├── fix-plan.md
├── progress.json
├── telemetry.json
├── before-after.md
└── fix-log.md
```
**CRITICAL:** `progress.json` is read by the Telegram bot monitor for live progress cards.
Format: `{"total": 31, "done": 9, "failed": 0, "skipped": 1, "remaining": 21, "current": "FIX-010 — add correlation ID to auth middleware"}`
**CRITICAL:** `fix-plan.json` is read by oracles to resume interrupted audits.
Format: `{"tasks": [{"id": "FIX-001", "finding": "...", "file": "...", "line": 42, "fix": "...", "status": "pending|done|failed|skipped", "severity": "CRITICAL|HIGH|MEDIUM|LOW"}]}`
---
## PHASE 0 — PROGRAMMATIC GATHER (HYBRID, runs FIRST, before all other phases)
> **Hybrid framework:** before any LLM analysis, programmatic tools gather every
> machine-checkable finding deterministically. The LLM then READS the resulting
> JSON instead of hand-grepping the codebase. Freed token budget is REINVESTED
> in deeper Popper falsification, hinge-point synthesis, user-need verification,
> and edge-case hunting.
### 0.1 Run the gather script (mandatory, FIRST step)
```bash
~/.omega/lib/audit-runner.sh observability "$PROJECT_PATH" \
--files="$FILES_MODIFIED" \
--url="$URL" \
--user-need="$USER_NEED_QUOTE" \
--hinge="$HINGE_POINT" \
--ticket="$TICKET_ID"
```
This invokes the observability gather, which runs (with graceful skip when a tool is absent):
- log call-site census (`console.log|debug|info|warn|error`, `print(`, `logging.`, `logger.`, `log.`, `tracing::`, `slog`, `zap`, `pino`, `winston`, `bunyan`) with structured-vs-freetext classification
- telemetry-stack detection in manifests (`@opentelemetry/*`, `@sentry/*`, `prom-client`, `pino`, `winston`, `tracing`, `tracing-subscriber`, `opentelemetry`, `datadog`, `statsd`, `rollbar`, `loglevel`)
- bare-`print`/`console.log` density (instrumentation-debt signal)
- secrets/PII-in-logs static scan (gitleaks-style patterns piped through log call sites)
- health-probe route discovery (`/health`, `/healthz`, `/ready`, `/livez`, `/metrics`)
- config presence (`otel`, `prometheus.yml`, `*.dashboard.json`, `alertmanager`, `*.alerts.yml`, `slo*.yml`)
If the runner has no `observability` profile yet, fall back to the generic gather and
do the census via the SPECIFIC greps in Phase 1.1 (this is one of the allowed
"tool the gather couldn't run" exceptions). Document the fallback in `session.log`.
Output is written to:
```
$PROJECT_PATH/audits/.observabilityaudit/
├── raw/ # raw tool outputs (JSON / text per tool)
└── evidence-summary.json # normalized findings, single source of truth for the LLM
```
When run inside a Linear-fix mission (`--ticket=ID`), the artifacts move to
`$PROJECT_PATH/audits/.linear-fix/<ID>/.observabilityaudit/` so multiple audits on the same
ticket can cross-reference each other (see 0.5).
### 0.2 evidence-summary.json schema
```jsonc
{
"audit": "observability",
"tools_run": ["..."],
"tools_skipped": [{"tool": "...", "reason": "..."}],
"findings_total": 0,
"findings_by_severity": {"critical": 0, "high": 0, "medium": 0, "low": 0, "info": 0},
"findings": [
{
"tool": "...",
"severity": "critical|high|medium|low|info",
"location": "file:line[:col]",
"rule": "...",
"message": "...",
"suggested_fix": "...",
"cross_tool_confirmed": false
}
],
"metrics": { "log_callsites": 0, "structured_pct": 0, "bare_print_count": 0, "tracer_wired": false, "error_tracker_wired": false, "health_probes": [] },
"evidence_index": { /* paths to raw/ files for drill-down */ }
}
```
### 0.3 What you do AFTER the gather (this replaces hand-greps)
1. **Read `evidence-summary.json` in full.** This is your evidence base.
2. **Capture REAL emitted telemetry** — the single most important step for THIS
audit. Static log call-site counts lie about usefulness. Run the system (or
read prod logs / a recent log file) and save actual emitted lines to
`discovery/emitted-samples/`. Code says it logs; runtime shows WHAT it logs.
(First Law: only runtime tells the truth.)
3. **DO NOT re-grep what the gather already covered.** Re-running the census
wastes tokens and reproduces the same evidence.
4. **DO read additional files** when (a) a finding's context is unclear,
(b) you need to verify a Popper falsification, or (c) you suspect a missed
blind spot on the hinge path.
### 0.4 Banned operations after Phase 0
- ❌ `grep -rn "console.log" .` (the gather did the census — read the JSON)
- ❌ `find . -name "*.ts" | xargs wc -l` (the gather has size metrics)
- ❌ Generic "let me read every file looking for logs" loops (the gather's job)
You MAY still:
- ✅ Read SPECIFIC files cited in findings (verify the issue)
- ✅ Run a SPECIFIC grep to falsify a finding (Popper test, see Phase H1.1)
- ✅ Run the SYSTEM and capture real emitted telemetry (the gather can't model runtime)
- ✅ Probe a SPECIFIC `/health` / `/metrics` endpoint with `curl`
### 0.5 Cross-audit synthesis (read sibling evidence-summary.json files)
Sibling summaries live at `$PROJECT_PATH/audits/.linear-fix/<TICKET>/.<other-audit-id>/evidence-summary.json`. Read them. Use them.
High-value confluences for observability:
- **observability + codeaudit** flag the same silent `catch {}` → it both swallows the error AND has no log: a guaranteed invisible failure.
- **observability + secaudit** flag the same log line → it emits a token/PII into logs: a leak surface.
- **observability + debugaudit** report the same broken flow → debugaudit found the break, observability confirms it produced NO telemetry (the worst case).
- **observability + perfaudit** on the same endpoint → perf found it slow, observability confirms there's no duration metric/span to detect the slowdown in prod.
GitHubで見る