Add agent-first observability to code — structured logs, health endpoints, failure-state persistence, and explicit failure modes — so the next agent hitting a problem at 3am has the signals it needs to diagnose. Use when asked to "add logging", "add observability", "add metrics", "debug later", "make this observable", or when building/refactoring a subsystem that will run unattended (auto-mode engine, background jobs, servers, watchers). Operationalizes VISION.md's "agent-first observability" principle.
75
92%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
This skill is the thinking process for adding it. Not "add logs everywhere" — add the right signals at the right decision points.
Invocation points:
<core_principle>
LOG DECISIONS, NOT ACTIVITY. "Entering function X" is noise. "Dispatched unit slice/S02 after guard check passed because status=pending" is signal. Every log line should answer a question a future debugger will ask.
FAIL LOUDLY AND PERSIST THE REASON. Silent try/catch that returns undefined is an anti-pattern. If something fails, the failure state needs to be somewhere a fresh agent can find it — a JSONL, a status file, a health endpoint.
OBSERVABILITY IS NOT FREE. Every log allocation, every metric, every health check costs CPU and disk. Add only what you would actually read. </core_principle>
Before instrumenting, list what can go wrong:
This map tells you where to instrument. Don't instrument uniformly — instrument at the decision points where these failures would manifest.
For each decision the code makes that could plausibly go wrong later:
Format:
log.info({
event: "unit-dispatched",
unitType: "slice",
unitId: "S02",
reason: "pending",
attempt: 1,
flowId,
});Use the project's existing logger if one exists. In gsd-2, follow the patterns in src/resources/extensions/gsd/activity-log.ts and src/resources/extensions/gsd/journal.ts — structured JSONL, one event per line, with ts, event, and domain-specific fields.
Avoid:
console.log("here") — what does "here" mean in six months?When something fails in a way the caller can't immediately handle, write the failure state to disk:
await writeAtomically(
resolve(".gsd/runtime/last-error.json"),
JSON.stringify({
ts: new Date().toISOString(),
phase: "execute",
unitId,
error: { message, stack, code },
retryCount,
})
);A fresh agent reading .gsd/runtime/ sees what happened last, what was retried, and where the process stopped. Pattern exists already in gsd-2 — reuse the atomic-write.ts helpers and the .gsd/runtime/ and .gsd/forensics/ directories.
For long-running processes:
{status: "healthy" | "degraded" | "down", ...diagnostics}.STATE.md and the health widget. In a server, it's /internal/status with last 10 request summaries.Don't build a metrics empire. Build exactly what you'd check at 3am.
Replace silent handling with explicit:
// Bad
try {
return await db.getUser(id);
} catch {
return null;
}
// Good
try {
return await db.getUser(id);
} catch (err) {
log.error({ event: "db-getuser-failed", userId: id, err: serializeError(err) });
throw new DatabaseError("Failed to load user", { cause: err, userId: id });
}The caller now knows the failure happened, gets an error type it can branch on, and a log line exists for forensics.
Before shipping, cull the ad-hoc instrumentation you used while debugging. Keep only:
Drop:
console.log debug linesThe system prompt says it plainly: "Remove noisy one-off instrumentation before finishing unless it provides durable diagnostic value."
Pick one plausible failure mode from Step 1 and simulate it (inject an error, point at a missing file, break a dependency). Confirm:
If any signal is missing, add it — that's the gap this skill exists to catch.
<anti_patterns>
"Processing user 42 now" vs {event: "user-process-start", userId: 42} — the latter is queryable, the former is not.catch {} or catch (err) { /* ignore */ } without a log is a deferred production incident.</anti_patterns>
<success_criteria>
.gsd/runtime/, /var/log/, a status file).try/catch swallowing errors.</success_criteria>
33c00aa
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.