/investigate
Systematic diagnosis for unknown failures — local environment, tool setup, CI vs local divergence, hook misbehavior, and runtime anomalies. Gathers signals broadly, ranks hypotheses, uses adversarial review (Codex or foundry:challenger) for ambiguous cases, probes each, and
Claude Code
$ npx -y skills add Borda/AI-Rig --skill investigate --agent claude-code
Codex
$ npx skills add Borda/AI-Rig --skill investigate -a codex -y
Cursor
$ npx skills add Borda/AI-Rig --skill investigate -a cursor -y
Gemini CLI
$ npx skills add Borda/AI-Rig --skill investigate -a gemini-cli -y
GitHub Copilot
$ npx skills add Borda/AI-Rig --skill investigate -a github-copilot -y
OpenCode
$ npx skills add Borda/AI-Rig --skill investigate -a opencode -y
Windsurf
$ npx skills add Borda/AI-Rig --skill investigate -a windsurf -y
SKILL.md
investigate.SKILL.mdname: investigate
description: "Systematic diagnosis for unknown failures — local environment, tool setup, CI vs local divergence, hook misbehavior, and runtime anomalies. Gathers signals broadly, ranks hypotheses, uses adversarial review (Codex or foundry:challenger) for ambiguous cases, probes each, and reports root cause with a recommended next action. NOT for known code bugs (/develop:debug (requires `develop` plugin)) or config quality (/foundry:audit). TRIGGER when: unknown failure with no Python traceback — hook not firing, CI passes locally but fails remotely, background agent stalled, behavior inconsistent with config; phrases: \"not working but config looks right\", \"hook not triggering\", \"why isn't X running\". SKIP: Python traceback present (use develop:debug (requires `develop` plugin)); known code bug with repro (use develop:fix (requires `develop` plugin)); pure config quality check (use foundry:audit)."
argument-hint: <symptom, question, or failing command> [--fast] [--keep "<items>"]
allowed-tools: Read, Write, Bash, Grep, Agent, Skill, TaskList, TaskCreate, TaskUpdate, AskUserQuestion
effort: high
<objective>
Diagnose unknown failures: broken local setup, environment mismatch, tool misbehavior, hook problems, CI vs local divergence, permission errors, runtime anomalies. Gather signals broadly, eliminate hypotheses systematically, report confirmed root cause + recommended next skill. No fixes — diagnosis only. NOT for: known Python test failures with traceback (use `/develop:debug` (requires `develop` plugin)); `.claude/` config quality sweep (use `/foundry:audit`).
</objective>
<inputs>
- **$ARGUMENTS**: required — symptom, question, or failing command, e.g.:
- `"hooks not firing on Save"`
- `"bridge review is unavailable on this machine"`
- `"/foundry:calibrate times out every run"`
- `"CI fails but passes locally"`
- `"uv run pytest can't find conftest.py"`
- **`--fast`**: optional flag — skip Step 4 adversarial Codex review; use when speed matters more than thoroughness, or Codex unavailable.
$ARGUMENTS empty or too vague: use AskUserQuestion: "What exactly is failing or behaving unexpectedly? Include the command and any error output you can share."
</inputs>
<compaction>
- Key boundary 1: end of Step 2 (signals.md written to run-dir), before Step 3 rank hypotheses.
- Key boundary 2: end of Step 3 (hypotheses.md written), refreshed again after each Step 5 probe verdict — so a mid-loop compaction does NOT re-rank or re-probe.
- Preserve: INVESTIGATE_RUN, symptom.txt, signals.md, hypotheses.md paths; adversarial-review path (codex/challenger) if Step 4 ran; probe ledger (hypothesis → Confirmed/Ruled-out/Inconclusive).
- Terminal path: end of Step 6 (report + follow-up gate complete).
</compaction>
<workflow>
**Task hygiene** — task tools may be deferred; load before first use: `ToolSearch(query="select:TaskList,TaskCreate,TaskUpdate,TaskGet", max_results=4)`. Call `TaskList` first and triage each task it returns: `completed` if work clearly done, `deleted` if orphaned, keep `in_progress` only if genuinely continuing. Never spend a turn on bookkeeping alone — every `TaskCreate`/`TaskUpdate` ships in the same response as the next substantive tool call; one exception, `TaskUpdate(completed)` immediately before a long output block (`rules/task-lifecycle.md`).
**Task tracking**: TaskCreate tasks for Gather, Hypothesise, Probe, Report in the same response as the Step 1 block; each later `TaskUpdate` rides with that step's first real tool call — zero bookkeeping-only turns (measured: ~7 per run before this rule).
**Turn budget** — the profiled runs were 94% single-call turns, and every turn re-reads the whole live context. Each step below is one bash block plus the Read/Grep/Write calls it needs, all issued together in one response; independent probes go in one response too. Never split a block to look at half its output.
Step 1: Parse symptom and scope
One block: flag parsing, stale-ledger clear, and the run directory Step 2 needs. Run-dir creation has no dependency on the scoping below, and a second bash block would cost a whole turn — a turn re-reads the entire live context (`claude-config.md` §Turn Batching).
PLUGIN_ROOT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/resolve_plugin_root.py" --plugin-name foundry) || exit $?; export PLUGIN_ROOT
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
python "$PLUGIN_ROOT/bin/parse-skill-flags.py" --flags fast --keep-state investigate -- "$ARGUMENTS" >/dev/null # timeout: 5000 — no eval; investigate-{fast,clean-args,keep-items}-${CSID}, clears stale contract
IFS= read -r ARGUMENTS < "${TMPDIR:-/tmp}/investigate-clean-args-${CSID}" 2>/dev/null || ARGUMENTS=""
rm -f "${TMPDIR:-/tmp}/investigate-verdicts-${CSID}" # stale probe ledger # timeout: 3000
INVESTIGATE_RUN=".temp/investigate/$(date -u +%Y-%m-%dT%H-%M-%SZ)"
mkdir -p "$INVESTIGATE_RUN"
echo "$INVESTIGATE_RUN" > "${TMPDIR:-/tmp}/investigate-run-path-${CSID}" # persist; re-read in later steps
echo "INVESTIGATE_RUN=$INVESTIGATE_RUN" # bash vars don't persist; read from stdout
printf '%s\n' "$ARGUMENTS" | tr ' ' '\n' | grep -E '^--' | sed 's/^/UNKNOWN_FLAG=/' # feeds unsupported-flag checkFrom $ARGUMENTS extract:
- **What**: specific failure or anomaly
- **Where**: local / CI / both; which tool or command; which skill or hook if applicable
- **When**: started recently (after change) or always broken; intermittent or consistent
**Unsupported flag check** — after all supported flags extracted (`--fast`, `--keep`), every `UNKNOWN_FLAG=--<token>` line printed by the Step 1 block is a remaining `--<token>`. Found: invoke `AskUserQuestion` with question text `` ! Unknown flag(s): `--<token>`. Supported: `--fast`, `--keep`. `` — (a) **Abort** (stop, re-invoke with correct flags) · (b) **Continue ignoring** (skip unknown flags, proceed). On Abort: stop.
Step 2: Gather signals
`$INVESTIGATE_RUN` is created in Step 1 and holds for every
Read more
name: investigate description: "Systematic diagnosis for unknown failures — local environment, tool setup, CI vs local divergence, hook misbehavior, and runtime anomalies. Gathers signals broadly, ranks hypotheses, uses adversarial review (Codex or foundry:challenger) for ambiguous cases, probes each, and reports root cause with a recommended next action. NOT for known code bugs (/develop:debug (requires `develop` plugin)) or config quality (/foundry:audit). TRIGGER when: unknown failure with no Python traceback — hook not firing, CI passes locally but fails remotely, background agent stalled, behavior inconsistent with config; phrases: \"not working but config looks right\", \"hook not triggering\", \"why isn't X running\". SKIP: Python traceback present (use develop:debug (requires `develop` plugin)); known code bug with repro (use develop:fix (requires `develop` plugin)); pure config quality check (use foundry:audit)." argument-hint: <symptom, question, or failing command> [--fast] [--keep "<items>"] allowed-tools: Read, Write, Bash, Grep, Agent, Skill, TaskList, TaskCreate, TaskUpdate, AskUserQuestion effort: high
<objective>
Diagnose unknown failures: broken local setup, environment mismatch, tool misbehavior, hook problems, CI vs local divergence, permission errors, runtime anomalies. Gather signals broadly, eliminate hypotheses systematically, report confirmed root cause + recommended next skill. No fixes — diagnosis only. NOT for: known Python test failures with traceback (use `/develop:debug` (requires `develop` plugin)); `.claude/` config quality sweep (use `/foundry:audit`).
</objective>
<inputs>
- **$ARGUMENTS**: required — symptom, question, or failing command, e.g.:
- `"hooks not firing on Save"`
- `"bridge review is unavailable on this machine"`
- `"/foundry:calibrate times out every run"`
- `"CI fails but passes locally"`
- `"uv run pytest can't find conftest.py"`
- **`--fast`**: optional flag — skip Step 4 adversarial Codex review; use when speed matters more than thoroughness, or Codex unavailable.
$ARGUMENTS empty or too vague: use AskUserQuestion: "What exactly is failing or behaving unexpectedly? Include the command and any error output you can share."
</inputs>
<compaction>
- Key boundary 1: end of Step 2 (signals.md written to run-dir), before Step 3 rank hypotheses.
- Key boundary 2: end of Step 3 (hypotheses.md written), refreshed again after each Step 5 probe verdict — so a mid-loop compaction does NOT re-rank or re-probe.
- Preserve: INVESTIGATE_RUN, symptom.txt, signals.md, hypotheses.md paths; adversarial-review path (codex/challenger) if Step 4 ran; probe ledger (hypothesis → Confirmed/Ruled-out/Inconclusive).
- Terminal path: end of Step 6 (report + follow-up gate complete).
</compaction>
<workflow>
**Task hygiene** — task tools may be deferred; load before first use: `ToolSearch(query="select:TaskList,TaskCreate,TaskUpdate,TaskGet", max_results=4)`. Call `TaskList` first and triage each task it returns: `completed` if work clearly done, `deleted` if orphaned, keep `in_progress` only if genuinely continuing. Never spend a turn on bookkeeping alone — every `TaskCreate`/`TaskUpdate` ships in the same response as the next substantive tool call; one exception, `TaskUpdate(completed)` immediately before a long output block (`rules/task-lifecycle.md`).
**Task tracking**: TaskCreate tasks for Gather, Hypothesise, Probe, Report in the same response as the Step 1 block; each later `TaskUpdate` rides with that step's first real tool call — zero bookkeeping-only turns (measured: ~7 per run before this rule).
**Turn budget** — the profiled runs were 94% single-call turns, and every turn re-reads the whole live context. Each step below is one bash block plus the Read/Grep/Write calls it needs, all issued together in one response; independent probes go in one response too. Never split a block to look at half its output.
Step 1: Parse symptom and scope
One block: flag parsing, stale-ledger clear, and the run directory Step 2 needs. Run-dir creation has no dependency on the scoping below, and a second bash block would cost a whole turn — a turn re-reads the entire live context (`claude-config.md` §Turn Batching).
PLUGIN_ROOT=$(python "${CLAUDE_PLUGIN_ROOT}/bin/resolve_plugin_root.py" --plugin-name foundry) || exit $?; export PLUGIN_ROOT
export CSID="${CLAUDE_CODE_SESSION_ID:-$PPID}"
python "$PLUGIN_ROOT/bin/parse-skill-flags.py" --flags fast --keep-state investigate -- "$ARGUMENTS" >/dev/null # timeout: 5000 — no eval; investigate-{fast,clean-args,keep-items}-${CSID}, clears stale contract
IFS= read -r ARGUMENTS < "${TMPDIR:-/tmp}/investigate-clean-args-${CSID}" 2>/dev/null || ARGUMENTS=""
rm -f "${TMPDIR:-/tmp}/investigate-verdicts-${CSID}" # stale probe ledger # timeout: 3000
INVESTIGATE_RUN=".temp/investigate/$(date -u +%Y-%m-%dT%H-%M-%SZ)"
mkdir -p "$INVESTIGATE_RUN"
echo "$INVESTIGATE_RUN" > "${TMPDIR:-/tmp}/investigate-run-path-${CSID}" # persist; re-read in later steps
echo "INVESTIGATE_RUN=$INVESTIGATE_RUN" # bash vars don't persist; read from stdout
printf '%s\n' "$ARGUMENTS" | tr ' ' '\n' | grep -E '^--' | sed 's/^/UNKNOWN_FLAG=/' # feeds unsupported-flag checkFrom $ARGUMENTS extract:
- **What**: specific failure or anomaly
- **Where**: local / CI / both; which tool or command; which skill or hook if applicable
- **When**: started recently (after change) or always broken; intermittent or consistent
**Unsupported flag check** — after all supported flags extracted (`--fast`, `--keep`), every `UNKNOWN_FLAG=--<token>` line printed by the Step 1 block is a remaining `--<token>`. Found: invoke `AskUserQuestion` with question text `` ! Unknown flag(s): `--<token>`. Supported: `--fast`, `--keep`. `` — (a) **Abort** (stop, re-invoke with correct flags) · (b) **Continue ignoring** (skip unknown flags, proceed). On Abort: stop.
Step 2: Gather signals
`$INVESTIGATE_RUN` is created in Step 1 and holds for every
Practical agent workflows for Python, ML, and open-source maintenance. AI-Rig turns recurring work—scoping a change, reproducing a bug, reviewing a pull request, running an experiment, or checking release readiness—into explicit workflows with specialist
More skills from other plugins.
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…
ask-matt
Ask which skill or flow fits your situation. A router over the skills in this repo.
Questions about investigate.
- Which coding agents can use investigate?
- investigate installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.

