Skip to content

Add Pre-Commit Hook to Validate Sub-CLAUDE.md Completeness#1978

Merged
Trecek merged 3 commits into
developfrom
add-pre-commit-hook-to-validate-sub-claude-md-completeness/1975
May 6, 2026
Merged

Add Pre-Commit Hook to Validate Sub-CLAUDE.md Completeness#1978
Trecek merged 3 commits into
developfrom
add-pre-commit-hook-to-validate-sub-claude-md-completeness/1975

Conversation

@Trecek
Copy link
Copy Markdown
Collaborator

@Trecek Trecek commented May 6, 2026

Summary

Add a validate-only pre-commit hook (scripts/check_sub_claude_md.py) that checks every sub-CLAUDE.md file table mentions all .py files in its directory. This catches the gap at commit time (during pre-commit run --all-files) instead of at CI time, preventing the systematic 5+ CI round-trip failures observed since PR #1820. The script replicates the coverage logic from test_sub_claude_md_covers_all_py_files and test_tests_sub_claude_md_covers_all_py_files, using the same EXPECTED_SUB_CLAUDE_MDS lists. A new .pre-commit-config.yaml stanza triggers it on .py file changes under src/autoskillit/ and tests/.

Requirements

  • New script: scripts/check_sub_claude_md.py (validate-only, exits 1 with structured message on mismatch)
  • New stanza in .pre-commit-config.yaml triggered on files: ^(tests/|src/autoskillit/).*\.py$
  • Must check both tests/<subdir>/CLAUDE.md and src/autoskillit/<subdir>/CLAUDE.md file tables
  • Must use the same EXPECTED_SUB_CLAUDE_MDS lists as the test files (or derive from disk)
  • No auto-fix — the agent must manually add the row with a meaningful Purpose description
  • Pattern: pass_filenames: false (like existing doc-counts hook)

Changed Files

New (★):

★ scripts/check_sub_claude_md.py
★ tests/docs/test_check_sub_claude_md_script.py

Modified (●):

● .pre-commit-config.yaml
● tests/docs/CLAUDE.md
● tests/infra/test_ci_dev_config.py

Closes #1975

Implementation Plan

Plan file: /home/talon/projects/autoskillit-runs/impl-20260505-211945-173795/.autoskillit/temp/make-plan/add_pre_commit_hook_sub_claude_md_plan_2026-05-05_213000.md

🤖 Generated with Claude Code via AutoSkillit

Token Usage Summary

Step count uncached output cache_read peak_ctx turns cache_write time
plan 1 2.6k 13.2k 505.4k 61.2k 80 83.5k 7m 59s
verify 1 35 7.2k 746.3k 56.0k 84 47.6k 5m 25s
implement 1 503.5k 7.9k 682.3k 44.8k 75 43.4k 6m 19s
prepare_pr 1 83.0k 3.3k 186.8k 26.7k 21 39.0k 1m 16s
compose_pr 1 59.5k 2.0k 210.6k 26.7k 21 15.0k 56s
review_pr 1 142 30.8k 755.5k 77.1k 47 66.0k 7m 8s
resolve_review 1 325 28.6k 2.3M 92.3k 102 79.8k 12m 19s
Total 649.1k 93.0k 5.4M 92.3k 374.2k 41m 22s

Token Efficiency

Step LoC Changed cache_read/LoC cache_write/LoC output/LoC
plan 0
verify 0
implement 266 2564.9 163.2 29.6
prepare_pr 0
compose_pr 0
review_pr 0
resolve_review 18 126061.9 4432.1 1589.9
Total 284 18859.0 1317.7 327.3

Introduces scripts/check_sub_claude_md.py as a validate-only pre-commit hook
that checks every sub-CLAUDE.md file table mentions all .py files in its
directory. This catches coverage gaps at commit time rather than CI time.

- scripts/check_sub_claude_md.py: new hook script with SRC_EXPECTED (27 dirs)
  and TESTS_EXPECTED (19 dirs) lists mirroring the test suite's lists
- .pre-commit-config.yaml: new check-sub-claude-md hook in local repo hooks
- tests/docs/test_check_sub_claude_md_script.py: 9 unit/integration tests for
  check_coverage() and main(), plus list-sync guards against the test files
- tests/infra/test_ci_dev_config.py: structural test verifying the hook is
  present in pre-commit config with pass_filenames: false
- tests/docs/CLAUDE.md: added test_check_sub_claude_md_script.py entry

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator Author

@Trecek Trecek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AutoSkillit PR Review — Verdict: approved_with_comments

SRC_ROOT = PROJECT_ROOT / "src" / "autoskillit"
TESTS_ROOT = PROJECT_ROOT / "tests"

SRC_EXPECTED = [
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] arch: SRC_EXPECTED and TESTS_EXPECTED are static hardcoded lists. When a new package sub-directory with a CLAUDE.md is added, the script silently ignores it. The hook should dynamically discover all CLAUDE.md files under SRC_ROOT and TESTS_ROOT rather than relying on an opt-in list that must be manually maintained.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid observation — flagged for design decision. Dynamic discovery vs. hardcoded opt-in list is an architectural choice requiring human decision: dynamic discovery would make the lists in TestExpectedListsSync sync tests obsolete and change the hook's scope significantly.

Comment thread scripts/check_sub_claude_md.py
Comment thread scripts/check_sub_claude_md.py Outdated
Comment thread scripts/check_sub_claude_md.py
spec = importlib.util.spec_from_file_location(test_module_name, test_file)
assert spec is not None and spec.loader is not None
test_mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(test_mod)
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[warning] bugs: spec.loader.exec_module(test_mod) is called without guarding that spec.loader implements exec_module. The assertion on L110 only checks spec.loader is not None. A TypeError or AttributeError would surface as an opaque test failure rather than a clear message.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid observation — flagged for design decision. spec_from_file_location for a .py file always returns SourceFileLoader which implements exec_module — near-zero risk in practice. Adding a hasattr guard would improve the error message but requires a design decision on failure behavior.

Comment thread tests/docs/test_check_sub_claude_md_script.py
Comment thread tests/docs/test_check_sub_claude_md_script.py
Comment thread tests/docs/test_check_sub_claude_md_script.py
Copy link
Copy Markdown
Collaborator Author

@Trecek Trecek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AutoSkillit review: warning-only findings detected. See inline comments — no blocking changes required.

Trecek and others added 2 commits May 5, 2026 22:05
…ile coverage

- Missing CLAUDE.md paths now append a failure message instead of silently
  continuing, preserving the coverage guarantee for directories that lost
  their CLAUDE.md file.
- Regular .py file check changed from bare substring match to backtick-form
  check (f"\`{name}\`") — consistent with the existing __init__.py check and
  the actual table format used in all sub-CLAUDE.md files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…edium

- test_check_coverage_skips_nonexistent_claude_md renamed and updated to
  expect a failure message for missing CLAUDE.md (mirrors script fix).
- Module pytestmark changed from small to medium: test_main_returns_zero_on_live_repo
  performs real filesystem I/O against the live repo tree, exceeding the small
  definition (no persistent I/O).
- Fix pre-existing E501 line-length violations in docstrings and string literals.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Trecek Trecek added this pull request to the merge queue May 6, 2026
Merged via the queue into develop with commit a48265f May 6, 2026
2 checks passed
@Trecek Trecek deleted the add-pre-commit-hook-to-validate-sub-claude-md-completeness/1975 branch May 6, 2026 05:28
Trecek added a commit that referenced this pull request May 8, 2026
## Summary

Add a validate-only pre-commit hook (`scripts/check_sub_claude_md.py`)
that checks every sub-CLAUDE.md file table mentions all `.py` files in
its directory. This catches the gap at commit time (during `pre-commit
run --all-files`) instead of at CI time, preventing the systematic 5+ CI
round-trip failures observed since PR #1820. The script replicates the
coverage logic from `test_sub_claude_md_covers_all_py_files` and
`test_tests_sub_claude_md_covers_all_py_files`, using the same
`EXPECTED_SUB_CLAUDE_MDS` lists. A new `.pre-commit-config.yaml` stanza
triggers it on `.py` file changes under `src/autoskillit/` and `tests/`.

## Requirements

- New script: `scripts/check_sub_claude_md.py` (validate-only, exits 1
with structured message on mismatch)
- New stanza in `.pre-commit-config.yaml` triggered on `files:
^(tests/|src/autoskillit/).*\.py$`
- Must check both `tests/<subdir>/CLAUDE.md` and
`src/autoskillit/<subdir>/CLAUDE.md` file tables
- Must use the same `EXPECTED_SUB_CLAUDE_MDS` lists as the test files
(or derive from disk)
- No auto-fix — the agent must manually add the row with a meaningful
Purpose description
- Pattern: `pass_filenames: false` (like existing `doc-counts` hook)

## Changed Files

### New (★):
★ scripts/check_sub_claude_md.py
★ tests/docs/test_check_sub_claude_md_script.py

### Modified (●):
● .pre-commit-config.yaml
● tests/docs/CLAUDE.md
● tests/infra/test_ci_dev_config.py

Closes #1975

## Implementation Plan

Plan file:
`/home/talon/projects/autoskillit-runs/impl-20260505-211945-173795/.autoskillit/temp/make-plan/add_pre_commit_hook_sub_claude_md_plan_2026-05-05_213000.md`

🤖 Generated with [Claude Code](https://claude.com/claude-code) via
AutoSkillit
<!-- autoskillit:pipeline-signature
steps=prepare_pr,run_arch_lenses,compose_pr,annotate_pr_diff,review_pr
-->

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant