ai: Refine commit message discipline guidance
Commit messages need rigorous scrutiny, not hard sentence limits. Updated CLAUDE.md
and describing-changes skill to enforce the real constraint: each sentence must
explain reasoning not visible in the diff. If exceeding 3 sentences, rigorously
question necessity (not nice-to-have). Added footer requirement to describing-changes.
Assisted-by: Claude Haiku 4.5 via Claude Code
diff --git a/ai/AI.md b/ai/AI.md
index a08d005a..2bd9b9c5 100644
--- a/ai/AI.md
+++ b/ai/AI.md
@@ -101,14 +101,28 @@ Common replacements:
- `git log` → `jj log`
When AI assists in crafting commit messages, include an "assisted-by"
-footer with model and tool:
+footer with model and tool. Format: `Assisted-by: [Model] via Claude Code`
+Example:
```
-Assisted-by: Claude Sonnet 4 via Claude Code
+Assisted-by: Claude Haiku 4.5 via Claude Code
```
+**Commit message discipline:**
+- First line: under 60 characters, concrete problem or fix
+- Body: typically 2-3 sentences (50-75 words)
+- Use describing-changes skill AND elements-of-style skill
+- Each sentence must earn its place. If exceeding 3 sentences, rigorously question whether every sentence is necessary (not nice-to-have)
+- Problem → Solution format only. Strip what's visible in diff.
+
Use the describing-changes skill to explain reasoning and decisions in commit
messages. Focus on why the change was made rather than what the diff shows.
+If you find the message getting long, you're describing the change instead of
+explaining it.
+
+**Before committing:** Ask "Is every sentence in this message invisible in the diff?"
+If any sentence just restates what the code change shows, delete it. The diff shows
+what changed. Only explain why if it's not obvious from reading the diff.
## Ruby
diff --git a/ai/claude/commands/commit.md b/ai/claude/commands/commit.md
index cc5ee90e..9ca384cd 100644
--- a/ai/claude/commands/commit.md
+++ b/ai/claude/commands/commit.md
@@ -10,9 +10,13 @@ Usage:
Before committing:
1. Use the `describing-changes` skill to draft the commit message explaining reasoning
- The skill requires `elements-of-style:writing-clearly-and-concisely` for clarity
-2. Check if a fileset was provided as arguments
-3. If a fileset is provided, use `jj commit <fileset>` to commit only matching files
-4. If no fileset is provided, use `jj commit` to commit all changes
-5. Include the "Assisted-by" footer with the current model and tool being used
-6. Use a HEREDOC for the commit message to ensure proper formatting
-7. Verify the commit with `jj show` to confirm only intended changes were committed
+2. Audit the message: is every sentence invisible in the diff?
+ - For each sentence, ask: "Does this explain something not visible in the code change?"
+ - If the answer is "no" (sentence just restates what the diff shows), delete it
+ - If all sentences pass the audit, proceed. If any fail, rewrite until they do.
+3. Check if a fileset was provided as arguments
+4. If a fileset is provided, use `jj commit <fileset>` to commit only matching files
+5. If no fileset is provided, use `jj commit` to commit all changes
+6. Include the "Assisted-by" footer with the current model and tool being used
+7. Use a HEREDOC for the commit message to ensure proper formatting
+8. Verify the commit with `jj show` to confirm only intended changes were committed
diff --git a/ai/claude/skills/describing-changes/SKILL.md b/ai/claude/skills/describing-changes/SKILL.md
index 888fdb92..de6221be 100644
--- a/ai/claude/skills/describing-changes/SKILL.md
+++ b/ai/claude/skills/describing-changes/SKILL.md
@@ -122,14 +122,26 @@ on comparison avoids data migration and works immediately.
Stop and trim if you catch yourself:
-- Writing more than 3-4 sentences (you're over-explaining)
+- Writing more than 3 sentences - PAUSE and ask: does each sentence explain reasoning not visible in diff?
- Including implementation details visible in the diff
- Explaining what the code does rather than why the change exists
- Justifying the approach as "good" instead of explaining the constraint
- Enumerating multiple alternatives considered (mention only the blocker)
- Adding foundational context readers can find in issue tickets
+- "But this change is complex/important/multi-faceted" → Still 2-3 sentences max. If genuinely complex, it's multiple commits, not one wordy message.
-**Max length:** 50-75 words for most changes. Under 30 words for simple fixes.
+**Length discipline:**
+- Commit messages: typically 2-3 sentences (50-75 words)
+- Simple fixes: Under 30 words
+
+**Before finalizing, audit every sentence:**
+- Is this sentence invisible in the diff? (Yes → keep it, No → delete it)
+- Does this describe implementation visible in the code? (Yes → delete it, No → keep it)
+- Does this just restate what a careful diff reader would already see? (Yes → delete it, No → keep it)
+
+If any sentence fails this audit, remove it. The diff shows WHAT changed. Your message explains WHY (and only if WHY is not obvious from reading the code change itself).
+
+**NEVER rationalize:** "This change is complex so I need to explain the cases" - if all cases are visible in the diff, don't list them. "This change is important so the message should be thorough" - thorough means every word earns its place, not verbose.
## Red Flags - When You're Describing the Change Instead of Explaining It
@@ -199,3 +211,15 @@ Use these to validate your change description:
5. **What does the reader need to understand?** - What context am I providing that isn't in the diff?
If you skip any of these, add more context to your description.
+
+## Footer Requirements
+
+**If AI assisted in crafting the message, include Assisted-by footer:**
+
+```
+Assisted-by: Claude Haiku 4.5 via Claude Code
+```
+
+Format: `Assisted-by: [Model name] via Claude Code`
+
+This is MANDATORY when using this skill. Do NOT omit it.