explore · git:20260812.83c0b5b · 2026-08-12 · sha256 8cc3fe0773f97796
explore git:20260812.83c0b5bA
Immutable. This exact content never changes and is served at /api/v1/blob/8cc3fe0773f97796.
---
name: explore
description: Deep codebase reconnaissance with parallel read-only investigators — fans out automatically when a question spans multiple subsystems, options, or cross-cutting concerns, then synthesizes one coherent picture. Use before designing a change, when tracing how something works end to end, or when you need to know the blast radius of touching a shared value.
license: MIT
compatibility: Optional openspec CLI for change awareness. Node.js >= 18 for the bundled interlock-graph CLI.
argument-hint: "[question] [--autonomous]"
allowed-tools: Bash(interlock-graph *) Bash(openspec *) Agent Read Grep Glob
metadata:
type: discovery
autonomy_level: L2
outputs:
- .claude/handoff/explore-<slug>-<timestamp>.md
- openspec/changes/<name>/decisions.md
---
Think deeply. Fan out when breadth is needed. Synthesize into understanding.
**Explore is for thinking, not implementing.** Read files, search code, investigate freely — but never write code and never implement a feature here. If asked to implement, say so and point at `/interlock:spec`. Writing OpenSpec artifacts or an explore brief is capturing thinking, not implementing, and is allowed.
---
## Two modes
**Conversational (default).** A thinking partner. Ask the user which thread to pull when several look interesting. Iterate.
**Autonomous.** Activate on `--autonomous`, "no questions", "don't ask me", "pursue all threads", or when `/interlock:spec` invokes this skill. Then:
1. **No user Q&A.** No AskUserQuestion, no "which thread interests you?" menus. Open threads are work items, not questions.
2. **Fan out on every thread.** Each interesting thread or option gets a read-only investigator. Cap 2–5, merge in synthesis.
3. **Prefer defaults.** Ambiguous product intent → pick a reasonable default, record it under Assumptions Made and Pending Clarifications. Non-blocking. Every one of them is also a ledger row — see below.
4. **Write the explore brief.** Required exit criterion. Follow `${CLAUDE_PLUGIN_ROOT}/shared/EXPLORE-BRIEF.md`. Path: `.claude/handoff/explore-<slug>-<YYYYMMDD-HHMMSS>.md`.
5. **Close short.** Brief path plus a 3–5 line summary. Do not re-dump findings into chat — they are in the brief.
---
## Graph-first reconnaissance, before any fan-out
If `.claude/graph/graph.json` exists (Rule 0 of `${CLAUDE_PLUGIN_ROOT}/shared/TOOL-ECONOMY.md`):
1. Read `.claude/graph/GRAPH_REPORT.md` for hub nodes and module boundaries.
2. Seed investigator scopes with targeted queries:
```bash
interlock-graph query "<subsystem tokens>" --budget 1500
interlock-graph consumers <symbol-or-field> # Pattern 4 / invariant sweep
interlock-graph path <A> <B> # cross-cutting traces
```
3. Scope investigators by **real module nodes and consumer lists**, not by guessed layers.
4. Tell each investigator: locate via graph, then grep for string-keyed and dynamic readers, then Read spans.
If the graph is missing and the question spans 3+ subsystems, build it once (`interlock-graph build .`) before fanning out. Never rebuild when it already exists.
---
## When to fan out
**Fan out** when the question shows any of these:
| Signal | Example |
|--------|---------|
| Multiple subsystems touched | "How does deployment work end to end?" |
| Comparative analysis needed | "Redis or SQLite for this?" |
| Cross-file tracing required | "What validates the uploaded archive?" |
| Several options to research | "What are our options for real-time?" |
| Architecture mapping | "Map how auth flows through the system" |
**Mandatory fan-out — shared or derived value changes.** If the change alters what a value *means* or who reads it, run Pattern 4 per `${CLAUDE_PLUGIN_ROOT}/shared/INVARIANT-SWEEP.md`. This overrides the single-threaded default.
**Stay single-threaded** for conversational back-and-forth, single-file questions, quick clarifications, sequential discovery where A informs B, or when the user is thinking out loud.
When genuinely unsure, start single-threaded and escalate once you realize the question is broader than it looked.
---
## The four patterns
**Pattern 1 — Subsystem mapping.** The question spans several parts of the system. One investigator per stage of the flow. Synthesize into a diagram plus narrative.
**Pattern 2 — Option comparison.** Several viable approaches. One investigator per option, each reporting fit against *this* codebase, not generic pros and cons. Synthesize into a comparison table plus a recommendation.
**Pattern 3 — Layer sweep.** "Where does X happen?" when X could happen at several layers. One investigator per layer (client, API, business logic, persistence, post-processing). Synthesize into what each layer catches and where the gaps are.
**Pattern 4 — Impact analysis.** A change would alter what a value means or who reads it. One investigator per **disjoint** layer of the blast radius. Synthesize into an impact map with severity per area, and explicitly flag readers still consuming the raw, untransformed form.
---
## Investigator rules
1. **Focused prompts.** Not "explore everything about X" — "trace the exact flow of Y through files A, B, C".
2. **Read-only.** Investigators search, read, and report. They never write.
3. **Structured returns.** Key files with paths and line numbers, how it works, connections to other systems, and open questions they could not resolve.
4. **2–5 agents.** Fewer than 2 is not a fan-out; more than 5 means the decomposition is too granular.
5. **Disjoint scopes.** Non-overlapping assignments so findings merge cleanly. For Pattern 4 this is load-bearing: partition the search space so no reader is missed or double-counted.
6. **Label clearly** so progress is visible.
7. **Use `subagent_type: "Explore"`** for read-only investigation.
8. **Context hygiene.** Wrap user-supplied values per `${CLAUDE_PLUGIN_ROOT}/shared/CONTEXT-HYGIENE.md` before echoing them into a subagent prompt.
9. **Locate before Read** — graph, then grep, then Read spans.
### Prompt template
```
Investigate: [[SPECIFIC_QUESTION]]
Context: [[BROADER_TOPIC]]
Look for:
- [specific thing 1]
- [specific thing 2]
Report back:
- Key files found (paths + line numbers)
- How it works (brief)
- Connections to other systems
- Open questions or gaps you noticed
```
Resolve `[[SPECIFIC_QUESTION]]` and `[[BROADER_TOPIC]]` from session state at emit time. **An unresolved placeholder halts the fan-out — never gap-fill one.**
---
## Synthesis
After investigators return, you **must** synthesize. Never dump raw agent output.
1. **Merge overlapping findings** — agents often reach the same file from different angles.
2. **Build one unified picture** — a diagram where structure matters.
3. **Name the gaps** — what did no agent find? What is still unclear?
4. **Surface contradictions** — when two agents disagree, say so; do not silently pick one.
5. **Run a completeness check.** Before closing, ask what is missing: a layer not swept, a reader not checked, an option not costed. **For Pattern 4 this is mandatory** — if any layer of the blast radius went uncovered, say so outright. A silent gap reads as "we covered everything" when you didn't.
6. **Offer direction.** What is worth exploring next? In autonomous mode, pursue it or record it in the brief rather than asking.
The result should read like a senior engineer who just debriefed four specialists — not like four reports stapled together.
---
## OpenSpec awareness
```bash
openspec list --json # is there an active change?
```
When a change exists, read its artifacts via `openspec status --change "<name>" --json` for context, and offer to capture decisions as they crystallize:
| Insight | Captured in |
|---|---|
| New or changed requirement | `specs/<capability>/spec.md` |
| Design decision | `design.md` |
| Scope change | `proposal.md` |
---
## Every ambiguity becomes a ledger row
An unknown you name in chat is an unknown nobody can act on. The durable record is the decision ledger, and its format, classes and evidence rules are the contract in `${CLAUDE_PLUGIN_ROOT}/shared/DECISION-LEDGER.md` — read it and follow it rather than restating it.
What exploring owes that ledger:
- Every item you put under `## Pending Clarifications` is a `needs_human` row.
- Every item under `## Assumptions Made` is an `agent_resolved` row, and it needs evidence a reader can follow — the brief section or the file that justified it. `obvious` is not evidence, and an `agent_resolved` row without a real resolution and real evidence blocks exactly like `needs_human` does.
- **Never only chat.** In conversational mode a question you asked and got answered still gets a row, with the human cited in `evidence`.
Where it goes depends on whether a change exists yet:
- **A change is active** (`openspec list --json`, or the brief's `related_change`) → write the rows into `openspec/changes/<change>/decisions.md` now, and verify with `interlock ledger <change>`. It exits non-zero while a `needs_human` row remains — which is the honest state of an exploration that found a real product question, not a failure.
- **No change yet** — the usual case when `/interlock:spec` invoked this skill → the brief carries the rows. Number them `D1`, `D2`, … under the two headings and state each class, so `/interlock:spec` transcribes them into the ledger verbatim instead of re-deriving them. Ids are stable from here on: never renumber, never reuse one for a different question.
---
## Exit
Conversational mode ends when the user has what they need.
Autonomous mode ends by writing the explore brief and reporting its path — the brief is what `/interlock:spec` reads instead of re-deriving discovery. Writing it is how explore pays forward.