explore · diff

git:20260812.cc6f239 to git:20260812.83c0b5b

28 added, 10 removed. Audit A to A.

---
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 specflow-graph CLI.
+ compatibility: Optional openspec CLI for change awareness. Node.js >= 18 for the bundled interlock-graph CLI.
argument-hint: "[question] [--autonomous]"
- allowed-tools: Bash(specflow-graph *) Bash(openspec *) Read Grep Glob
+ 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 `/specflow:spec`. Writing OpenSpec artifacts or an explore brief is capturing thinking, not implementing, and is allowed.
+ **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 `/specflow:spec` invokes this skill. Then:
+ **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.
+ 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
- specflow-graph query "<subsystem tokens>" --budget 1500
- specflow-graph consumers <symbol-or-field> # Pattern 4 / invariant sweep
- specflow-graph path <A> <B> # cross-cutting traces
+ 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 (`specflow-graph build .`) before fanning out. Never rebuild when it already exists.
+ 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 `/specflow:spec` reads instead of re-deriving discovery. Writing it is how explore pays forward.
+ 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.