.claude-plugin/skills/orphan-config-detection/SKILL.md
# Orphan Config Detection ## Overview | Field | Value | |------------|-----------------------------------------------------------------| | Date | 2026-02-20 | | Issue | #777 | | PR | #824 | | Objective | Warn when a `config/models/*.yaml` file
npx skillsauth add homericintelligence/projectscylla .claude-plugin/skills/orphan-config-detectionInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
| Field | Value |
|------------|-----------------------------------------------------------------|
| Date | 2026-02-20 |
| Issue | #777 |
| PR | #824 |
| Objective | Warn when a config/models/*.yaml file is not referenced by any experiment or test file |
| Outcome | Success — 2220 tests pass, 73.4% coverage, pre-commit clean |
| Category | testing |
Apply this pattern when:
validation.py module with a similar convention (filename ↔ field consistency)Add to scylla/config/validation.py:
_REFERENCE_EXTENSIONS = ("*.yaml", "*.py")
def validate_model_config_referenced(
config_path: Path, search_roots: list[Path]
) -> list[str]:
"""Warn if model config file is not referenced by any file under search_roots."""
stem = config_path.stem
if stem.startswith("_"): # skip test fixtures
return []
for root in search_roots:
if not root.exists():
continue
for ext_pattern in _REFERENCE_EXTENSIONS:
for f in root.rglob(ext_pattern):
if f == config_path: # don't count self
continue
try:
if stem in f.read_text(encoding="utf-8", errors="ignore"):
return []
except (OSError, PermissionError):
continue
return [
f"Model config '{config_path.name}' is not referenced by any file under "
f"{[str(r) for r in search_roots]}. It may be orphaned."
]
Key design decisions:
list[str] (same shape as validate_filename_model_id_consistency) — stays consistent with existing conventions_-prefix skips test fixtures — consistent with the filename validatorIn load_all_models() (loader.py), add a second pass after loading all models:
search_roots = [self.base_path / "config", self.base_path / "tests"]
for model_file in sorted(models_dir.glob("*.yaml")):
if model_file.name.startswith(".") or model_file.stem.startswith("_"):
continue
for warning in validate_model_config_referenced(model_file, search_roots):
logger.warning(warning)
Do it as a second pass (not inline with loading) so all model files are checked regardless of whether they loaded successfully.
File: tests/unit/test_config_validation.py
Cover these cases:
.yaml → no warning.py → no warning_-prefixed fixture → no warningsearch_roots → warningFile: tests/unit/test_config_loader.py — add TestModelConfigOrphanValidation class:
test_load_all_models_warns_unreferenced — caplog captures WARNING with filenametest_load_all_models_no_warn_referenced — no orphan warning when referencedtest_load_all_models_skips_test_fixtures — _-prefixed files never warnedpixi run python -m pytest tests/unit/test_config_validation.py tests/unit/test_config_loader.py -v
pre-commit run --files scylla/config/validation.py scylla/config/loader.py tests/unit/test_config_validation.py tests/unit/test_config_loader.py
None on this task — the approach was straightforward given the existing codebase patterns.
| Metric | Value |
|-------------------|--------------------------------|
| New functions | 1 (validate_model_config_referenced) |
| New test file | tests/unit/test_config_validation.py (8 tests) |
| Modified files | scylla/config/validation.py, scylla/config/loader.py, tests/unit/test_config_loader.py |
| Tests added | 11 (8 unit + 3 integration) |
| Total tests pass | 2220 |
| Coverage | 73.4% (meets 73% threshold) |
| Pre-commit result | All hooks pass |
list[str] (warnings), never raise_-prefixed files are test fixtures — always skip validationlogger.warning() in the loader, not in the validator itselfconfig/ and tests/ (covers both experiment YAMLs and test Python files)_REFERENCE_EXTENSIONS = ("*.yaml", "*.py") — extend this tuple if you add new file typesdevelopment
# Skill: docs-status-fix ## Overview | Field | Value | |------------|----------------------------------------------------| | Date | 2026-02-19 | | Category | documentation | | Objective | Fix stale "Current Status" in CLAUDE.md | | Issue | #753 | | PR | #810
tools
# Skill: preflight-closing-issues-fix ## Overview | Field | Value | |-------|-------| | Date | 2026-02-21 | | Issue | #802 | | PR | #912 | | Category | tooling | | Objective | Fix `preflight_check.sh` Check 3 false positives caused by free-text PR search matching issue numbers in unrelated PR titles/bodies | | Outcome | Success — 6 bash tests pass, all pre-commit hooks green, PR created with auto-merge | ## When to Use Trigger this skill when: - A preflight/guard script uses `gh pr list --s
tools
# Preflight Check Skill Propagation ## Overview | Field | Value | |-------|-------| | Date | 2026-02-21 | | Issue | #803 | | Objective | Add preflight check to `worktree-create` skill so developers bypassing `gh-implement-issue` still run the 6-check safety gate | | Outcome | Success — PR #917 created, auto-merge enabled | | Files Changed | `tests/claude-code/shared/skills/worktree/worktree-create/SKILL.md` | ## When to Use Use this pattern when: - A safety/quality gate exists in one entry-
tools
# Skill: model-config-naming-validation ## Overview | Field | Value | |------------|----------------------------------------------------| | Date | 2026-02-19 | | Issue | #682 | | PR | #769 | | Objective | CI check that filename matches model_id in YAML configs | | Outcome | Success — 28 tests