agentsclimarketplace

Cross file source of truth grep

Skill Ed3Design/ed3design-skill-bundles/code-quality/skills/cross-file-source-of-truth-grep

Use when about to refactor a value, constant, helper-function, lookup, or config-pattern from old-form to new-form across the codebase — schema-drift fixes, display-name SoT migration, config-pattern updates (hardcoded ID → env-var), helper rename, deprecated-import cleanup. STOP and run `grep -r "<old-pattern>"` on the WHOLE repo BEFORE writing the new pattern anywhere. Trigger when phrases like "I'm refactoring X to Y", "fix schema drift", "migrate from old to new form", "rename helper", "single-source-of-truth" appear, OR a mental model of "only 3 files use this" exists — dispatcher, scheduler, jobs, notifications, tests often hide additional places. Method: `grep -rn "<old-pattern>" --include="*.py"` excluding cache dirs, then categorize each hit. Do NOT load for greenfield code, pure-cosmetic renames in same file, or refactors guaranteed file-local.From its SKILL.md

Install
npx -y skills add Ed3Design/ed3design-skill-bundles --skill cross-file-source-of-truth-grep

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

10.6 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it

Cross-File Source-of-Truth Grep

PROMOTED — TDD Cycle 1 PASS. RED subagent gave a heuristic "grep first" recommendation, but without the decisive 4th grep pass on mapping values. GREEN subagent added the 4th pass grep -rn "'CL=F'\s*:\s*'WTI" — which catches copies of the mapping structure under deviating variable names (_DISPLAY_MAP, LABELS, dicts embedded inside helper functions). Precisely this pass would have caught the signal_dispatcher.py:_get_display_name bug before the refactor. R1 refactor applied: 4th grep pass in Quick Reference as a separate line + hint block.

Overview

Before every refactor: grep -r for the OLD pattern, not the NEW one.

When you replace an old pattern (column name, helper call, inline dict, default string, deprecated import) with a new one, 2-5 additional callers often lurk that you didn't have in the mental model of "the 3 relevant files":

  • notifications/ dispatcher (Telegram, email, webhook)
  • Scheduler jobs (cron-triggered, often rarely touched)
  • Batch scripts (offline analytics)
  • Integration tests + mock fixtures
  • Deprecated-but-still-in-path modules

Skill = simple discipline: grep -rn "<old-pattern>" BEFORE you write the first new call. 30 seconds of effort prevents hours of re-review cycle.

This maxim is the refactor-variant of the "Single Source of Truth" maxim: the SoT migration is only complete when grep for the old pattern returns nothing.

When to use

Trigger phrases (the kind you'd be about to use):

  • "I'm refactoring <X> to <Y>"
  • "fix schema drift in <table>.<column>"
  • "introduce SoT for <Display-Name / config-var / helper>"
  • "migrate from old config_loader path to new"
  • "rename helper-function from foo to bar"
  • "deprecated import cleanup"
  • "extract config defaults from code"

High-risk markers (additional trigger):

  • You have a small list of affected files in mind (≤5) — precisely then grep, because that's the case most prone to under-estimation
  • The new pattern already lives somewhere ("we standardized this in core/") — meaning older spots are not migrated yet
  • Module belongs to notification / dispatcher / scheduler / cron / batch — these paths are rarely touched, drift accumulates

When NOT to use

  • Greenfield code: the old pattern doesn't exist yet
  • Pure cosmetic rename in a single file: local variable, no semantic shift
  • Guaranteed file-local helper: _private_helper in module, with _ prefix convention
  • Rename of a symbol with IDE refactor-tool: when LSP refactor cleanly covers all callers, grep is redundant (but verify 1× afterwards anyway)

The 4-Step Cross-File SoT Grep Flow

Step 1 — Note the old pattern explicitly

Before grep, write as a comment or via TodoWrite:

  • Old pattern: o.yf_symbol (column alias)
  • New pattern: o.symbol AS yf_symbol
  • Suspected caller count: 3 (signals.py, timeline.py, take_signal)
  • What I expect to find: 3-5 (with ~2 extra in tests/mocks)

Step 2 — Grep with repo scope

# Standard: all Python files incl. tests, scripts, integrations
grep -rn "<old-pattern>" --include="*.py" \
  --exclude-dir=node_modules \
  --exclude-dir=.git \
  --exclude-dir=__pycache__ \
  --exclude-dir=.venv \
  | grep -v "\.pyc:"

Never just in a subdirectory (grep ... /core/). That misses the skill's goal.

Step 3 — Categorize the hit list

Sort each hit into one of these categories:

CategoryExampleAction
Production hot-pathcore/services/X.pymigrate (mandatory)
Production cold-pathnotifications/dispatcher.py, scheduler/jobs/Y.pymigrate + pre-push hook live-smoke if possible
Test/Mocktests/integration/test_Y.py with fixed datamigrate + fixture updates
Doc / Comment / Note# old: yf_symbolleave as-is (history) OR replace if fully-replace required
Deprecated-but-in-pathlegacy/foo.py with import from productionexplicitly decide: migrate OR add deprecation notice + issue
False positivesubstring match in variable nameignore

Step 4 — Migrate + verification grep

After the refactor: grep again grep -rn "<old-pattern>" — result should be empty (or only the doc/comment false-positives remain).

grep -rn "<old-pattern>" --include="*.py" | wc -l
# Expectation: 0 (or list of deliberately not-migrated hits)

Quick Reference

Refactor typeGrep pattern (example)
Column rename`grep -rn ".yf_symbol\
Helper rename`grep -rn "from .* import old_helper\
Inline-dict → SoT (variable name)grep -rn "display_names\\s*=\\s*{"
Inline-dict → SoT (value substring, catches obscured names)grep -rn "'CL=F'\\s*:\\s*'WTI" — catches _DISPLAY_MAP, LABELS, SYMBOL_NAMES etc. which copy the same mapping under another name
Deprecated importgrep -rn "from config_loader import"
Hardcoded env default`grep -rn '"c0619ab1e363"\
Magic string → enum`grep -rn "'long'\

R1 refactor (Cycle 1): the substring-grep on mapping values ('CL=F': 'WTI) is the most critical variant — it finds copies of the mapping structure under deviating variable names. Precisely this variant would have caught the signal_dispatcher.py:_get_display_name bug BEFORE the refactor (the dict there was not named display_names but was embedded in a helper function).

Anti-Patterns

Anti-PatternLesson
"I know the 3 files that use this"Mental models overlook notification/scheduler/batch — grep is 30s, less than the re-review cycle
Only grep in core/Notification dispatcher often lies in notifications/, scheduler jobs in scheduler/jobs/ — grep repo-wide
Grep without --include="*.py"Hits in .pyc, .log, node_modules noise the output
Don't grep again after refactorVerification grep is the final check — empty output = migration complete
Trust LSP refactor blindlyLSP usually finds everything, but dynamic imports (importlib) and string keys (getattr(o, "yf_symbol")) escape — grep finds both

Cost of Skipping (real)

Experience from a Phase-1 re-review (code-review cleanup):

  • Display-name SoT migration to core/utils/display.instrument_label() had covered 4 hot-path files
  • Re-review subagent found notifications/signal_dispatcher.py:_get_display_name with old config_loader path
  • Would have stayed unnoticed for weeks in the V1/V2 signal Telegram dispatch — symbols in Telegram instead of display names

Pattern: notification-dispatcher modules are rarely touched + often have their own helper versions that are not visible in the main refactor path.

Lesson: 30s grep upfront = hours of re-review cycle saved.

Red Flags — STOP and grep

  • You're writing the first new call after a refactor right now
  • Your mental model is "the 3 files" or "only in /core/"
  • Notification/scheduler/batch were not explicitly mentioned in your list
  • LSP refactor ran cleanly, but you have dynamic imports in the codebase

All mean: 30s repo-wide grep on old pattern, then categorize hit list, then migrate.

Cross-References

  • REQUIRED COMPLEMENT: pre-deploy-code-drift-detection (drift check AFTER the refactor)
  • COMPLEMENT: silent-except-hides-schema-drift (same bug class from the symptom side)
  • Maxim: "Single Source of Truth — hardcoded defaults are ticking time bombs"

Background: TDD progression (Bulletproofing log)

Cycle 1 — PASS with R1 refactor

  • RED subagent (without skill, scenario "migrate display_names inline-dicts to central instrument_label(), 3 known files"): heuristically recommended "first grep for further occurrences" — surprisingly good, but only the variable-name grep (grep -rn "display_names"). Self-critique listed 7 points (repo not inspected, DB as SoT not addressed, migration order with imports, tests before deletion, tooling hint, anti-pattern arc, no dict diff before merge).

  • GREEN subagent (with skill): brought the decisive added value — the 4th grep pass on mapping values (grep -rn "'CL=F'\s*:\s*'WTI") that catches copies of the mapping structure under deviating variable names. Plus: named concrete high-risk paths for the codebase (notifications/signal_dispatcher.py, notifications/telegram_*.py, scheduler/jobs/*.py, briefings/*.py), cross-reference to pre-deploy-code-drift-detection as complement after the refactor, schema-use-case-mismatch hint (display_name IS NULL check).

  • R1 refactor applied: Quick Reference table extended with row "Inline-dict → SoT (value substring, catches obscured names)" + hint block that this is the most critical variant (would have caught the bug).

  • Anti-pattern avoided: GREEN predicted the bug exactly — notifications/signal_dispatcher.py with its own _get_display_name would have stayed unmigrated, raw symbols in the V1/V2 Telegram dispatch for weeks.

Cycle-2-Backlog (Polish, non-blocking)

  1. CWD hint for subagent use-cases: "when your CWD is not the target repo: first cd or delegate commands to user". GREEN subagent had a CWD mismatch (vault instead of repo) and had to solve that via command suggestions.
  2. LSP find_references as complement source (not only as anti-pattern): for LSP-capable repos additional verification alongside grep.
  3. Schema-use-case mismatch as explicit sub-check in Step 3: for DB-backed lookups (instruments.display_name IS NULL) a DB-data-state check before migration is needed — own drift class.
  4. High-risk paths list for the codebase as Quick Reference: notification/, scheduler/, briefings/, analytics/, tests/integration/ — project-specifically valuable.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Gives 0 of the 12 instructions most refactoring skills give in ~2.4k tokens

Counted across 521 of the 525 authors here whose files we hold, read 2026-08-07

  • Run tests after each changein 52 of 521
  • Run the full test suite after each stepin 32 of 521
  • Preserve external behaviorin 27 of 521, across 24 files
  • Remove dead codein 26 of 521
  • Write tests before refactoringin 26 of 521, across 25 files
  • Make small incremental changesin 19 of 521, across 16 files
  • Break the implementation into tiny commitsin 18 of 521, across 5 files
  • Ask the user about alternative optionsin 17 of 521, across 4 files
  • Create a GitHub issue with the planin 17 of 521, across 4 files
  • Explore the repository to verify assertionsin 17 of 521, across 4 files
  • Interview the user about the refactorin 16 of 521, across 3 files
  • Check the codebase for test coveragein 16 of 521, across 3 files

Said here and by no other author read

  • run repo-wide grep before writing new patterns
  • exclude cache and virtual environment directories from grep
  • search mapping values to catch obscured variable names
  • categorize every grep hit
  • migrate all production hot-path hits
  • decide explicitly whether to migrate deprecated-but-in-path hits

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.

Keep looking

Skills are one crate of 326,696. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.