scout
Workflow Phase 2 — Codebase Scouting and Constraint Discovery. Maps the relevant slice of the codebase for a given task. Produces a scout report at `docs/scout/<slug>.md` naming the files, modules, an
Files1
View on GitHubSKILL.md.claude/skills/scout/SKILL.md
GitHubYou are mapping the slice of the codebase that matters for the current task — no more, no less. The scout report is consumed downstream by /research and /spec.
Prereqs
.claude/state/workflow.jsonexists.intakeis incompletedOR inexceptions. If neither, stop and direct the user to invokeintake.
Inputs
- The intake document at
docs/intake/<slug>.md— read Problem and Goal first; they define scope. - The BRD at
docs/brd/<slug>.mdif present — In/Out scope lists. - The codebase at the project root.
- Optional argument: a specific path to scope the scout.
If no intake exists (ad-hoc invocation), fall back to the parent task description and note in the report that the scout ran without a structured intake.
Method
Reconcile against the workspace corpus before discovering anything. This step is gated — check the flag FIRST:
node .claude/skills/workspace/cli.mjs flags # gates on memory.workspace.enabled — read the `workspace:` linefalse(the default, and the value for any project that has not opted in) → skip the rest of this step entirely and go to step 1. A populated corpus must not change scout's behaviour for a project that never asked for it.true→ ifdocs/system/elements/holds any element, this scout run is a reconciliation, not a rediscovery:node .claude/skills/workspace/cli.mjs reconcile --touched <comma,separated,paths> --json # wraps workspace/reconcile.mjs -> reconcilemode: "reconcile"→ report the returneddelta(changed/unreferenced) for the slice being touched and go straight to step 3; the corpus already answers "what is this system".mode: "discovery"→ the corpus is absent or empty, so fall through to step 1 and scout normally.The delta carries exactly those two keys.
addedandstaleare deliberately absent fromreconcile.mjs:addedwould need a prior reconcile snapshot that does not exist, and staleness is decided per element byclassify, which/memory-syncStep 0e surfaces. Reporting a field the helper never returns is how a scout report comes to describe a delta nobody computed.This step is the whole point of the corpus: without it the modules are an orphan nothing calls, and every cycle pays full rediscovery again. A delta that names every element is a re-derivation — report that as a corpus defect rather than passing it off as a delta.
0.5 Resolve the tracking annotations the code carries. Gated the same way — check the flag FIRST:
node .claude/skills/workspace/cli.mjs flags # gates on memory.annotations.enabled — read the `annotations:` line
false (the default) → skip the rest of this step and go to step 1. true →
scan and resolve:
node .claude/skills/workspace/cli.mjs annotations --json # wraps workspace/annotations.mjs -> scanAnnotations
Report both halves of the result in the scout report's Constraints section:
resolved[]→ for every annotation whose governed file is in the slice being touched, surfacefile:lineplus the entry'shookline. This is the reason the code has its shape, reaching the person about to change it — the whole point of the annotation.dangling[]→ report EVERY entry, in or out of the slice. An annotation naming a deleted or renamed entry asserts that a reason exists and then sends the reader nowhere; it is the one case worth being loud about, and silence lets it rot indefinitely.
The scan reports; it never blocks. A dangling annotation is a finding for the report, not a failed phase.
Identify the nouns and verbs in the task. Each is a search anchor.
For each anchor, pick the right tool:
- Structural / navigation questions ("where does the data on page X come from?", "what component renders Y?", "what wraps Z?", "find the API for this icon/button"): invoke
Skill(code-browser). It walks the import graph from the page down to the network boundary and returns flat indexes (byHook/byService/byApiCall/byComponent) — far more reliable than keyword grep, which routinely picks up unrelated flows that share a domain word. - Direct concept-to-file lookups (a named feature plus a file kind:
reducer,types,hook,context,service): consultcode-browser'sconventions.mdif present, orGlobagainst the convention path — no walker needed. - Term sweeps ("every file that references flag F", "all callers of util U", config / migration / deploy-manifest searches):
rg(orgrep -r) for the exact term, filtered to source directories. Read the top 3–5 hits with surrounding context. Follow imports/callers one hop out — do not recurse further.
If a navigation question lands you in
rgfirst, stop and switch tocode-browser— that is the failure mode the skill exists to prevent.Gathering delegation (seed.md §4.2-A). A broad sweep MAY be delegated to a read-only advisory subagent (e.g.
Explore): it returns findings only — no writes, no decisions. What enters the report is decided here, in main context.- Structural / navigation questions ("where does the data on page X come from?", "what component renders Y?", "what wraps Z?", "find the API for this icon/button"): invoke
Identify entry points — HTTP routes, CLI commands, cron jobs, queue consumers — that would trigger the code path being modified.
Identify existing tests for the affected code. Note flaky/skipped ones.
Note constraints — config files, feature flags, migrations, deploy manifests that need lockstep changes.
Output
Write the report to docs/scout/<slug>.md (create the directory if missing). Format:
# Codebase Scout Report — <task>
## Primary touchpoints
- <path:line> — <role in the task>
- ...
## Entry points that reach this code
- <HTTP route / CLI cmd / job> at <path:line>
## Existing tests
- <test path> — <what it covers> — <passing? skipped?>
## Constraints and co-changes
- <config / migration / flag> — <why it's linked>
## Patterns in use here
- <1–3 sentences on the style the code follows, for the implementer>
## Risks / landmines
- <anything surprising: dead code, TODO comments, shims, version skew>
After writing the file, append "scout" to workflow.json → completed.
Tell the user: Scout report at <path>. Next: /research.
Constraints
- Project source is read-only during scout. Do not modify project files. The only write is to
docs/scout/<slug>.md. - Do not speculate. If a search turns up nothing, say so. Do not invent paths.
- Keep the report under ~300 lines. If the surface is genuinely larger, say so and propose a scoping split with the user.
- Do not recommend an implementation approach. That is
/research's job. Stick to what is. - No code generation. No new files outside
docs/scout/.