T-913K-friction-incident-log-infrastructure
Status: closed/superseded · Impact: medium · Complexity: large
The SDLC protocol’s friction-tracking story today is “post-mortems in task files.” That captures
per-task friction beautifully but makes cross-task patterns invisible: when something fails for the
third time in a row, we have to spelunk three post-mortems by hand to notice. The proposed remedy is
a structured incident log — every time a /sdlc:task-work, /sdlc:task-close-out,
/sdlc:pr-respond, or other lifecycle skill hits a known failure mode (API socket close, lease
conflict, quality-gate false positive, worktree path mismatch, etc.), a record gets written to
.sdlc/incidents/. The log is queryable: “show me every API-socket-close in the last 30 days”
becomes one command, not a manual diff across post-mortems. Future task-spawning decisions reach for
data instead of vibes — the threshold for “this is worth fixing” moves from “I noticed it once” to
“this is the N-th occurrence in M runs.”
The triggering moment was T-JXBQ-task-work-warns-on-long-sub-agent-prompt: one sub-agent crashed
with API Error: socket connection closed unexpectedly, and the spawned-task proposed adding a
prompt-length warning. The user pushed back: with one data point, we can’t tell whether prompt
length was the cause vs. flaky API vs. model timeout. Without evidence, the fix is speculation. This
task builds the substrate that makes evidence available.
| Location | Role today |
|---|---|
.sdlc/incidents/ | Does not exist. |
apps/sdlc/skills/*/SKILL.md post-mortem section | The only friction-capture mechanism today. Captures per-task; cross-task patterns are invisible. |
apps/sdlc/lib/services/lease/reconcile.ts | Detects active anomalies in current state (dangling leases, missing PRs, etc.). Doesn’t capture historical friction — it’s a snapshot, not a timeseries. |
apps/sdlc/skills/task-work/SKILL.md failure paths | When a sub-agent crashes, lease transition fails, quality gate hits false positives, etc., the skill surfaces the error to the user but doesn’t write any structured record. |
Proposed
Section titled “Proposed”A new shared incident-logging substrate at apps/sdlc/lib/services/incidents/ (library) and
.sdlc/incidents/ (per-project storage). Each incident is a structured record (YAML or JSON)
capturing:
- Timestamp (UTC, ISO 8601)
- Class (one of an enumerated taxonomy — see below)
- Context (task ID, skill name, git SHA, free-form details)
- Resolution (if known at capture time — “user retried”, “fixed by re-baseline”, “wontdo”, etc.)
Auto-capture from skill failure paths where feasible. The operator can also record incidents
manually via a /sdlc:incident skill for things the protocol didn’t auto-catch.
A surface for querying — a registry op with subcommands (list, summary, class <name>), under
its own noun or an existing one per D-H7FS-op-substrate-surface, or growth in the lease
reconcile reporter to include “incidents this period” alongside its anomaly views.
Initial taxonomy (to be refined during research):
api-socket-close— sub-agent or skill dispatch died with a socket-close errorsubagent-crash— sub-agent returned an error verdictlease-conflict— Step 2a’s acquire lost the CAS racelease-stolen— reacquire took an expired leasequality-gate-false-positive— gate fired on baseline-shift summary linesworktree-path-mismatch— script wrote to or read from the wrong.sdlc/directorystart-task-cache-miss— historical; obsoleted by the lease-cache dropspec-pr-blocks-impl— historical; obsoleted by the Step 2 branch-prefix fixmanual— operator-recorded, no automated class fits
The taxonomy grows as patterns emerge. The schema should make adding new classes cheap.
Approach
Section titled “Approach”(High-level — this is the design-needed task.)
- Inventory current failure modes. Walk the SKILL.md failure paths across
task-work,task-close-out,pr-respond,orchestrate. List the distinct failure modes that today surface to the user without leaving a record. That list seeds the taxonomy. - Design the record schema. Decide on YAML vs JSON, file-per-incident vs append-only log,
per-project location, what fields are required vs optional. Settle on an
apps/sdlc/lib/model/entities/incident/schema.tsif going the entity route — that wires into existing entity-audit machinery. - Build the library + query op.
apps/sdlc/lib/services/incidents/exposesrecordIncident({ class, context, ...fields }). A registry op lists / summarises / filters. - Auto-capture instrumentation. Add
recordIncidentcalls in the most common failure paths: lease conflict, sub-agent verdict-error, quality-gate false positive (where detectable), worktree path mismatch (now closed but worth instrumenting for future analogues). - Surface in reconcile or new skill. Either extend the lease reconcile reporter with an
“incidents (last N days)” view, or build a dedicated
/sdlc:incidentsskill. Pick during design. - Manual-entry skill.
/sdlc:incident <class> <message>for incidents the protocol didn’t auto-catch. - Documentation. A short convention doc at
apps/sdlc/conventions/incident-log.mddescribing the schema, the taxonomy, and when to record manually.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
apps/sdlc/lib/services/incidents/ | new | Library exposing recordIncident() and friends. |
apps/sdlc/lib/services/incidents/tests/ | new | Unit tests. |
apps/sdlc/lib/model/entities/incident/schema.ts | new | If incidents become an entity type. |
apps/sdlc/lib/services/incidents/ops/ | new | Registry ops: list, summary, filter. |
apps/sdlc/skills/incidents/ (or extend reconcile) | new | Skill surface for the operator. |
apps/sdlc/skills/task-work/SKILL.md | modify | Add recordIncident calls in failure paths. |
apps/sdlc/skills/task-close-out/SKILL.md | modify | Same. |
apps/sdlc/skills/pr-respond/SKILL.md | modify | Same. |
apps/sdlc/skills/orchestrate/SKILL.md | modify | Same. |
apps/sdlc/conventions/incident-log.md | new | Convention doc. |
Acceptance criteria
Section titled “Acceptance criteria”(These will tighten during the design pass — this is a backlog task pending research.)
- AC-1:
recordIncident({ class, context, ...fields })inapps/sdlc/lib/services/incidents/writes a structured record to<project-root>/.sdlc/incidents/<YYYY-MM-DD-HHMMSS>-<class>.yaml(or whatever shape the design pass settles on). - AC-2: At least three failure paths in
apps/sdlc/skills/write incidents automatically — covering at minimum lease conflict, sub-agent verdict error, and a third class to be chosen during design. - AC-3: An incidents summary op (e.g.
sdlc incidents summary --last 30d; final path per the design pass) produces a digest likeapi-socket-close: 3, lease-conflict: 1, ...so the operator can see frequency at a glance. - AC-4: An operator manually records an incident via
/sdlc:incident <class> "<message>"and it shows up in the nextsummarydigest. - AC-5: Auto-captured incidents include enough context (task ID, skill name, SHA, error class) that a follow-up task can be opened with concrete evidence rather than vibes.
- AC-6: All existing tests pass; project quality checks pass.
Out of scope
Section titled “Out of scope”- A web dashboard for incidents. Plain CLI output is fine; consumers can build their own dashboards.
- Cross-project incident aggregation (incidents from multiple repos in one view). Per-project for now.
- Telemetry or remote logging. The log lives in the project’s working tree; never leaves the operator’s machine.
- Auto-spawning follow-up tasks when an incident class crosses a threshold. Tempting but premature — let the operator decide based on the digest.
Dependencies
Section titled “Dependencies”- none
Discovery context
Section titled “Discovery context”User feedback on 2026-05-27 during slice-4 friction triage: “I’d like to start somehow capturing classes of errors numerically — you say it has shown up before in the wild, do you have records of that? Without direct evidence it was prompt length that caused problem the fix is just a guess.”
The triggering moment was T-JXBQ-task-work-warns-on-long-sub-agent-prompt — proposed in a post-mortem with one observation, dropped as cargo-culting. The reframed direction: build the substrate that makes decisions like that data-driven, then reopen the original task only when evidence supports it.
This task is intentionally planning/backlog until a design pass settles the record schema,
auto-capture surface area, and the taxonomy. The user described it as “a backlog item” specifically
— not urgent, but the foundation for better friction-task triage going forward.