Skip to content

/gsd forensics

/gsd forensics is the deep investigation tool for when auto-mode fails in ways that aren’t obvious from the surface. It programmatically scans activity logs, the metrics ledger, crash locks, and doctor diagnostics to build a structured forensic report. It then detects anomalies — stuck loops, cost spikes, timeouts, missing artifacts, error traces — and hands the whole package to the LLM for interactive investigation.

Unlike /gsd doctor which checks structural integrity, forensics focuses on behavioral anomalies: did a unit run too many times? Did costs spike unexpectedly? Did something time out? Did a completed unit leave missing artifacts?

Forensics cannot run while auto-mode is active — it needs to inspect the state without interference.

/gsd forensics

The command prompts you to describe what went wrong. This problem description helps the LLM focus its investigation. If you provide the description as an argument, it skips the prompt:

/gsd forensics auto-mode got stuck on task T03 and kept retrying

The first time you run forensics (when forensics_dedup is not set in your global preferences), GSD shows an interactive choice:

  • Enable duplicate detection — Before filing a GitHub issue, the LLM will search closed issues, open PRs, and merged PRs to avoid creating duplicates. Uses additional AI tokens for the search.
  • Skip for now — File without checking for duplicates.

If you enable it, the preference is saved to your global GSD preferences file (~/.gsd/agent/preferences.md) as forensics_dedup: true. You can also set it manually.

The forensic report builder collects data from five sources:

  1. Activity logs (.gsd/activity/*.jsonl) — Scanned from both the active auto-worktree and the project root. All matching JSONL files from each directory are sorted alphabetically (the filename encodes a sequence number, unit type, and unit ID) and the five most recent from each directory are read. Results are then merged and sorted by modification time, keeping the five most recent overall. Each log records tool calls, reasoning traces, errors, and files written during a unit’s execution. Worktree logs take priority over root logs when both exist.
  2. Metrics ledger (.gsd/metrics.json) — Cost, token count, timing, and model data for every completed unit. Used to compute per-type averages and detect cost spikes. The ten most recent units are included in the report.
  3. Crash lock (.gsd/auto.lock) — Written at auto-mode startup with PID, unit type, unit ID, and session file path. If the PID is dead, it’s a crash indicator.
  4. Doctor checks — The full doctor scan runs internally. Error-severity issues become forensic anomalies.
  5. Completed keys (.gsd/completed-units.json) — List of units marked as done. Cross-referenced against expected artifacts in both the project root and the active worktree to detect stale completions.
TypeSeverityWhat It DetectsTrigger
stuck-loopwarning/errorSame unit dispatched multiple timesCount ≥ 2 (warning), ≥ 3 (error)
cost-spikewarningUnit cost exceeds 3× the average for its typePer-unit cost / type average > 3.0
timeoutwarningTimeout patterns in activity logsgsd-auto-timeout-recovery in tool calls, or idle/hard/timeout-recovery keywords in last reasoning
missing-artifacterrorCompleted unit but expected artifact missing or invalidverifyExpectedArtifact() returns false at both root and worktree
crasherrorCrash lock with dead PIDLock exists and isLockProcessAlive() returns false
doctor-issueerrorError-severity structural issue from doctorDoctor scan finds error-level issues
error-tracewarningErrors recorded in activity log tracestrace.errors.length > 0

Every forensic report is saved as a timestamped markdown file in .gsd/forensics/ (e.g., report-2026-03-17-14-30-22.md). This creates an audit trail of investigations. The report includes all anomalies, recent unit history, activity log traces, doctor issues, and crash lock state.

Before writing, the report is redacted: absolute paths are replaced with relative equivalents, home directories are replaced with ~, and API keys, Bearer tokens, and environment variable values are scrubbed.

The report is formatted into a structured prompt (capped at 30KB) and dispatched to the LLM with triggerTurn: true. The LLM receives the problem description, all anomalies, a table of the ten most recent units from the metrics ledger, the top three activity log traces (tool calls, files written, errors, last reasoning), doctor issues, crash lock state, metrics summary, and the path to the GSD extension source code with a comprehensive domain-organized source map.

The source map organizes GSD’s source files by domain so the LLM can navigate directly to relevant code:

DomainCoverage
Auto-mode engineDispatch loop, stuck detection, timeout recovery, artifact verification, worktree sync, budget
State & persistenceState derivation, file paths, JSON persistence, atomic writes
Forensics & recoveryTrace extraction, crash lock lifecycle, session lock
Metrics & telemetryCost/token ledger, skill telemetry, token counting
Health & diagnosticsDoctor checks, environment checks, issue formatting
Prompts & contextPrompt loading, prompt cache optimization, context budget
Git & worktreesGit service, worktree manager, self-healing
CommandsCommand dispatcher, inspect commands, maintenance commands

The LLM follows a structured investigation sequence:

  1. Analyze anomalies and trace data — treat automated findings as leads, not conclusions
  2. Read source code — navigate to the candidate files to confirm or deny hypotheses; do not guess what code does
  3. Trace the code path — follow function calls from entry point through to the failure
  4. Clarify — may ask up to 2 questions if the report is genuinely ambiguous (skipped if data is sufficient)
  5. Explain — what happened, why it happened (with file:line references), the problematic code snippet, and how to recover

Then the LLM offers GitHub issue creation at gsd-build/gsd-2 with labels bug, auto-generated. The issue is created via gh issue create --repo gsd-build/gsd-2 using the bash tool (not the github_issues tool, which can’t target a specific repo). The issue template includes GSD version, model, the failing unit, reproduction context, forensic findings, and a concrete fix suggestion — automatically redacted of any user-specific data.

When duplicate detection is enabled, the LLM first searches closed issues, open PRs, and merged PRs using keywords from its diagnosis. It presents any matches and lets you choose to skip issue creation (already fixed), add a comment to an existing issue, or create a new one anyway.

FilePurpose
.gsd/forensics/report-*.mdTimestamped, redacted forensic report
~/.gsd/agent/preferences.mdUpdated when user enables duplicate detection for the first time
FilePurpose
.gsd/activity/*.jsonlActivity logs from project root (last 5 by sequence, merged by mtime)
.gsd/worktrees/<MID>/.gsd/activity/*.jsonlActivity logs from active auto-worktree (merged with root, top 5 overall)
.gsd/metrics.jsonCost and timing metrics for anomaly detection
.gsd/auto.lockCrash detection (PID, unit type, unit ID, session file)
.gsd/completed-units.jsonStale completion detection
.gsd/STATE.mdCurrent project state (active milestone and slice)
.gsd/milestones/*/Doctor scan (run internally)
~/.gsd/agent/preferences.mdGlobal preferences (reads forensics_dedup setting)

Investigating a stuck auto-mode session:

> /gsd forensics
● Describe what went wrong:
auto-mode kept retrying T03 and never moved forward
● Duplicate detection available
Before filing a GitHub issue, forensics can search existing issues and PRs
to avoid duplicates. This uses additional AI tokens for analysis.
> Enable duplicate detection (recommended)
Skip for now
● Building forensic report...
Forensic report saved: .gsd/forensics/report-2026-03-17-14-30-22.md
● Analyzing report...
Found 3 anomalies:
[ERROR] stuck-loop: Unit execute-task/M001/S02/T03 was dispatched 4 times
Repeated dispatch suggests the unit completed but its artifacts
weren't verified, or the state machine kept returning it.
[WARNING] cost-spike: $2.41 vs $0.38 average for execute-task
Unit execute-task/M001/S02/T03 cost 6.3x the average.
May indicate excessive retries or large context.
[WARNING] error-trace: 7 error(s) in execute-task/M001/S02/T03
Error: ENOENT: no such file or directory, open 'dist/api/users.js'
Error: Test suite failed: 3 failing
Error: ENOENT: no such file or directory...
Investigating T03 activity log...
Would you like me to create a GitHub issue for this on gsd-build/gsd-2?

Passing the problem description directly to skip the prompt:

> /gsd forensics crash lock is stale after terminal was killed
● Building forensic report...
Forensic report saved: .gsd/forensics/report-2026-03-19-09-12-44.md
  • forensics — Deep diagnostic investigation prompt
  • /gsd doctor — Structural health checks (forensics runs doctor internally)
  • /gsd status — View current project state
  • /gsd cleanup — Clean up after resolving forensic issues
  • /gsd stop — Stop auto-mode before running forensics