| name | investigate |
| description | The Infiquetra systematic-debugging engine. Find the ROOT CAUSE of a bug, test failure, error, or unexpected behavior BEFORE any fix — trace the full trigger→symptom causal chain with no gaps, ground every hypothesis in observed evidence, and only then apply a GATED, trivial-scope, self-verified fix. Diagnosis is the primary deliverable: it writes an agent-consumable DEBUG REPORT, routes real implementation work to /work via a /handoff issue, design problems to /brainstorm, and trackable defects to /handoff. READ-ONLY on the world and the saga; never commits, pushes, opens a PR, or deploys. Triggers on "investigate", "debug this", "why is this failing", "trace this error", "root cause", a pasted stack trace / error message / issue ref, or a /qa or /loop hand-in for a deep failure. |
Investigate
Migration evidence contract
The debug report separates observed facts, hypotheses, experiments, the supported root cause, and
unresolved uncertainty. The operator explicitly chooses diagnosis-only or a separately authorized fix
route. A passing reproduction by the diagnosing producer is evidence, not independent certification.
/investigate answers "What is the ROOT CAUSE — and is there a fix small enough to apply safely here?"
It investigates a bug systematically, traces the full causal chain from trigger to symptom before
proposing anything, and treats the diagnosis as the deliverable. The fix is optional, gated, and
deliberately small; real implementation work routes to /work.
This engine is a faithful 3-source merge. The spine — investigate-before-fixing, the causal-chain
gate, and predictions-for-uncertain-links — is a PORT of CE ce-debug. The pattern-signature
table and the enum'd DEBUG REPORT status (DONE / DONE_WITH_CONCERNS / BLOCKED) are GRAFTS
from gstack investigate. The Iron Law ("no fixes without root-cause investigation first") and
the multi-component boundary instrumentation technique are BORROWED from superpowers
systematic-debugging (self-contained here — superpowers is not a runtime dependency).
Position in the lifecycle
/investigate is OFF-CHAIN (like /loop, /doc-review, and /founder-review): it is not a
lifecycle phase, it does not advance lifecycle_phase, and it writes no saga tick. It is a
routed diagnostic lens reachable three ways:
- (a) directly —
/investigate <error | test | issue# | description>;
- (b) via
/loop — when the router meets a failure that wants root-cause work;
- (c) via
/qa — /qa routes deep post-merge failures here for root-cause analysis (/qa's
Phase 6.2 routes deep post-merge root-cause failures here).
It is not on the linear spine (loop/references/dispatch-table.md). Its outputs route back onto the
spine: an applied trivial fix ships through /work or /code-review; a real fix becomes a /handoff
issue that /work then executes; a design problem goes to /brainstorm.
Core principles
- Investigate before fixing — the IRON LAW. NO FIX until you can explain the full causal chain
from trigger to symptom with no gaps. "Somehow X leads to Y" is a gap. The causal-chain GATE
(Phase 2) is the enforcement: you do not enter Phase 3 until the chain is complete. Fixing a symptom
creates whack-a-mole debugging; every symptom patch makes the next bug harder to find.
- Predictions for uncertain links. For each uncertain or non-obvious link in the chain, form a
prediction — something in a different code path or scenario that must also be true if the link is
correct. A wrong prediction with a fix that "works" means you found a symptom, not the cause — the
real cause is still active. When the chain is obvious (missing import, explicit null deref), the chain
explanation itself is the gate; a prediction is for uncertain links only, never a ritual.
- Evidence before hypothesis. Run an assumption audit first — list every "this must be true"
belief and mark it verified (you read the code, checked state, or ran it) or assumed; assumptions
are the most common source of stuck debugging. Then instrument the boundaries: capture the
actual values at each component boundary, never assumed ones. "X seems off" is not evidence;
"X equals null at
file:42 because Y was never initialized under condition Z" is.
- One change at a time; when stuck, diagnose why. No shotgun debugging — one hypothesis, one change,
one test. When stuck, do not try harder; diagnose why you are stuck. Two distinct numeric
gates govern this (kept separate — see below): the Phase 2 hypothesis-exhaustion gate and the
Phase 3 3-failed-fix-attempts gate.
- Diagnosis-PRIMARY; the fix is GATED, trivial-scope, and self-verified. The DEBUG REPORT is the
deliverable. The user chooses fix-vs-diagnosis. Only a trivial / single-concern fix is applied
inline (test-first + the engine's own verification); any real implementation work routes to
/work. /investigate never commits, pushes, opens a PR, or deploys.
- Read-only on the world and the saga.
gh and saga.py are used read-only (restore /
ticks for evidence; never mint, never save). Real fixes route to /work; trackable defects route
to /handoff; design problems route to /brainstorm. Large or parallel read-only investigation is
offered a backend (operator-choice), never auto-launched.
- Leave the system smarter. The deliverable is an agent-consumable DEBUG REPORT a future agent
can act on cold. A non-obvious root cause is promoted (gated, selective) to the engineering
journal
LEARNINGS.md; a localized mechanical fix with no generalizable insight is skipped silently.
The two distinct numeric gates
These are two separate counters — do not merge them into one "3-strike" rule:
- Phase 2 — HYPOTHESIS-EXHAUSTION gate. When 2-3 hypotheses are exhausted without confirmation,
STOP and run the smart-escalation table (
references/methodology.md). This is the gstack
"if 3 hypotheses fail → STOP, this may be architectural" numeric form. It counts hypotheses.
- Phase 3 — 3-FAILED-FIX-ATTEMPTS gate. After 3 applied fixes fail, question the architecture
and return to root-cause (Phase 2). This counts applied fix attempts, not hypotheses. A failed fix
with a wrong root cause is a Phase-2 problem wearing a Phase-3 costume.
Interaction method
Ask one blocking question through the current session for choices from a known
set (fix-vs-diagnosis-vs-rethink, an execution backend for large/parallel
read-only investigation, the trivial-bug fast-path apply/skip). Ask one question
per turn, stop until the operator answers, and never silently skip it. Do not ask questions by default —
investigate first (read code, run tests, trace). Ask only when a genuine ambiguity blocks
investigation and cannot be resolved by reading code or running tests.
In a channel session (redis-channel active), the capability receipt does not prove structured interaction — inline the choices in
your reply text instead, following the canonical channel-inline convention in
saga/skills/brainstorm/SKILL.md (do not duplicate its wording here).
Use repo-relative paths in every generated document. Absolute paths break portability across machines and
worktrees. (The one exception is a saga --saga-id value — a derived id, not a path.)
Phase 0 — Triage
Parse the input and reach a clear problem statement. The input is an error message, a test path,
a GitHub issue ref, or a free-text description of broken behavior. Take it from command arguments
or the active artifact.
Issue reference (#N, org/repo#N, a github.com URL): fetch it read-only and read the full
comment thread, not just the opening post:
gh issue view <N> --json title,body,comments,labels
Comments frequently carry updated repro steps, narrowed scope, prior failed attempts, or a pivot to a
different suspected cause; treating the opening post as the whole picture sends the investigation the
wrong way. Everything else (stack traces, test paths, error messages, descriptions) is the problem
statement.
Trivial-bug fast-path. If the cause is immediately readable from the input (single-file typo, missing
import, obvious null deref / off-by-one with a one-line fix) and verification needs no deep tracing,
present the cause and the proposed one-line fix, then run the Phase 2 fix-vs-diagnosis gate before
editing — the fast-path saves investigation ceremony, not the user's choice. If the user picks fix, run
Phase 3's workspace/branch check, apply it, self-verify (fresh-reproduce), and skip to the Phase 4 DEBUG
REPORT. If diagnosis-only, write the report and stop. When in doubt, run the full framework — a wrong
root cause costs more than the ceremony.
Prior-attempt awareness. Only when the user signals prior failure ("keeps failing", "I've been
trying", "stuck"), ask what they already tried before investigating — this avoids repeating dead ends and
is one of the few cases where asking first is right.
Saga evidence (READ-ONLY). If a work-thread saga exists for this change, read it for evidence —
never mint or write it:
python3 plugins/saga/scripts/saga.py restore --saga-id <issue-N|task-slug>
python3 plugins/saga/scripts/saga.py ticks --saga-id <issue-N|task-slug>
Then proceed to Phase 1.
Phase 1 — Investigate (read-only on the world)
See references/methodology.md for the full recipes.
1.1 Reproduce. Confirm the bug exists and understand its behavior — run the test, trigger the error,
follow the reported steps. For a UI surface, drive the running app with the installed
chrome-devtools / playwright MCP (read console + network). If it does not reproduce after 2-3 attempts,
use the intermittent-bug techniques in the reference; if it cannot reproduce at all here, document what
was tried and what conditions appear missing.
1.2 Environment sanity. Before deep tracing, confirm the environment is what you think — branch,
dependencies installed/up-to-date, expected runtime version, required env vars present, no stale build
artifacts, dependent local services running when the bug plausibly involves them. Stale node_modules
/ artifacts are a frequent false lead. The full checklist is in references/methodology.md.
1.3 Trace backward. Trace data flow backward from the symptom to where valid state first became
invalid. Read the stack trace bottom-to-top (the bottom frame is the symptom; the cause is
upstream), then instrument the boundaries around the first frame with invalid data to capture the
actual values. For a bug crossing subsystems, use multi-component boundary instrumentation — log
what enters and exits every boundary in one run and read the log linearly; the boundary where data
first stops matching expectation is the failing layer. Do not stop at the first function that looks
wrong — the cause is where bad state originates.
1.4 Recent changes + evidence. As you trace, check recent changes (git log --oneline -10 -- <file>,
git blame). If the bug is a regression ("it worked before"), use git bisect (recipe in the
reference). Harvest evidence from gh (issue/PR/check output, read-only), application logs, the saga
ticks from Phase 0, and any prior-session skeletons — all read-only.
Phase 2 — Root cause
Reminder: investigate before fixing. No fix until the full causal chain has no gaps.
Assumption audit (first). List every "this must be true" belief your understanding depends on and
mark each verified or assumed (principle 3). Many "wrong hypotheses" are correct hypotheses tested
against a wrong assumption.
Pattern-signature match. Check the symptom against references/pattern-taxonomy.md — gstack's 6
signatures (race / null / state-corruption / integration / config-drift / stale-cache) plus the
infiquetra serverless row (cold-start / IAM-permission / eventual-consistency-DynamoDB / throttling /
env-or-SSM-drift). Pattern-matching is cheap and points the trace at the right place first.
Form hypotheses, ranked by likelihood. For each:
- what is wrong and where (
file:line);
- ≥1 concrete observation that supports it — a runtime value, a log line, an instrumented boundary
capture, a behavior delta against a working case. "X seems off" is theorizing; go back to Phase 1 and
instrument;
- the step-by-step causal chain from trigger to symptom;
- for uncertain links — a prediction (principle 2). Obvious chains skip the prediction.
Causal-chain GATE. Do not proceed to Phase 3 until the full chain — trigger through every step to
symptom — has no gaps. The user may explicitly authorize proceeding with the best-available
hypothesis if investigation is stuck.
Hypothesis-exhaustion gate (Phase 2's numeric gate). When 2-3 hypotheses are exhausted, STOP and run
the smart-escalation table (references/methodology.md): different-subsystem scatter → design
problem (suggest /brainstorm); self-contradicting evidence → wrong mental model, re-read without
assumptions; works-locally-fails-elsewhere → environment problem; fix-works-but-prediction-wrong →
symptom, keep investigating.
Parallel read-only sub-agents (offer). When hypotheses are evidence-bottlenecked across clearly
independent subsystems, OFFER a backend per ../../references/operator-choice.md (inline /
multi-agent-consensus) to dispatch read-only probes in parallel — each with one
explicit hypothesis and a structured evidence-return format, no edits. Never auto-spawn; skip when
hypotheses depend on each other. Parallel sub-agents use generic Explore / Task agents (this
plugin has no agents/ dir).
Source lineage: team-execution and cc-workflows-ultracode both map to
multi-agent-consensus and are not offered separately.
Present findings + the gate. Present the root cause (causal-chain summary with file:line), the
proposed fix and which files would change, the recommended regression test, and whether existing tests
should have caught it. Then run the fix-vs-diagnosis-vs-rethink gate via a structured blocking interaction:
- Fix it now — proceed to Phase 3 (only applies the fix if it is trivial/single-concern; else
diagnose + route to
/work).
- Diagnosis only — I'll take it from here — skip Phase 3, write the report (Phase 4), stop.
- Rethink the design — only when the root cause reveals a design problem (a wrong responsibility
or interface, wrong/incomplete requirements, or every fix is a workaround). Route to
/brainstorm.
Size alone never makes a bug a design problem.
Phase 3 — Fix (GATED, optional, trivial-scope, own verification)
Run this phase only if the user chose "Fix it now" and the fix is trivial / single-concern.
If the proper fix is real implementation work, diagnose and route to /work instead — do not grind a
big change in here.
Reminder: one change at a time.
Workspace / branch check. Before editing: git status — if the user has uncommitted work in files
that need changing, confirm before editing. If on the default branch, ask whether to create a feature
branch (detect the default via main / master / git rev-parse --abbrev-ref origin/HEAD with the
origin/ prefix stripped).
Test-first. (1) Write a failing regression test that captures the bug; (2) verify it fails for
the RIGHT reason — the root cause, not unrelated setup; (3) implement the minimal, root-cause-only
fix — no drive-by refactors, formatting, or unrelated cleanup; (4) the test passes; (5) run the full
suite for regressions; (6) self-review the diff.
Own minimal verification. Fresh-reproduce the original bug and confirm it is fixed — this is the
engine's own verification, not optional. /investigate does NOT route to /qa to verify; the
acceptance gate is a separate, downstream concern.
On a failed fix. Return to Phase 2 and explicitly INVALIDATE the current hypothesis first — state
what evidence ruled it out — then form a new one with its own grounding observation and prediction. Do
not retry variants of the same theory (the rationalization spiral).
3-failed-fix-attempts gate (Phase 3's numeric gate, separate from Phase 2's). After 3 applied fixes
fail, the root-cause identification was likely wrong: question the architecture and return to
Phase 2.
Blast-radius FLAG. A fix touching >5 files is a FLAG — surface the blast radius to the user
and offer a backend — not the inline-vs-route discriminator. The discriminator is
trivial/single-concern vs real implementation work; a 6-file mechanical rename can still be trivial,
and a 1-file change can still be real work that belongs in /work.
Conditional defense-in-depth. When the root-cause pattern exists in 3+ other files (grep the
signature) or the bug would have been catastrophic in production, add guards at the appropriate layers
(entry validation / invariant check / environment guard / diagnostic breadcrumb) per
references/methodology.md. Skip for a one-off with no realistic recurrence path.
/investigate never commits, pushes, opens a PR, or deploys — even after a successful self-verified
fix. Shipping is /work / /code-review's job.
Phase 4 — Report + route
4.1 Emit the DEBUG REPORT. Write the agent-consumable report to:
docs/investigations/<slug>-<date>.md
Use the enum'd shape in references/debug-report.md: Symptom / Root cause (causal chain with
file:line) / Fix (or "diagnosis only") / Evidence / Regression-test path / Related /
Status (DONE / DONE_WITH_CONCERNS / BLOCKED).
4.2 Learning capture — BOTH-SPLIT. Two distinct sinks, by what was found:
- Non-obvious root cause → journal
LEARNINGS.md (gated, selective): append a new learning when
the lesson is generalizable (a wrong assumption about a shared dependency, a pattern in 3+ locations).
Skip silently when the fix is mechanical with no insight. Promotion is a pure append per the journal
rules; offer it neutrally when the lesson is one sentence.
- Trackable confirmed defect →
/handoff (as a defect-type SDLC issue, --issue-type defect):
the report is agent-consumable EVIDENCE, not a handoff source. Open the defect by describing the
bug with the report LINKED as evidence inside the issue. NEVER pass the report path to
handoff_envelope's classifier — infer_maturity keys on docs/plans/ / docs/brainstorms/ etc.
and does not recognize docs/investigations/, so it would fall through to requirements-ready and
mis-classify the report. See references/debug-report.md.
4.3 Route per loop/references/dispatch-table.md (read it; never restate it):
- inline fix applied + self-verified →
/work or /code-review to SHIP it via a PR (the fix is
on a branch; /investigate does not push it);
- real fix needed →
/handoff → SDLC issue → /work executes it (NOT by handing /work a
docs/investigations/ path — /work consumes a plan path, a GitHub issue, or a resume request);
- design problem →
/brainstorm;
- diagnosis-only → stop.
There is NO saga write — /investigate is off-chain and saga READ-ONLY.
Hard boundary
/investigate investigates, diagnoses, optionally applies a trivial self-verified fix, writes the DEBUG
REPORT, and routes — then stops. It does NOT:
- mutate the world or the saga —
gh / git / saga.py are READ-ONLY (restore / ticks for
evidence only; never save, never mint);
- commit, push, open / update / merge a PR, or deploy — even after a successful fix;
- file SDLC issues — mission-control owns the SDLC; defects route through
/handoff;
- route to
/qa to verify — it does its own fresh-reproduce verification; the acceptance gate is
downstream and separate;
- write the saga — off-chain, no
lifecycle_phase advance, no tick;
- do real implementation work inline — that routes to
/work; only trivial/single-concern fixes
apply here;
- path-classify the DEBUG REPORT — never pass
docs/investigations/... to handoff_envelope; link
it as evidence in a described DEFECT instead.
fix is this engine's identity verb — gated-allowed, trivial-scope, self-verified. It is never the
default action; the diagnosis is.
Reference files
references/methodology.md — the full procedure: triage (trivial fast-path + prior-attempt);
investigate (env-sanity checklist + backward-trace recipe + multi-component instrumentation +
git bisect); root-cause (assumption audit + hypotheses-with-evidence + predictions + causal-chain
gate + smart-escalation table + the hypothesis-exhaustion gate + parallel read-only sub-agent dispatch
via ../../../references/operator-choice.md); fix (workspace/branch check + test-first + minimal-diff +
own minimal verification + failed-fix invalidation + the 3-failed-fix-attempts gate + the >5-file
blast-radius FLAG + conditional defense-in-depth).
references/pattern-taxonomy.md — gstack's 6 bug signatures + the infiquetra serverless addition with
a symptom→suspect map, and the anti-patterns catalog (shotgun debugging, confirmation bias, "it works
now move on", prediction quality bad-vs-good, rationalization-spiral red flags).
references/debug-report.md — the DEBUG REPORT template (the gstack enum'd shape), the journal-
LEARNINGS promotion template, and the /handoff defect-routing note (report = evidence, fix reaches
/work via a /handoff ISSUE, never via the report path through the classifier).
../../references/operator-choice.md — the 3-backend contract for offering a backend for large/parallel
read-only investigation.
loop/references/dispatch-table.md — the outbound routing reference (read, never restate).
../brainstorm/SKILL.md — the canonical channel-inline convention (cite, never duplicate).
../../references/saga-spec.md — the saga contract (restore / ticks; /investigate is read-only).