scan-codebase
Run the deterministic codebase scanner (core/components/plays/codify/lib/scan.py) over one or more repository roots and produce a bounded scan-index.json under STM. This skill is the sole structured-i
SKILL.mdcore/components/skills/scan-codebase/SKILL.md
GitHubscan-codebase
Called by the /codify play before any inference agent dispatches. Produces scan-index.json in STM. The index is the only structured-input that downstream inference skills consume.
Purpose
Garura's /codify play is a brownfield bootstrap — it reverse-engineers a product's LTM from an existing codebase. Before any LLM inference runs, a deterministic scan extracts structured facts: manifest data, directory tree, git signals, framework idioms, frontend detection, ADR harvest, config surface. That scan is this skill's job. Agents must never navigate source code as their primary input — they reason over the scan-index this skill produces.
Input
Receive from the /codify play orchestrator via JSON contract.
repo_roots(list[path], required) — one or more absolute repository root paths to scan. Multi-repo monorepos pass multiple entries.output_path(path, required) —{stm_base}/{issue}/evidence/codify/scan-index.jsonsize_limit_mb(int, optional, default 10) — soft cap on scan-index.json size; scan writes a partial index withscan_status: budget_exhaustedon breach.time_limit_seconds(int, optional, default 600) — soft cap on wall-clock duration.extra_ignore(list[str], optional) — additional ignore globs beyond the built-in list (node_modules, dist, .git, etc.).
Process
1. Validate inputs
- Confirm every entry in
repo_rootsis an absolute path to an existing directory. Missing or non-directory → structured failure withwhat_failed: invalid_repo_rootand the offending path. - Confirm
output_pathparent directory is writable. If parent does not exist, create it. Failure to create → structured failure withwhat_failed: stm_path_unwritable. - Confirm Python 3.8+ is on PATH. Missing → structured failure with
what_failed: python_missing. - Confirm
scan.pyexists atcore/components/plays/codify/lib/scan.pyrelative to repo root. Missing → structured failure withwhat_failed: scan_script_missing.
2. Invoke scan.py
Build the command line:
python3 core/components/plays/codify/lib/scan.py \
--output <output_path> \
--size-limit-mb <size_limit_mb> \
--time-limit-s <time_limit_seconds> \
--path <root_1> [--path <root_2> ...] \
[--ignore <pattern> ...]
Run via subprocess. Capture stdout and stderr. Honor the time-limit budget by passing --time-limit-s — do not wrap with a separate timeout.
3. Inspect status
After scan.py exits:
- Exit code 0 AND
scan-index.jsonexists → scan ran to a definite status (completeorbudget_exhausted). - Exit code 2 OR
scan-index.jsonmissing → scan failed; structured failure withwhat_failed: scan_script_errorand the captured stderr.
Read scan-index.json. Parse top-level fields: scan_status, scan_size_bytes, scan_duration_seconds, repos, budget.
4. Emit result
Write a small scan-result.yaml alongside the index at {stm_base}/{issue}/evidence/codify/scan-result.yaml containing:
scan_index_path: "<output_path>"
scan_status: "complete" | "budget_exhausted"
budget_exhausted_reason: "time_limit" | "size_limit" | null
scan_duration_seconds: <float>
scan_size_bytes: <int>
repos:
- label: "<repo-label>"
root_path: "<abs-path>"
file_count: <int>
total_bytes: <int>
manifest_count: <int>
frontend_detected_any_repo: <bool>
Return this YAML path to the caller.
Output
Primary artifact: scan-index.json at output_path.
Companion artifact: scan-result.yaml at {stm_base}/{issue}/evidence/codify/scan-result.yaml.
No decision manifest is produced — this skill makes no inferred decisions. It is a deterministic wrapper around scan.py.
Failure Modes
All failures return a structured failure payload per the universal contract:
status: failure
what_failed: "<one of: invalid_repo_root, stm_path_unwritable, python_missing, scan_script_missing, scan_script_error>"
detail: "<specific error string>"
evidence: {}
Notes
- The scanner is intentionally conservative: if ripgrep or git is unavailable, those sections of the index are omitted (with an
available: falseflag) rather than failing the whole scan. Downstream skills MUST handle missing sections. - The scanner enforces its own budgets. This skill does NOT retry on
budget_exhausted— surfacing the partial status is the correct behavior; the play orchestrator prompts the user. - The scan is read-only on the target codebase. It creates no files inside any
repo_root.