meta(tasks): create [tdd-criteria-precommit-hook] in claude-skills
This commit is contained in:
@@ -508,3 +508,76 @@ Both layers are needed. Either alone leaves a path-of-least-resistance route to
|
||||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: .meeting-room / 2026-05-07T04:03:12.170Z -->
|
||||
|
||||
---
|
||||
|
||||
## ⚪ [tdd-criteria-precommit-hook] — Optional pre-commit hook script that automates the bright-line checks from `tdd-criteria` Anti-loophole rules 1 and 4. Project owner opts in per-repo by symlinking / copying to `.git/hooks/pre-commit` (or via `husky` / `lefthook` integration if the project uses them).
|
||||
|
||||
**Two checks** (both bright-line, both fail-closed):
|
||||
|
||||
**Check 1 — `[skip-tdd: <category>]` validation.** If `git diff --cached --name-only` includes a `*.ts` / `*.js` / `*.py` / similar code file (excluding tests and Permissive-zoned paths like `*.css` / `*.env*` / `*.md` / `*.yaml`), require either:
|
||||
- A `*.test.*` / `*.spec.*` / `test_*.py` / similar file present in the same diff, OR
|
||||
- The commit subject (read from `$1` arg, line 1 of `$1` = msg path) matches `\[skip-tdd: (visual|spike|oneshot|wrapper)\]`.
|
||||
|
||||
If neither holds → block with message:
|
||||
```
|
||||
TDD policy violation: code change without test or skip marker.
|
||||
Add a test, or include [skip-tdd: <visual|spike|oneshot|wrapper>] in commit subject.
|
||||
See claude-skills/.wiki/concepts/tdd-criteria-design.md for which category applies.
|
||||
```
|
||||
|
||||
**Check 2 — Test-modification audit (`[test-modify]` rule 4).** Detect test-modifying changes in `git diff --cached`:
|
||||
- Removed line matching `^-\s*(expect|assert|assertThat|chai\.)\(` (assertion deletion)
|
||||
- Added/removed lines that change argument values inside `expect(...)` / `assert(...)` calls
|
||||
- Added `.skip` / `\.xit\b` / `@pytest\.mark\.skip` / `@Disabled` / `@Ignore` annotations
|
||||
- Deleted `it(...)` / `test(...)` / `def test_*` definitions (matches `^-\s*(it|test|describe)\(` or `^-def test_`)
|
||||
|
||||
If any matched → require commit subject matches `\[test-modify: [^:]+: was .+; is .+; reason: .+\]`. Block otherwise with message:
|
||||
```
|
||||
Test-modification without [test-modify: ...] marker.
|
||||
Required format: [test-modify: <name>: was <literal>; is <literal>; reason: <Z>]
|
||||
The was/is must be the LITERAL assertion expressions, not paraphrased.
|
||||
See tdd-criteria Anti-loophole rule 4.
|
||||
```
|
||||
|
||||
ALSO: if `git diff --cached --name-only` includes both a test-pattern file AND an impl-pattern file → block:
|
||||
```
|
||||
Test changes must be in a separate commit from impl changes (tdd-criteria rule 4b).
|
||||
Run: git reset HEAD <impl-files> && git commit (test-only) && git add <impl-files> && git commit (impl-only).
|
||||
```
|
||||
|
||||
**Implementation:**
|
||||
- Bash script (single file). Cross-platform: works on Linux/macOS and on Windows under git-bash (which Claude/Hermes both already run on).
|
||||
- Path: `~/projects/claude-skills/scripts/tdd-criteria-precommit-hook.sh`. Plus a Windows wrapper `.ps1` that delegates if needed.
|
||||
- Tested on a real repo before commit (`books` is a good candidate — it has Jest tests + `*.test.js` convention).
|
||||
- Documented in `claude-skills/.wiki/concepts/tdd-criteria-design.md` «See also» section (already linked).
|
||||
|
||||
**Activation pattern (per-repo):**
|
||||
```bash
|
||||
# Symlink or copy the hook
|
||||
ln -sf ~/projects/claude-skills/scripts/tdd-criteria-precommit-hook.sh \
|
||||
.git/hooks/pre-commit
|
||||
chmod +x .git/hooks/pre-commit
|
||||
```
|
||||
|
||||
Or via `lefthook.yml` / `.husky/pre-commit` if the project already uses one of those.
|
||||
|
||||
**Out of scope:**
|
||||
- Mutation testing (Stryker, mutmut) — separate heavyweight infra, not this hook.
|
||||
- Coverage gates — different mechanism, different cost/benefit.
|
||||
- Visual regression infra (Percy, Chromatic) — Permissive-5 acknowledges this is heavyweight; not bundled.
|
||||
- Auto-fixing the violation — hook only blocks; fix is human's job.
|
||||
|
||||
**Why this is optional, not required by the SKILL.md:**
|
||||
|
||||
The skill is **policy** that lives in claude-skills and gets pulled into agent context per project. The hook is **enforcement** that needs per-project setup. Some projects opt out of pre-commit hooks entirely (e.g. `karu` if it's pure CSS — no code surface to enforce). Forcing the hook into the skill would couple policy to tooling.
|
||||
|
||||
**Bypass:**
|
||||
|
||||
Pre-commit hooks have `--no-verify`. Per `project-discipline` Rule 4 («never skip hooks unless user explicitly asks») agents must not use `--no-verify` — but humans can in emergencies. Each `--no-verify` use should be self-flagged in the commit body («bypassed pre-commit because: ...»). Not enforceable by the hook itself; this is a higher-level audit.
|
||||
|
||||
**Status:** ready
|
||||
**Where I stopped:** (not started)
|
||||
**Next action:** Решить, нужен ли hook (он опционален) — если да, написать `~/projects/claude-skills/scripts/tdd-criteria-precommit-hook.sh` по спеке в description, протестировать на `books` (Jest-конвенция `*.test.js`), задокументировать activation pattern. Если нет — закрыть как `wontfix` с пометкой что fence чисто социальная (commit subject visible в `git log`).
|
||||
**Branch:** master
|
||||
<!-- created-by: OpeItcLoc03@DESKTOP-NSEF0UK / from: .meeting-room / 2026-05-07T05:10:28.610Z -->
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user