diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-23 20:48:44 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-23 20:48:44 -0500 |
| commit | c238afbd4150ef53737f16e7dd84a565d2838ecc (patch) | |
| tree | 588a25dc318cb854c57d8146639d400674baed18 /scripts/tests/install-lang.bats | |
| parent | 10ea44b6de3be1872f7f0bd4501ccf3878105bc4 (diff) | |
| download | rulesets-c238afbd4150ef53737f16e7dd84a565d2838ecc.tar.gz rulesets-c238afbd4150ef53737f16e7dd84a565d2838ecc.zip | |
feat(languages): ship the missing python and typescript hooks
The python and typescript bundles carried rules and a coverage script but no pre-commit hook, so any project installing one got no credential scan on commit. Both now ship all four components the README documents: the shared secret scan, a validate-on-edit hook, settings wiring, and a seed CLAUDE.md. Verified against a real repo: a commit carrying an AWS key is refused.
install-lang now warns when a bundle is missing a documented component. That's the half that keeps this from recurring. Whoever adds the sixth bundle will forget something too, and today the installer prints success either way.
Two things fell out of the build. node --check is unusable on TypeScript: it ignores --experimental-strip-types, so it rejects valid TS and accepts broken TS. The hook uses tsc filtered to syntactic diagnostics instead. And completing the bundles means every pair now collides on settings.json and pre-commit, so no two compose without FORCE=1. The earlier "bundles already compose" reading rested on these two being incomplete. Filed for a real decision; clock-panel is the project that wants it.
Also stamps :LAST_REVIEWED: at task creation, with a lint checker to catch misses. Writing a task is reviewing it, so leaving the stamp off pushed every fresh task to the top of the next review batch to be re-derived by someone with less context than its author had. Tonight's sweep sent the staleness count from 13 to 22 while the list got more accurate.
Diffstat (limited to 'scripts/tests/install-lang.bats')
| -rw-r--r-- | scripts/tests/install-lang.bats | 62 |
1 files changed, 57 insertions, 5 deletions
diff --git a/scripts/tests/install-lang.bats b/scripts/tests/install-lang.bats index 8518852..c00b915 100644 --- a/scripts/tests/install-lang.bats +++ b/scripts/tests/install-lang.bats @@ -79,19 +79,42 @@ teardown() { grep -qxF "coverage/" "$PROJECT/.gitignore" } -@test "install-lang python: seeds the language-neutral default CLAUDE.md when the bundle ships none" { - run bash "$INSTALL_LANG" python "$PROJECT" +@test "install-lang: seeds the language-neutral default CLAUDE.md when the bundle ships none" { + # Every shipping bundle now carries its own CLAUDE.md (python and typescript + # gained theirs 2026-07-23), so the fallback needs a synthetic bundle to + # exercise. Keep testing it: the fallback is what stops a bundle added later, + # before its CLAUDE.md is written, from inheriting another language's header. + fake="$REAL_REPO/languages/zz-test-noclaude" + mkdir -p "$fake/claude/rules" + printf '# rule\n' > "$fake/claude/rules/zz.md" + run bash "$INSTALL_LANG" zz-test-noclaude "$PROJECT" + rm -rf "$fake" [ "$status" -eq 0 ] [ -f "$PROJECT/CLAUDE.md" ] - # The default names no language, so it can't mislabel a python (or bash, or - # multi-bundle) project the way inheriting elisp's "Elisp project" header did. - ! grep -qi "Python project" "$PROJECT/CLAUDE.md" + # The default names no language, so it can't mislabel a project the way + # inheriting elisp's "Elisp project" header did. ! grep -qi "Elisp project" "$PROJECT/CLAUDE.md" grep -qF "names no language" "$PROJECT/CLAUDE.md" [[ "$output" == *"language-neutral default"* ]] } +@test "install-lang python: seeds the bundle's own CLAUDE.md, not the default" { + run bash "$INSTALL_LANG" python "$PROJECT" + + [ "$status" -eq 0 ] + grep -qF "Python project." "$PROJECT/CLAUDE.md" + [[ "$output" == *"CLAUDE.md installed (python)"* ]] +} + +@test "install-lang typescript: seeds the bundle's own CLAUDE.md, not the default" { + run bash "$INSTALL_LANG" typescript "$PROJECT" + + [ "$status" -eq 0 ] + grep -qF "TypeScript/JavaScript project." "$PROJECT/CLAUDE.md" + [[ "$output" == *"CLAUDE.md installed (typescript)"* ]] +} + @test "install-lang elisp: seeds the bundle's own CLAUDE.md, not the default" { run bash "$INSTALL_LANG" elisp "$PROJECT" @@ -147,3 +170,32 @@ teardown() { grep -qxF ".claude/" "$PROJECT/.gitignore" grep -qxF "cover.out" "$PROJECT/.gitignore" } + +@test "install-lang python: full bundle lands (rules, hook, settings, githook, CLAUDE.md, coverage)" { + run bash "$INSTALL_LANG" python "$PROJECT" + + [ "$status" -eq 0 ] + [ -f "$PROJECT/.claude/rules/python-testing.md" ] + # PostToolUse validate hook, executable and wired into settings + [ -x "$PROJECT/.claude/hooks/validate-python.sh" ] + grep -qF "validate-python.sh" "$PROJECT/.claude/settings.json" + # Pre-commit githook — the secret scan. Absent until 2026-07-23. + [ -x "$PROJECT/githooks/pre-commit" ] + grep -qF "potential secret" "$PROJECT/githooks/pre-commit" + # Coverage slice + [ -f "$PROJECT/.claude/scripts/coverage-summary.py" ] + grep -qxF ".claude/" "$PROJECT/.gitignore" +} + +@test "install-lang typescript: full bundle lands (rules, hook, settings, githook, CLAUDE.md, coverage)" { + run bash "$INSTALL_LANG" typescript "$PROJECT" + + [ "$status" -eq 0 ] + [ -f "$PROJECT/.claude/rules/typescript-testing.md" ] + [ -x "$PROJECT/.claude/hooks/validate-typescript.sh" ] + grep -qF "validate-typescript.sh" "$PROJECT/.claude/settings.json" + [ -x "$PROJECT/githooks/pre-commit" ] + grep -qF "potential secret" "$PROJECT/githooks/pre-commit" + [ -f "$PROJECT/.claude/scripts/coverage-summary.js" ] + grep -qxF ".claude/" "$PROJECT/.gitignore" +} |
