Skip to content
Agentmart
Submit a tool

V12-commit-discipline

Skill by HwangTaehyun

IndexedMIT
Write a review

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.

Book a call

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.

We use your email only for this newsletter. Privacy

About

The publisher has not written a description yet.

No 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.

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
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

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.

Goes to the Chalk Labs founders, not the newsletter. Privacy

Need help deploying V12-commit-discipline?

CallGet help
Cite this page

V12-commit-discipline skill. Agent Mart. https://agentmart.dev/skills/hwangtaehyun-v12-commit-discipline (last updated 2026-10-24)