| name | cqs-plan |
| description | Task planning with scout data + task-type templates. Produces implementation checklists. |
| disable-model-invocation | false |
| argument-hint | <task description> |
Plan
Generate an implementation plan by combining cqs scout output with a task-type template.
Process
- Classify the task into one of the templates below based on the description.
- Run scout:
cqs scout "<task description>" --json 2>/dev/null (no -q flag on subcommands)
- Run targeted lookups from the template's checklist — scout alone misses structural touchpoints (clap structs, dispatch arms, skill files).
- Produce a plan listing every file to change, what to change, and why. Be specific about struct fields, function signatures, and match arms.
Arguments
$ARGUMENTS — task description (required)
Templates
Add/Replace a CLI Flag
When: Adding a new flag, renaming a flag, changing a flag's type (bool → enum).
Checklist:
src/cli/definitions.rs — Commands enum variant. Add/modify #[arg] field (often via a shared *Args struct in src/cli/args.rs). If enum-typed, define with clap::ValueEnum.
src/cli/dispatch.rs — run_with()/run_with_dispatch() match arm. Update destructuring and cmd_<name>() call.
src/cli/commands/<group>/<name>.rs (groups: search/, graph/, review/, index/, io/, infra/, eval/, train/) — flag flows into the *_core fn's typed *Args; update branching there, not just the CLI adapter.
- Daemon surface: if the flag affects core behavior, the daemon
dispatch_* handler in src/cli/batch/handlers/ must forward it too — CLI and daemon are parallel surfaces, wire both in the same PR. Parity tests live in src/cli/batch/handlers/dispatch_tests.rs.
src/store/*.rs / src/lib.rs — Usually NO changes. Only if flag affects query behavior.
- Tests:
tests/<name>_test.rs — add case for new value. Update tests using old flag name.
.claude/skills/cqs/SKILL.md — update the command's flag table.
README.md — update examples if the command is featured.
- Verify callers:
cqs callers cmd_<name> --json
Patterns:
- Output format flags:
#[arg(long, value_enum, default_value_t)]
- Display functions:
display_<name>_text(), display_<name>_json()
- JSON output:
serde_json::to_string_pretty on #[derive(Serialize)] structs
Add a New CLI Command
When: Adding an entirely new cqs <command>.
Checklist (command-core pattern — the NEW-COMMAND RULE, see CONTRIBUTING):
src/cli/commands/<group>/<name>.rs — New file in the right group (search/, graph/, review/, index/, io/, infra/). Implement ONE surface-agnostic <name>_core(...) taking a typed Deserialize <Name>Args and returning a Serialize <Name>Output. cmd_<name>() is a thin CLI adapter over the core.
src/cli/commands/<group>/mod.rs — Add mod <name>; and re-export cmd_<name> (+ the core for the daemon).
src/cli/definitions.rs — Add variant to Commands enum with args (shared *Args structs live in src/cli/args.rs).
src/cli/dispatch.rs — Add match arm calling cmd_<name>().
- Daemon surface in the same PR:
dispatch_<name> adapter in src/cli/batch/handlers/ (thin wrapper: parse wire request into <Name>Args, call the core). Add a CLI==daemon parity test in src/cli/batch/handlers/dispatch_tests.rs.
src/lib.rs or src/<module>.rs — Library function if logic is non-trivial. Keep CLI layer thin.
- Tests:
tests/<name>_test.rs — integration tests using TestStore or assert_cmd.
.claude/skills/cqs/SKILL.md — add the command to the dispatcher reference (and a cqs-<name> skill only if the workflow warrants it).
.claude/skills/cqs-bootstrap/SKILL.md — Add to portable skills list / command reference.
CLAUDE.md — Add to "Key commands" list.
README.md — Add to command reference.
CONTRIBUTING.md — Update Architecture Overview if adding new source files.
Patterns:
- Command files are ~50-150 lines. Store/library calls, then display.
- JSON output with
--json flag; text output via a display fn the daemon can reuse.
- Tracing span at core entry:
let _span = tracing::info_span!("<name>_core").entered();
Fix a Bug
When: Something produces wrong results, panics, or misbehaves.
Checklist:
- Reproduce: Understand the exact failure mode. Get input → actual → expected.
- Locate:
cqs scout "<bug description>" to find relevant code.
- Trace callers:
cqs callers <function> --json — who calls the buggy code? Are callers also affected?
- Check tests:
cqs test-map <function> --json — do tests exist? Do they cover the failing case?
- Fix: Minimal change in the library layer, not the CLI layer.
- Add test: Regression test that would have caught this bug.
- Check impact:
cqs impact <function> --json — did the fix change behavior for other callers?
Patterns:
- Fix in
src/*.rs (library), test in tests/*.rs or inline #[cfg(test)].
- Use
tracing::warn! for recoverable errors, bail! for unrecoverable.
- Never
.unwrap() in library code. ? or match + tracing::warn!.
Add Language Support
When: Adding a new programming language to the parser.
Checklist:
Cargo.toml — Add tree-sitter grammar dependency (optional).
src/language/mod.rs — Add to the define_languages! macro invocation.
src/language/languages.rs — Add the language's LanguageDef block (grammar wiring, extensions, extract/post-process hooks). Per-language files no longer exist — everything lives in this one file.
src/language/queries/<lang>.chunks.scm + <lang>.calls.scm (+ .types.scm if type deps apply) — tree-sitter queries live as standalone .scm files, not inline strings.
Cargo.toml features — Add lang-<name> feature, add to default and lang-all.
- Tests:
tests/fixtures/<lang>/ — sample files. Parser tests in tests/parser_test.rs.
tests/eval_test.rs and tests/model_eval.rs — Add match arms.
Patterns:
- One-liner in
define_languages! handles registration.
- Chunk query captures must use the parser's known capture names (see
src/parser/chunk.rs): function, struct, class, enum, trait, interface, const, ...
- Call query uses
@callee capture.
Add ChunkType Variant
When: Adding a new chunk type (e.g., Extension, Protocol, Alias).
Checklist:
src/language/mod.rs — Add variant to the define_chunk_types! invocation (ChunkType lives here now). Classify it so is_callable()/is_code() derive correctly — a round-trip test enforces consistency.
src/nl/mod.rs — Add natural language label for the variant (used in embedding text).
src/language/queries/<lang>.chunks.scm — Add capture using the new variant name.
src/parser/chunk.rs — Add to the capture-name map if using a new capture name.
src/cli/commands/index/stats.rs — Variant appears automatically via ChunkType iteration.
- Tests: Parser tests for each language using the new variant. Verify
cqs search returns results with correct type.
ROADMAP.md — Update ChunkType Variant Status table.
Patterns:
is_callable() returns true for Function, Method, Macro — most others return false.
Display uses lowercase singular (e.g., "type_alias"). FromStr accepts both snake_case and spaces.
- Container extraction uses
capture_types to decide what's a container vs leaf.
Add Injection Rule
When: Adding multi-grammar parsing (e.g., HTML→JS, PHP→HTML, Svelte→CSS).
Checklist:
src/language/languages.rs (host language's block) — Add InjectionRule to the host's injection rules. Specify parent_node, content_node, target_language, and optional detect_language callback.
src/language/languages.rs (target language's block) — Ensure the target's LanguageDef exists and parses correctly in isolation.
src/parser/injection.rs — Usually NO changes. Only if new detection logic is needed (e.g., detect_script_language, detect_heredoc_language).
- Tests:
tests/fixtures/<host>/ — sample file with embedded content. Verify chunks from both host and injected language appear.
- Verify depth limit: recursive injections (PHP→HTML→JS) must respect depth limit (default 3).
ROADMAP.md — Update Multi-Grammar Parsing section.
Patterns:
content_scoped_lines prevents container-spans-file problem in recursive injection.
detect_language callbacks inspect attributes (e.g., lang="ts", type="module").
set_included_ranges() for byte-range isolation of injected content.
Performance Optimization
When: Improving speed or reducing resource usage for a specific operation.
Checklist:
- Benchmark before:
cargo bench or manual timing with time cqs <command>. Record baseline.
- Profile:
cqs scout "<bottleneck description>" to find hot path. cqs callers to trace the call chain.
- Identify approach: Lazy loading, caching, reduced allocations, parallel iteration, candidate pruning.
- Implement: Minimal change. Prefer data structure changes over algorithmic rewrites.
- Benchmark after: Same benchmark as step 1. Quantify improvement.
- Regression test: Ensure correctness is preserved — same inputs produce same outputs.
- Check callers:
cqs impact <function> --json — did the optimization change the API surface?
Patterns:
- HNSW candidate fetch: load only
(id, embedding) for scoring, full content for top-k.
- Rayon
par_iter for embarrassingly parallel work. Check for shared mutable state first.
tracing::info_span! around hot paths for flame graph visibility.
Audit Finding Fix
When: Fixing an issue identified during a code audit (from docs/audit-triage.md).
Checklist:
- Read triage entry: Get priority, category, description, and affected code from
docs/audit-triage.md.
- Locate:
cqs scout "<finding description>" — verify the issue still exists (may have been fixed since audit).
- Assess scope:
cqs impact <function> --json — how many callers are affected?
- Fix: Follow the triage entry's suggested approach if provided.
- Add test: Cover the specific scenario from the finding.
- Update triage: Mark entry as fixed in
docs/audit-triage.md with PR reference.
- Check related findings: Same category may have related issues — fix together if trivial.
Patterns:
- P1 findings: fix immediately, standalone PR.
- P2-P3: batch by category into single PR.
- P4: fix opportunistically when touching nearby code.
Add Tree-Sitter Grammar
When: Adding a new tree-sitter grammar dependency (new language or replacing a grammar).
Checklist:
Cargo.toml — Add grammar crate as optional dependency. Prefer crates.io; use git dep with rev pin if unpublished.
build.rs — Usually NO changes (grammars self-register via tree-sitter-language crate).
src/language/<lang>.rs — Wire grammar via tree_sitter_<lang>::LANGUAGE or tree_sitter_<lang>::language().
Cargo.toml features — Add to lang-<name> feature gate. Add to default and lang-all.
- Verify compatibility: grammar must target tree-sitter
>=0.24, <0.27 (current range). Check grammar's Cargo.toml.
- Tests:
cargo test --features lang-<name> — parser produces expected chunks.
- If forked: document fork reason in
Cargo.toml comment. Track upstream for eventual switch.
Patterns:
- Git deps need
rev pin, not branch — branches break reproducibility.
- Some grammars export
LANGUAGE (static), others language() (function). Check their API.
- Monolithic grammars (Razor, VB.NET) don't need injection — they parse everything in one pass.
Schema Migration
When: Bumping the SQLite schema version (adding tables, columns, or changing data layout).
Checklist:
src/store/helpers/mod.rs — Bump CURRENT_SCHEMA_VERSION constant.
src/store/migrations.rs — Add async fn migrate_vN_to_vM() with ALTER TABLE / CREATE TABLE statements.
src/store/migrations.rs — Register it in the MIGRATIONS table as (N, M, |c| Box::pin(migrate_vN_to_vM(c))).
src/store/mod.rs — Update open() if new tables need initialization or if Store fields changed. src/schema.sql must reflect the new layout (its header states the version).
src/store/*.rs — Update queries that read/write affected tables.
- Tests: Migration test with a v(N-1) database → verify v(N) upgrade succeeds and data is preserved.
PROJECT_CONTINUITY.md — Update schema version in Architecture section.
Patterns:
- Migrations must be idempotent —
IF NOT EXISTS, IF NOT COLUMN guards.
- We use a metadata table for schema_version, not PRAGMA user_version.
- Test with a real old-version database if available (copy from
.cqs/ before upgrading).
cqs migrate skill handles user-facing migration workflow.
Refactor / Extract
When: Moving code, splitting files, extracting shared helpers.
Checklist:
- Find all call sites:
cqs callers <function> --json for each function being moved.
- Check similar code:
cqs similar <function> --json to find duplicates to consolidate.
- Plan visibility:
pub(crate) for cross-module, pub for public API, private for same-module.
- Move tests with code:
#[cfg(test)] mod tests works in submodules.
- Update imports: Each file needs its own
use statements — they don't carry across modules.
- Verify callers compile: After moving, all callers must update their
use paths.
CONTRIBUTING.md — Update Architecture Overview for structural changes.
Patterns:
impl Foo blocks can live in separate files (Rust allows multiple).
- Trait method imports don't carry over to submodule files.
- Use
pub(crate) for types/constants shared across submodules.
Output Format
Present the plan as:
## Plan: <task summary>
### Files to Change
1. **<file>** — <what and why>
- <specific change with code snippet>
### Tests
- <test file>: <what to test>
### Not Changed (verified)
- <file>: <why no changes needed>
When Not to Use
- Trivial changes (typos, single-line fixes) — just do it
- Pure research — use
cqs gather or cqs scout directly
- Running an audit — use
/audit skill (but audit finding fixes have a template above)