skills/observability-contract/SKILL.md
Logging mandate with applicability-aware activation: structured error, audit, and general logging are required only when the task introduces a runtime path, service boundary, or user-facing operation. Triggers at Phase 1 (specification) and Phase 5 (verification).
npx skillsauth add bigeasyfreeman/adlc observability-contractInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Every feature or change with an active observability surface must include structured logging. This is a mandatory deliverable for those tasks, not an afterthought. If it's not logged, it didn't happen.
Before generating the logging contract, record the observability applicability decision:
| Field | Purpose |
|-------|---------|
| observability_applicability.status | active or not_applicable |
| observability_applicability.reason | Concrete reason tied to task class or repo evidence |
| observability_applicability.trigger_fields | Which manifest fields activated or suppressed the overlay |
| observability_applicability.manifest_ref | Pointer to the upstream applicability manifest entry |
If the status is not_applicable, do not invent error, audit, or general logging requirements for that task. Record the suppression and move on.
All three are mandatory for every active observability task.
What: Exception context at every failure point.
Required fields:
Format: Structured JSON, ERROR level.
Rule: Every public function that can fail MUST have error logging.
# GOOD
try:
result = process_order(order_id)
except ProcessingError as e:
logger.error(
"order.processing_failed",
extra={
"order_id": order_id,
"error": str(e),
"correlation_id": ctx.correlation_id,
"input_state": {"status": order.status, "amount": order.amount},
},
exc_info=True,
)
raise
# BAD — silent failure
try:
result = process_order(order_id)
except ProcessingError:
pass
What: State changes — who did what, when, and what changed.
Required fields:
Format: Structured JSON, INFO level. Immutable append-only.
Rule: Every state mutation MUST have an audit log entry.
# GOOD
logger.info(
"order.status_changed",
extra={
"order_id": order_id,
"actor": current_user.id,
"from_state": "pending",
"to_state": "approved",
"correlation_id": ctx.correlation_id,
},
)
# BAD — state changed with no record
order.status = "approved"
db.commit()
What: Operational metrics, health signals, debug breadcrumbs.
Required fields:
Format: Structured JSON, configurable level (DEBUG/INFO).
Rule: Every external API call MUST log request/response metadata (NOT bodies — PII risk). Health-critical operations MUST log timing.
# GOOD
start = time.monotonic()
response = httpx.get(url, headers=headers)
logger.info(
"external_api.call",
extra={
"url": url,
"method": "GET",
"status_code": response.status_code,
"duration_ms": (time.monotonic() - start) * 1000,
"correlation_id": ctx.correlation_id,
},
)
Correlation IDs MUST propagate across service boundaries. Every request gets a correlation ID at the entry point. All downstream calls include it. All log entries include it.
This enables: tracing a single request through the entire system, linking error logs to audit logs to general logs.
The ADLC pipeline itself emits structured audit logs at every phase. This pipeline-level observability is separate from task-level overlay activation:
{
"pipeline_run_id": "uuid",
"phase": 0,
"phase_name": "prd_agent",
"started_at": "ISO8601",
"completed_at": "ISO8601",
"duration_ms": 1234,
"tokens_consumed": 5678,
"outcome": "success",
"details": {},
"errors": []
}
AST-based scan checks:
SWElfare: Error=daemon failures/API errors, Audit=job state changes/config changes, General=phase timing/token usage/health checks
Ratatosk: Error=trade execution failures/data feed errors, Audit=trade decisions/position changes/calibration updates, General=market data freshness/API latency/experiment metrics
Magnus: Error=publish failures/API errors, Audit=editorial decisions/content state changes/voice profile updates, General=engagement metrics/slop scores/pipeline throughput
| Excuse | Rebuttal | |--------|---------| | "Logging adds overhead" | Structured logging overhead is microseconds. Debugging without logs costs hours. | | "We'll add logging when something breaks" | By then you've lost the context you need to diagnose it. | | "The error message is enough" | Error messages without context (input state, correlation ID) are nearly useless. | | "Audit logs are only for compliance" | Audit logs are how you understand what your system actually did. |
development
Discovers and records repo-local approved build paths so agents reuse proven patterns instead of inventing parallel architectures.
development
Scoped maintenance for docs/solutions entries when stale signals, refactors, or explicit user scope require refresh.
documentation
Conditionally captures verified reusable ADLC learnings into docs/solutions after successful closeout.
development
Uses Graphify as ADLC's graph-backed research layer and Beads as an optional dependency-aware task memory layer. Produces evidence for compatibility, reuse, accuracy, dark-code hotspots, and long-horizon handoff.