Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .claude/skills/ci-push-checklist/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ See CLAUDE.md's "Using GitGalaxy's self-scan output for orientation" section for

## 1. Local & Unit Validation (~1 min)
* **Standalone Regex Re-test:** Isolate the target regex (e.g., `func_start`) against the failing corpus file manually to ensure false positives and negatives are resolved without affecting real matches.
* **See what the engine actually extracted before re-deriving it from source:** `galaxyscope <path> --db-only --debug --output <scratch-dir>` and grep the log for `[WORKER-TRACE] extracted functions for` -- one line per file with the exact satellite/function names produced. Much cheaper than tracing `_slice_by_keywords`/`_slice_by_terminator`/etc. cold when the question is "what did the engine actually name/count here." See CLAUDE.md's "Debugging what detector.py actually extracted from a specific file" for the full recipe (DB cross-reference, etc.) -- not repeated here.
* **Extraction Gauntlet & Strict Tests:** Run `pytest tests/extraction/languages/test_<lang>.py` and `test_<lang>_strict.py` for the language you modified.

## 2. Static Analysis & Linting (~15s)
Expand All @@ -27,6 +28,14 @@ See CLAUDE.md's "Using GitGalaxy's self-scan output for orientation" section for
* **Run the Crucible Check (Mandatory):** Execute `python tests/tools/crucible_check.py` against the full ~80-repo corpus.
* **Re-Bless Golden Masters:** If `crucible_check.py` shows expected, accurately traced diffs resulting from your fix, bless the new state:
`python tests/tools/crucible_check.py --update --yes`
* Always go through `crucible_check.py --update`, never `python tests/tools/update_golden_master.py`
directly -- the latter only updates whichever ONE fixture matches whatever happens to be
importable in your current shell, with no automatic venv/PATH management; `crucible_check.py
--update` runs it once per mode through its own properly-scoped venv, no manual bookkeeping.
* **Claude Code note:** blessing a golden master is exactly the kind of action Auto Mode's
classifier treats as destructive-looking and blocks by default (even via `--yes`, even on a
clean tree where it would be a no-op) -- expect to explicitly ask the user for one-time
permission before this step rather than being surprised mid-task.
* **Isolate exactly what your change touched, independent of whether the committed fixture is even current:** `python tests/tools/scope_check.py --expect <lang>[,<lang2>]` scans your working tree AND a comparison ref (default `origin/main`) fresh, in separate venvs, and buckets every difference by language -- fails loudly if anything outside `--expect` changed. This answers "is my diff actually scoped to what I meant to touch" directly, without needing the committed golden master to be current first (useful mid-investigation, or after `main` has moved and the committed fixture reflects a bunch of OTHER PRs' legitimate changes you didn't make). Costs roughly 2x a single `crucible_check.py` run (it builds and scans two venvs, not one) -- background it.
* **On the old "never clone a fresh corpus copy" folklore:** a fresh `language-crucible` clone is fine, and both `crucible_check.py` and `scope_check.py` do this routinely (the latter clones a temporary comparison-ref worktree every run). What actually causes massive, invalid-looking diffs is one of two SPECIFIC, now-automatically-checked things, not "metadata" in general (verified by direct repro, PR #2518, 2026-08-30/31 -- see `crucible_check.py`'s own module docstring for the full incident writeups):
1. **Wrong pin.** The corpus isn't on the tag `tests/_crucible_pin.py` names. `crucible_check.py` now warns about this automatically (`_check_corpus_pin`) -- if you see the warning, `git fetch --tags && git checkout <tag>` in the corpus checkout.
Expand Down
37 changes: 35 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,30 @@ diff be" is answered from data instead of a guess informed only by the issue tex
`"scala"` key starts inside `language_standards.py`'s `LANGUAGE_DEFINITIONS`) — it's for
orientation and prioritization, not symbol lookup. Read the actual file for that.

## Debugging what detector.py actually extracted from a specific file

Before tracing `_slice_by_keywords`/`_slice_by_terminator`/etc. by hand to understand why a
signal looks wrong for some target file or corpus, check what the engine actually did first —
much cheaper than re-deriving it from the regex/slicing logic cold (#2547: confirmed the exact
root cause — a slicer-synthesized non-function bucket name being miscounted as an orphan — in a
few minutes this way, instead of hours of pure static reading):

- `galaxyscope <path> --db-only --debug --output <scratch-dir>` and grep the resulting log for
`[WORKER-TRACE] extracted functions for` — one line per file, listing the exact satellite/
function names `_function_slice` produced for it (`detector.py`'s own debug trace, gated
behind `logger.isEnabledFor(logging.DEBUG)`). This is the fastest way to see whether a
suspiciously-named entry (a synthetic bucket, a reused generic keyword, a truncated remnant)
is in play, before assuming the signal count itself is what's wrong.
- Cross-reference the aggregated per-file numbers in the recorder DB this same run produces
(`<scratch-dir>/<repo>_galaxy_master.db`, `file_data` table) — column names are the
`record_keeper.py`-renamed form of the raw equation keys (e.g. `orphaned_logic` →
`state_slop_orphans`, `api` → `arch_api`; confirm via `.schema file_data` since this evolves).
- For a control/golden corpus already checked out locally (e.g. `keyword-rosetta`,
`language-crucible`), point `galaxyscope` straight at it this way instead of writing a
standalone repro script — the census requires git-tracked files (see `census-requires-git-
tracked` in a corpus's own deviation ledger if one exists), so scan the real corpus checkout,
not an ad hoc copy.

## Adding or hardening a language's structural signatures

Full protocol (LLM generation prompt, the 12 numbered engine rules for ReDoS/boundary
Expand Down Expand Up @@ -211,8 +235,17 @@ expected to be verified against `tests/golden_master_audit.json` /
`tests/golden_master_zero_dep_audit.json` — snapshots diffed by the `crucible-audit` CI check
against a ~80-repo corpus plus the PR's target repo. A failing diff means output changed: either
a bug, or an intentional improvement that needs the baseline re-blessed. **Never hand-edit these
fixtures.** Regenerate with `python tests/tools/update_golden_master.py` (shows the diff, asks
for confirmation) and explain *why* in the PR description — CI flags any PR touching these files.
fixtures.** Regenerate with `python tests/tools/crucible_check.py --update --yes` (default
`--mode both`) — explain *why* the output changed in the PR description, CI flags any PR touching
these files. This handles BOTH fixtures (full-precision and zero-dependency each need their own
venv/interpreter) in one command with no manual `PATH`/`pip install -e .` bookkeeping — see the
"Verifying locally before pushing" paragraph just below for exactly what it automates and why
that matters. `python tests/tools/update_golden_master.py` (`--yes` to skip its own confirmation
prompt) is the underlying single-mode script `--update` shells out to per venv; call it directly
only if you're already inside one specific mode's venv and deliberately want just that fixture —
reaching for it from your default shell silently updates whichever ONE fixture matches whatever
happens to be importable there (#2547: this cost a full investigation cycle before landing on
`crucible_check.py --update` instead).

The same PR paths also run `tri-comparison-audit.yml`, a baseline-gated regression check on
GitGalaxy's own **validated** precision against tree-sitter+ctags (see `docs/self_scan/
Expand Down
Loading