From b1713f71cf06c7e42bc49e90f997e2690ecce618 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Sun, 17 May 2026 20:22:38 +0200 Subject: [PATCH] git-commit skill: enforce concise CHANGELOG entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a "Be concise" subsection with hard rules (40-word soft cap, no multi-paragraph bullets, no sub-headers, no probe numbers, no nested file lists) and a before/after example so the rule is unambiguous. Calibration tells the author to scan five existing bullets and match their length. Existing guidance ("short imperative phrases") was too easy to read past — concrete commits this session shipped 5-paragraph bullets crammed with rationale that belonged in the commit body. The new text closes that loophole. Co-Authored-By: Claude Opus 4.7 (1M context) --- .claude/skills/git-commit/SKILL.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.claude/skills/git-commit/SKILL.md b/.claude/skills/git-commit/SKILL.md index 7f057d4e..7d3481d6 100644 --- a/.claude/skills/git-commit/SKILL.md +++ b/.claude/skills/git-commit/SKILL.md @@ -53,6 +53,35 @@ This repo follows [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) Entries should be short imperative phrases that describe user-facing impact — not implementation detail. "Added sidecar PTY support for terminal pane" beats "Added `internal/pty/session.go`." +### Be concise — this is the rule, not a suggestion + +CHANGELOG entries must be **one or two short sentences**. Strict ceiling: **40 words per bullet**, hard cap at 60. If you can't say it in one line wrapped at ~75 columns, you're writing the wrong document. + +The CHANGELOG is read by humans scanning for what changed between two versions. It is **not** the place for the rationale, the probe results, the implementation detail, the behavior-change deep dive, or the "see also" cross-references. Those belong in: + +- the **commit message body** — explain *why*, list evidence, name the trade-offs; +- a **D-record / decision document** — durable architectural rationale; +- the **ticket / PR description** — work-context and review notes. + +Hard rules: + +- **No multi-paragraph bullets.** One paragraph max. If you reach for a blank line inside a bullet, stop and split or trim. +- **No "Behavior change:" / "Side benefit:" / "Note:" sub-headers inside a bullet.** Those are essay structure; put them in the commit message. +- **No probe numbers, latency stats, or %-coverage deltas in entries.** ("hit 95% target" is fine; "0 hangs in 300 spawns vs ~5% before" is commit-body material.) +- **No nested function/file lists inside parentheses.** If you find yourself writing `(foo, bar, baz, …)` for more than 3 items, just say "several X" and trust the diff. +- **Don't restate the title in the body.** A bullet is its own title. + +Calibration — match the **existing entries** in `CHANGELOG.md`. Open it, look at five recent bullets, write to that length. If your draft is visibly bigger than its neighbors, trim until it isn't. + +Good: +> - Mouse wheel scrolling in Claude pane — converts scroll events to PgUp/PgDown so TUI apps scroll naturally. + +Bad (verbose; commit-body material leaked in): +> - **PTY spawning switched from `forkpty()` to `posix_openpt()` + `posix_spawn()`** (T-96). `forkpty` calls `fork()` underneath, which is unsafe in the multithreaded Dart VM: about 5% of spawns deadlocked in the child before `execve` because libc locks held by ghost-threads remained "locked forever" in the forked child. `posix_spawn` uses `vfork` (glibc/musl/macOS), keeping the parent suspended until `execve` completes — no Dart code runs in the child. Probed: zero hangs in 300 sequential spawns vs ~5% before. **Behavior change:** missing executable / missing workingDirectory now surface as a `PtyException`… + +Better: +> - PTY spawning uses `posix_openpt` + `posix_spawn` instead of `forkpty` — closes a ~5% deadlock window in the multithreaded Dart VM (T-96). Missing exe/cwd now throw `PtyException` at spawn time. + **What skips the changelog:** pure bookkeeping commits that have no user-visible effect (typo fix in internal comment, `.gitignore` tweak, lint config change, reformatting). When in doubt, add an entry — the harm of an extra line is zero. When a commit spans multiple entries (e.g. a feature that adds one thing and fixes another), add a line under each applicable subsection rather than cramming both into one.