Chalk Labs
Need help deploying V12-commit-discipline?
Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.
Install
Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.
npx agentmarket install skill/hwangtaehyun-v12-commit-discipline
Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.
Get the weekly diff
The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.
About
Reviews
Write a reviewNo reviews yet. Installed it? Reviews come from verified installers only. How reviews work
Permissions: not checked yet.
What's inside
- Skill name
V12-commit-discipline- Description
- None
- License
- MIT
- Instructions
- 171 lines in SKILL.md · view on GitHub
Agent Skills spec issues
- missing YAML frontmatter
- name: missing
- description: missing
Files (1)
- SKILL.md
SKILL.md (first lines)
# V12 — commit-discipline
> **Owner**: `hooks/validators/commit_discipline.py`
> **Tier**: 3 (Stop) only — Tier 2 (PostToolUse) is irrelevant because git working-tree state is the input, and that state is meaningful only at end-of-turn.
> **File patterns**: empty (matches every file). The whole-project view is what matters.
## Rules
| Rule ID | Severity | When |
|---|---|---|
| `V12-UNSTAGED-CHANGES` | warning | `git status --porcelain` shows working-tree modifications. The Stop hook is about to end the turn but the user has uncommitted work. |
| `V12-LARGE-DIFF` | warning | The unstaged + staged change touches more files than `thresholds.commit.large_diff_files` (default 15). Suggests splitting before commit. |
| `V12-MIXED-CHANGE` | warning | Same diff contains both rename / delete (`R` / `D`) and modify (`M`) entries — Kent Beck's "structural vs behavioral" mix that obscures the intent. |
| `V12-NO-TEST-IN-FEATURE` | warning | Source files (`*.go`, `*.ts(x)`, `*.py`) changed but no test files (`*_test.go`, `*.test.ts(x)`, `test_*.py`) changed. Bug-fix or feature without a test landing alongside it. |
| `V12-COMMIT-MSG-FORMAT` | warning | The most recent commit message (or, in some flows, the commit-message draft) does not match `^(feat|fix|refactor|docs|test|chore|style|perf|ci|build|revert)(\(.+\))?!?:\s+.+`. |
## Why this verifier exists
V12 enforces **Kent Beck's "Tidy First?" / atomic-commit discipline** at the moment a turn ends:
- **Atomic commits.** A 50-file diff covering 4 different intents is unreviewable. Splitting it into 4 commits gives reviewers a fighting chance.
- **Structural / behavioral separation.** Renaming a file *while* changing its semantics in the same commit hides the rename from diff tools. Splitting is cheap; not splitting is permanent code-archaeology debt.
- **Test alongside change.** A feature without a test or a bug-fix without a regression test is a permanent invitation to re-break.
- **Conventional Commits format.** Tooling-friendly history (changelog generation, automated semantic-version bumps, search) requires consistent messages.
V12 fires at Stop because that's where the user's "I'm done with this slice" intent is — and that's the moment to nudge them toward a tidier commit.
## Design rationale
- **Tier 3 only.** Working-tree state mid-edit is meaningless ("I'm in the middle of typing"). Stop is the right inflection point.
- **All warnings, not errors.** Every V12 rule has legitimate exceptions: a deliberately big "merge feature branch" commit, a structural-only refactor with no test changes (rename only), an emergency hotfix that bypasses Conventional Commits. Hard-failing Stop on these would erode trust in the validator.
- **`thresholds.commit.large_diff_files` is configurable.** A monorepo with auto-generated code can legitimately have 50-file commits; a small library can't. Project-level knob.
- **`-- INTENTIONAL:` style escape is *not* present.** Unlike V04's DDL, V12's warnings can't be silenced per-finding because they're noisy by design — the user is supposed to see them and decide.
- **Commit-message format takes the most recent commit.** Not the next-to-be-written one (we don't have access). The model is: the user just amended/committed, V12 reads what landed.
## How it checks (implementation)
Lives in `hooks/validators/commit_discipline.py`. `validate_project` is the only entry point.
### `validate_project(ctx)` — top-level
```python
def validate_project(self, ctx):
findings: list[Finding] = []
large_diff_threshold = ctx.config.thresholds.commit.large_diff_files
cwd = str(ctx.project_root)
# 1. Working-tree status
status = _run_git(["status", "--porcelain"], cwd)
if not status:
return findings # clean tree — nothing to check (already committed)
status_lines = [l for l in status.split("\n") if l.strip()]
yield Finding(
severity="warning",
rule="V12-UNSTAGED-CHANGES",
message=f"{len(status_lines)} unstaged/uncommitted change(s)",
...
)
# 2. Parse status into (status_code, file_path) tuples
all_files: list[tuple[str, str]] = []
for line in status_lines:
if len(line) < 4:
continue
code, path = line[:2], line[3:].strip()
all_files.append((code, path))
# 3. Large-diff
if len(all_files) >= large_diff_threshold:
yield Finding(rule="V12-LARGE-DIFF", ...)
# 4. Mixed structural + behavioral
findings.extend(self._check_mixed_changes(all_files, cwd))
# 5. Test-alongside-source
findings.extend(self._check_test_coverage(all_files, ctx))
# 6. Commit-message format
findings.extend(self._check_commit_msg_format(cwd))
return findings
```
### `_check_mixed_changes(all_files, cwd)` — V12-MIXED-CHANGE
```python
# Use `git diff --name-status HEAD` to get the full status (R/D/M)
# rather than working-tree-only `git status` (which can't see renames cleanly).
diff = _run_git(["diff", "--name-status", "HEAD"], cwd).splitlines()
has_structural = any(line[:1] in ("R", "D") for line in diff)
has_behavioral = any(line[:1] in ("M",) for line in diff)
if has_structural and has_behavioral:
yield Finding(rule="V12-MIXED-CHANGE", ...)
```
### `_check_test_coverage(all_files, ctx)` — V12-NO-TEST-IN-FEATURE
```python
SOURCE_PATTERNS = (".go", ".py", ".ts", ".tsx")
TEST_PATTERNS = ("_test.go", ".test.ts", ".test.tsx", ".spec.ts", ".spec.tsx")
def _is_source(p):
return p.endswith(SOURCE_PATTERNS) and not _is_test(p) \
and not p.endswith(("_test.go",)) \
and "test_" not in Path(p).name
def _is_test(p):
return p.endswith(TEST_PATTERNS) or Path(p).name.startswith("test_")
source_changed = any(_is_source(p) for _, p in all_files)
test_changed = any(_is_test(p) for _, p in all_files)
if source_changed and not test_changed:
yield Finding(rule="V12-NO-TEST-IN-FEATURE", ...)
```
### `_check_commit_msg_format(cwd)` — V12-COMMIT-MSG-FORMAT
```python
msg = _run_git(["log", "-1", "--pretty=%s"], cwd).strip()
CONVENTIONAL = re.compile(
r'^(feat|fix|refactor|docs|test|chore|style|perf|ci|build|revert)'
r'(\([^)]+\))?!?:\s+.+'From HwangTaehyun/verifiers, MIT.
More from HwangTaehyun/verifiers
- 0.251score
V18-mock-data-guard
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V20-hasura-graphql
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V01-env-config
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V02-graphql-gen
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V03-proto-connect
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V04-hasura-migration
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V06-go-quality
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V07-ts-quality
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V08-security
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V09-go-test-runner
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V10-ts-test-runner
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9 - 0.251score
V11-py-test-runner
HwangTaehyun
No description from the publisher yet.
SkillCFreshness: CClaude Code +9
Signals
- Stars
- 0
- Forks
- 0
- Open issues
- 0
- Last commit (this folder)
- Apr 29, 2026 (6 months ago)
From GitHub (fetched Oct 24, 2026).
Details
- License
- MIT
- Repository
- github.com/HwangTaehyun/verifiers
- First seen
- Oct 24, 2026
- Last checked
- Oct 24, 2026
- Source
- GitHubgithub-graphql
Done for you
Rather not set it up yourself?
Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.
See how we build AI agents →Read the case studies
Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.
- launches shipped
- 50+
- launches shipped
- media placements
- 500+
- media placements
- founders on every account
- 2
- founders on every account
Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block
Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.
Get V12-commit-discipline running in your business
Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.
Cite this page
V12-commit-discipline skill. Agent Mart. https://agentmart.dev/skills/hwangtaehyun-v12-commit-discipline (last updated 2026-10-24)