* test(#2711): derive the omit-rule guarded set from the corpus instead of a hand list The GUARDED array was a Goodhart metric: it reported green across 15 non-compliant workflows for no better reason than that nobody had added them to it. The guard now derives its set — every workflow emitting a model="{…}" dispatch site must state the omit-on-inherit/empty rule — and asserts the derivation is non-empty so a broken scan fails rather than passes. Rule detection stays a PROPERTY check, not a template match: plan-phase.md and execute-phase.md state it in different words and both are correct. RED expected on 15 workflows: audit-milestone, code-review, code-review-fix, debug, discuss-phase-assumptions, docs-update, map-codebase, new-milestone, new-project, quick, secure-phase, ui-phase, ui-review, validate-phase, verify-work. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPq9ovaovP2UvSVLjD4Lso * fix(#2711): propagate the #2517 omit-on-inherit rule to all 15 unguarded workflows 15 of the 19 model=-dispatching workflows carried no omit-on-inherit/empty guidance — 43 unguarded dispatch sites. Each would emit model="" whenever the bound *_model resolved empty, which is the DEFAULT state on non-Claude runtimes: the installer writes resolve_model_ids:"omit" into ~/.gsd/defaults.json for every one of them (references/model-profiles.md:101), and resolveModelInternal returns "" for that case (src/model-resolver.cts:383-386) and "inherit" for opus-tier agents and the inherit profile (:395). Both 404 on runtimes without native tier aliases — the failure #2517 documented and fixed in one file. Each file now carries a `<!-- #2517 model-omit-on-inherit -->` blockquote naming its own bound placeholders and linking the canonical statement in references/model-profile-resolution.md, mirroring the `<!-- #2508 runtime-aware-dispatch -->` block already present in all 15. The rule text lives in the reference; the workflows carry a pointer plus the one-line instruction, so the next revision edits one file rather than fifteen. plan-phase.md and execute-phase.md are deliberately untouched — they already state the rule in their own wording, and the guard checks the property rather than a template string. No dispatch site is edited and no placeholder renamed: the #2684 binding guard reports the same 19 files / 60 placeholders / 0 findings before and after, which is the independence proof that this change is additive prose only. There is no Hyrum's-Law routing change to disclose. Placement is span-aware. An initial pass anchored to the #2508 marker, but in six files that marker sits INSIDE the Agent(prompt="…") string, so the new paragraph's literal model= landed in a dispatch call span and tripped the #2284 fail-closed Hermes projection guard (bin/install.js:3704), refusing the install. Blocks are now anchored before the opening Agent( of the span owning the first dispatch, and verified to fall inside no span. gen:golden exits 0 across all 19 runtimes. Fixes #2711 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPq9ovaovP2UvSVLjD4Lso * fix(#2711): cite the issue number in the changeset body and tidy block placement Review findings from the two orthogonal passes: - The changeset body ended (#0). Repo convention across every prior fragment (e.g. #2617/#2693, #2608, #2605) is that the trailing (#NNN) is the ISSUE number, known at authoring time; only the frontmatter pr: field carries the 0 placeholder pending backfill. (#0) would have rendered a dead link in the published release notes. - new-milestone.md glued the inserted block directly under the preceding paragraph with no blank line, inconsistent with the other 14 insertions. - The derived-guard non-vacuity floor was >=17 against an actual derived count of 19, tolerating a silent two-file regression. Tightened to >=19. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPq9ovaovP2UvSVLjD4Lso * fix(#2711): reword the omit block so it survives Hermes projection, and exempt quick.md by size The first block wording regressed two suites on the full matrix (4 failures on both linux-node22 and linux-node24). gen:golden passing was not sufficient evidence — it exercises the installer's own fail-closed guard, which is narrower than the dedicated tests. 1. tests/fix-2284-hermes-agent-delegate-task-projection.test.cjs asserts that the INSTALLED code-review-fix.md contains no `model=` anywhere outside a string literal — masked whole-file, not merely inside call spans. The block's backticked `model=` survived the mask. The assertion is right: on Hermes the projection strips the parameter because delegate_task has no per-call model at all, so instructing the orchestrator to "omit the model= parameter" is advice about a parameter that does not exist there. The block now says "the `model` parameter" and carries no bare `model=` token. 2. tests/prompt-injection-scan.security.test.cjs flagged quick.md at 50,164 normalized chars against a 50,000 prompt-stuffing threshold. quick.md sits just under the line on next, so any insertion trips it — the situation review.md is already documented for in SIZE_ONLY_WORKFLOWS ("sat at 49,971 chars — 29 below the threshold — so it was going to trip on whatever was added to it next"). quick.md joins it with the same justification. This is a size-finding exemption only: the file is still fully injection scanned, and every other security check still runs on it. Because the canonical block can no longer carry a literal `model=`, the guard's detector now accepts the `<!-- #2517 model-omit-on-inherit -->` marker as the canonical signal, falling back to the inline-prose property for the four files that predate it (plan-phase, execute-phase, scan, ship — all four match the legacy branch). That is strictly stronger than word-proximity matching, and it keeps the guard a property check rather than a template match. Verified: derived guard 19/19 with 0 missing; the #2684 binding guard unchanged at 19 files / 60 placeholders / 0 findings; no inserted block contains a bare model= token; the masked-projection assertion passes for code-review-fix.md; gen:golden exits 0 across all 19 runtimes; lint:ci exits 0. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPq9ovaovP2UvSVLjD4Lso * chore(#2711): backfill changeset PR number Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DPq9ovaovP2UvSVLjD4Lso --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
22 KiB
Each agent has fresh context, explores a specific focus area, and writes documents directly. The orchestrator only receives confirmation + line counts, then writes a summary.
Output: .planning/codebase/ folder with 7 structured documents about the codebase state.
<available_agent_types> Valid GSD subagent types (use exact names — do not fall back to 'general-purpose'):
- gsd-codebase-mapper — Maps project structure and dependencies </available_agent_types>
Document quality over length: Include enough detail to be useful as reference. Prioritize practical examples (especially code patterns) over arbitrary brevity.
Always include file paths:
Documents are reference material for Claude when planning/executing. Always include actual file paths formatted with backticks: src/services/user.ts.
- Pass
--paths <p1>,<p2>,...through to each spawnedgsd-codebase-mapperagent's prompt. Agents scope their Glob/Grep/Bash exploration to the listed repo-relative prefixes only — no whole-repo scan. - Reject path values that contain
.., start with/, or include shell metacharacters (;,`,$,&,|,<,>). If all provided paths are invalid, fall back to a normal whole-repo run. - On write, each mapper stamps
last_mapped_commit: <HEAD sha>into the YAML frontmatter of every document it produces (seebin/lib/drift.cjs:writeMappedCommit).
Explicit contract — propagate --paths through a single normalized
variable. Downstream steps (spawn_agents, sequential_mapping, and any
Agent-mode prompt construction) MUST use ${PATH_SCOPE_HINT} to ensure every
mapper receives the same deterministic scope. Without this contract
incremental-remap can silently regress to a whole-repo scan.
# Validated, comma-separated paths (empty if --paths absent or all rejected):
SCOPED_PATHS="<validated paths or empty>"
if [ -n "$SCOPED_PATHS" ]; then
PATH_SCOPE_HINT="--paths $SCOPED_PATHS"
else
PATH_SCOPE_HINT=""
fi
All mapper prompts built later in this workflow MUST include
${PATH_SCOPE_HINT} (expanded to empty when full-repo mode is in effect).
When --paths is absent, behave exactly as before: full-repo scan, all 7
documents refreshed.
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
INIT=$(gsd_run query init.map-codebase)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
AGENT_SKILLS_MAPPER=$(gsd_run query agent-skills gsd-codebase-mapper)
Extract from init JSON: mapper_model, commit_docs, codebase_dir, existing_maps, has_maps, codebase_dir_exists, subagent_timeout, date.
If codebase_dir_exists is true:
ls -la .planning/codebase/
If exists:
.planning/codebase/ already exists with these documents:
[List files found]
What's next?
1. Refresh - Delete existing and remap codebase
2. Update - Keep existing, only update specific documents
3. Skip - Use existing codebase map as-is
Wait for user response.
If "Refresh": Delete .planning/codebase/, continue to create_structure If "Update": Ask which documents to update, continue to spawn_agents (filtered) If "Skip": Exit workflow
If doesn't exist: Continue to create_structure.
Create .planning/codebase/ directory:mkdir -p .planning/codebase
Expected output files:
- STACK.md (from tech mapper)
- INTEGRATIONS.md (from tech mapper)
- ARCHITECTURE.md (from arch mapper)
- STRUCTURE.md (from arch mapper)
- CONVENTIONS.md (from quality mapper)
- TESTING.md (from quality mapper)
- CONCERNS.md (from concerns mapper)
Continue to spawn_agents.
Before spawning agents, detect whether the current runtime supports the `Agent` tool for subagent delegation.How to detect: Check if you have access to an Agent tool (may be capitalized as Agent or lowercase as agent depending on runtime). If you do NOT have an Agent/agent tool (or only have tools like browser_subagent which is for web browsing, NOT code analysis):
→ Skip spawn_agents and collect_confirmations — go directly to sequential_mapping instead.
CRITICAL: Never use browser_subagent or Explore as a substitute for Agent. The browser_subagent tool is exclusively for web page interaction and will fail for codebase analysis. If Agent is unavailable, perform the mapping sequentially in-context.
Runtime-aware dispatch (#2508 Phase 4). GSD workflows dispatch specialized subagents by role. Before dispatching on a built-in-only runtime (kimi-code — three built-ins only), resolve the role to a built-in via
gsd_run query resolve-dispatch-type --requested <role> --raw. On named-dispatch runtimes (Claude/OpenCode/…) the role is returned unchanged; on kimi-code it maps tocoder/explore/planby role-suffix. The persona rides${AGENT_SKILLS_<ROLE>}(Phase 3) regardless. See @gsd-core/references/runtime-aware-dispatch.md.
Model omission (#2517). Omit the
modelparameter entirely when the value it would carry (mapper_model) is"inherit"or empty. An empty value 404s on runtimes without native tier aliases — the default on non-Claude runtimes. Omitting it inherits the orchestrator's model. See @gsd-core/references/model-profile-resolution.md.
Use Agent tool with subagent_type="gsd-codebase-mapper", model="{mapper_model}", and run_in_background=true for parallel execution.
CRITICAL: Use the dedicated gsd-codebase-mapper agent, NOT Explore or browser_subagent. The mapper agent writes documents directly.
Print: "Spawning 4 parallel codebase mapper agents (each runs in a subagent — no output until they return, ~1–5 min; expected, not a freeze)"
Agent 1: Tech Focus
Agent(
subagent_type="gsd-codebase-mapper",
model="{mapper_model}",
run_in_background=true,
description="Map codebase tech stack",
prompt="Focus: tech
Today's date: {date}
Analyze this codebase for technology stack and external integrations.
Write these documents to {codebase_dir}/:
- STACK.md - Languages, runtime, frameworks, dependencies, configuration
- INTEGRATIONS.md - External APIs, databases, auth providers, webhooks
IMPORTANT: Set all date stamps (`**Analysis Date:**`, footer `*... analysis: ...*`, `<!-- refreshed: ... -->`) to {date}, overwriting any existing date.
Scope: ${PATH_SCOPE_HINT:-(full repo)} — when --paths is supplied, restrict exploration to those prefixes only.
Explore thoroughly. Write documents directly using templates. Return confirmation only.
${AGENT_SKILLS_MAPPER}"
)
Agent 2: Architecture Focus
Agent(
subagent_type="gsd-codebase-mapper",
model="{mapper_model}",
run_in_background=true,
description="Map codebase architecture",
prompt="Focus: arch
Today's date: {date}
Analyze this codebase architecture and directory structure.
Write these documents to {codebase_dir}/:
- ARCHITECTURE.md - Pattern, layers, data flow, abstractions, entry points
- STRUCTURE.md - Directory layout, key locations, naming conventions
IMPORTANT: Set all date stamps (`**Analysis Date:**`, footer `*... analysis: ...*`, `<!-- refreshed: ... -->`) to {date}, overwriting any existing date.
Scope: ${PATH_SCOPE_HINT:-(full repo)} — when --paths is supplied, restrict exploration to those prefixes only.
Explore thoroughly. Write documents directly using templates. Return confirmation only.
${AGENT_SKILLS_MAPPER}"
)
Agent 3: Quality Focus
Agent(
subagent_type="gsd-codebase-mapper",
model="{mapper_model}",
run_in_background=true,
description="Map codebase conventions",
prompt="Focus: quality
Today's date: {date}
Analyze this codebase for coding conventions and testing patterns.
Write these documents to {codebase_dir}/:
- CONVENTIONS.md - Code style, naming, patterns, error handling
- TESTING.md - Framework, structure, mocking, coverage
IMPORTANT: Set all date stamps (`**Analysis Date:**`, footer `*... analysis: ...*`, `<!-- refreshed: ... -->`) to {date}, overwriting any existing date.
Scope: ${PATH_SCOPE_HINT:-(full repo)} — when --paths is supplied, restrict exploration to those prefixes only.
Explore thoroughly. Write documents directly using templates. Return confirmation only.
${AGENT_SKILLS_MAPPER}"
)
Agent 4: Concerns Focus
Agent(
subagent_type="gsd-codebase-mapper",
model="{mapper_model}",
run_in_background=true,
description="Map codebase concerns",
prompt="Focus: concerns
Today's date: {date}
Analyze this codebase for technical debt, known issues, and areas of concern.
Write this document to {codebase_dir}/:
- CONCERNS.md - Tech debt, bugs, security, performance, fragile areas
IMPORTANT: Set all date stamps (`**Analysis Date:**`, footer `*... analysis: ...*`, `<!-- refreshed: ... -->`) to {date}, overwriting any existing date.
Scope: ${PATH_SCOPE_HINT:-(full repo)} — when --paths is supplied, restrict exploration to those prefixes only.
Explore thoroughly. Write document directly using template. Return confirmation only.
${AGENT_SKILLS_MAPPER}"
)
ORCHESTRATOR RULE — CODEX RUNTIME: After calling all 4 Agent() calls above with
run_in_background=true, do NOT read any source files, analyze the codebase, or write any mapping documents independently while the subagents are active. Wait for all 4 agents to complete before proceeding to collect_confirmations. This prevents duplicate work and wasted context.
Continue to collect_confirmations.
Wait for all 4 background agents to finish, then read each agent's output file to collect confirmations.Each Agent(...) call above with run_in_background=true returns an async_launched result that carries an outputFile path (and canReadOutputFile: true). The 4 agents run concurrently and each one's completion arrives as a message in this conversation when it finishes — do NOT issue a separate blocking call to wait for them.
Once all 4 agents have reported completion, read each agent's output file (single message with 4 Read calls):
Read tool:
file_path: "{outputFile from that agent's async_launched result}"
Allow up to
workflow.subagent_timeoutfor the slowest agent to finish before treating it as failed. The timeout is configurable viaworkflow.subagent_timeoutin.planning/config.json(milliseconds). Default: 300000 (5 minutes). Increase for large codebases or slower models.
Each output file contains that agent's completion confirmation. Parse the confirmation marker (see below) from the file contents.
Expected confirmation format from each agent:
## Mapping Complete
**Focus:** {focus}
**Documents written:**
- `.planning/codebase/{DOC1}.md` ({N} lines)
- `.planning/codebase/{DOC2}.md` ({N} lines)
Ready for orchestrator summary.
What you receive: Just file paths and line counts. NOT document contents.
If any agent failed, note the failure and continue with successful documents.
Continue to verify_output.
When the `Agent` tool is unavailable, perform codebase mapping sequentially in the current context. This replaces `spawn_agents` and `collect_confirmations`.IMPORTANT: Do NOT use browser_subagent, Explore, or any browser-based tool. Use only file system tools (Read, Bash, Write, Grep, Glob, list_dir, view_file, grep_search, or equivalent tools available in your runtime).
IMPORTANT: Set all date stamps (**Analysis Date:**, footer, <!-- refreshed -->) to {date} from init context, overwriting any existing date — Update runs seed from files with concrete prior dates, so merely replacing [YYYY-MM-DD] placeholders is not sufficient. NEVER guess the date.
SCOPE: When ${PATH_SCOPE_HINT} is non-empty (i.e. --paths was supplied), restrict every pass below to the validated path prefixes in ${SCOPED_PATHS}. Do NOT scan files outside those prefixes. When ${PATH_SCOPE_HINT} is empty, perform a full-repo scan.
Perform all 4 mapping passes sequentially:
Pass 1: Tech Focus
- Explore package.json/Cargo.toml/go.mod/requirements.txt, config files, dependency trees
- Write
.planning/codebase/STACK.md— Languages, runtime, frameworks, dependencies, configuration - Write
.planning/codebase/INTEGRATIONS.md— External APIs, databases, auth providers, webhooks
Pass 2: Architecture Focus
- Explore directory structure, entry points, module boundaries, data flow
- Write
.planning/codebase/ARCHITECTURE.md— Pattern, layers, data flow, abstractions, entry points - Write
.planning/codebase/STRUCTURE.md— Directory layout, key locations, naming conventions
Pass 3: Quality Focus
- Explore code style, error handling patterns, test files, CI config
- Write
.planning/codebase/CONVENTIONS.md— Code style, naming, patterns, error handling - Write
.planning/codebase/TESTING.md— Framework, structure, mocking, coverage
Pass 4: Concerns Focus
- Explore TODOs, known issues, fragile areas, security patterns
- Write
.planning/codebase/CONCERNS.md— Tech debt, bugs, security, performance, fragile areas
Use the same document templates as the gsd-codebase-mapper agent. Include actual file paths formatted with backticks.
Continue to verify_output.
Verify all documents created successfully:ls -la .planning/codebase/
wc -l .planning/codebase/*.md
Verification checklist:
- All 7 documents exist
- No empty documents (each should have >20 lines)
If any documents missing or empty, note which agents may have failed.
Continue to scan_for_secrets.
**CRITICAL SECURITY CHECK:** Scan output files for accidentally leaked secrets before committing.Run secret pattern detection:
# Check for common API key patterns in generated docs
grep -E '(sk-[a-zA-Z0-9]{20,}|sk_live_[a-zA-Z0-9]+|sk_test_[a-zA-Z0-9]+|ghp_[a-zA-Z0-9]{36}|gho_[a-zA-Z0-9]{36}|glpat-[a-zA-Z0-9_-]+|AKIA[A-Z0-9]{16}|xox[baprs]-[a-zA-Z0-9-]+|-----BEGIN.*PRIVATE KEY|eyJ[a-zA-Z0-9_-]+\.eyJ[a-zA-Z0-9_-]+\.)' .planning/codebase/*.md 2>/dev/null && SECRETS_FOUND=true || SECRETS_FOUND=false
If SECRETS_FOUND=true:
⚠️ SECURITY ALERT: Potential secrets detected in codebase documents!
Found patterns that look like API keys or tokens in:
[show grep output]
This would expose credentials if committed.
**Action required:**
1. Review the flagged content above
2. If these are real secrets, they must be removed before committing
3. Consider adding sensitive files to Claude Code "Deny" permissions
Pausing before commit. Reply "safe to proceed" if the flagged content is not actually sensitive, or edit the files first.
Wait for user confirmation before continuing to commit_codebase_map.
If SECRETS_FOUND=false:
Continue to commit_codebase_map.
Commit the codebase map:gsd_run query commit "docs: map existing codebase" --files .planning/codebase/*.md
Continue to offer_next.
Present completion summary and next steps.Get line counts:
wc -l .planning/codebase/*.md
Output format:
Codebase mapping complete.
Created .planning/codebase/:
- STACK.md ([N] lines) - Technologies and dependencies
- ARCHITECTURE.md ([N] lines) - System design and patterns
- STRUCTURE.md ([N] lines) - Directory layout and organization
- CONVENTIONS.md ([N] lines) - Code style and patterns
- TESTING.md ([N] lines) - Test structure and practices
- INTEGRATIONS.md ([N] lines) - External services and APIs
- CONCERNS.md ([N] lines) - Technical debt and issues
---
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
**Initialize project** — use codebase context for planning
`/clear` then:
`/gsd:new-project`
---
**Also available:**
- Re-run mapping: `/gsd:map-codebase`
- Review specific file: `cat .planning/codebase/STACK.md`
- Edit any document before proceeding
---
End workflow.
<success_criteria>
- .planning/codebase/ directory created
- If Agent tool available: 4 parallel gsd-codebase-mapper agents spawned with run_in_background=true
- If Agent tool NOT available: 4 sequential mapping passes performed inline (never using browser_subagent)
- All 7 codebase documents exist
- No empty documents (each should have >20 lines)
- Clear completion summary with line counts
- User offered clear next steps in GSD style </success_criteria>