Skip to content

Commit a76f1c6

Browse files
Adopt Conventional Commits and make the rules binding (#985)
* Adopt Conventional Commits and make the rules binding CONTRIBUTING.md banned Conventional Commits outright. Its load-bearing argument was that nothing here generates from commit types, because release notes were hand-written in CHANGELOG.md. Notes are moving to generated, so that premise goes. Subjects become <type>(<scope>): <description>, keeping the component as the scope. The bans that were right are kept verbatim: ticket IDs, status tags, filenames in subjects. A short note records that the policy changed so it is not re-litigated from older git log entries. Co-Authored-By is now banned explicitly, on any artifact, whoever wrote the change. AGENTS.md states that the rules bind humans and agents equally and that a violating pull request is declined rather than fixed in review. Its inline copy of the prefix rules is gone — a second copy is one that goes stale. CL-7880 * Update the layers that enforce the commit rule, not just the doc Flipping CONTRIBUTING.md alone would have left the repo fighting itself. The style skill — loaded by builder and other agents — banned subject prefixes outright and listed `feat: add retry logic` as a bad example, so agents would keep writing subjects the new rule declines. The review skill would then flag the compliant ones as prefix violations. Updated together: the style skill now specifies the type/scope form and keeps the ticket-ID, status-tag and filename bans; the review skill flags a missing or unrecognized type instead of flagging types themselves; the implement skill and the builder director prompt stop telling workers the title is a plain-English sentence; the PR template matches. CONTRIBUTING.md also states the consequence directly, so the README can point at it rather than making a claim the source of truth does not. CL-7880 * Name the real product in release forms and drop notes commits
1 parent 5eed102 commit a76f1c6

7 files changed

Lines changed: 102 additions & 59 deletions

File tree

‎.github/PULL_REQUEST_TEMPLATE.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Fixes #123
1818
Partial work: Related to CL-1234
1919
No tracker: delete this comment block and leave no magic-word line.
2020
21-
Do not put CL-… or #N in the PR title. Commit subjects stay plain English
22-
with no ticket IDs — see CONTRIBUTING.md.
21+
Do not put CL-… or #N in the PR title. Commit subjects are Conventional
22+
Commits — <type>(<scope>): <description> — with no ticket IDs. See
23+
CONTRIBUTING.md.
2324
-->

‎AGENTS.md‎

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,15 @@ same reason.
6161

6262
## Commits, pull requests, and issue tracking
6363

64-
**MUST follow `CONTRIBUTING.md`.** That file is the source of truth for commit
65-
titles and bodies, PR titles and bodies, and Linear/GitHub linking. Do not use
66-
Conventional Commits prefixes (`feat:`, `fix:`, `docs:`, `ci:`, …), ticket IDs
67-
in commit subjects, or free-form PR body sections. Rewrite before push if a
68-
message violates those rules. Commit with the operator's local git identity.
64+
**MUST follow `CONTRIBUTING.md`.** That file is the single source of truth for
65+
commit titles and bodies, PR titles and bodies, and Linear/GitHub linking. It
66+
is not summarized here on purpose — a second copy of the rules is a copy that
67+
goes stale, and the rules have changed before. Read it.
68+
69+
**This binds humans and agents equally. A pull request that violates
70+
`CONTRIBUTING.md` will be declined** — not fixed in review. Check your commit
71+
subjects against that file before you push, and rewrite them if they do not
72+
match. Commit with the operator's local git identity.
6973

7074
## Pushing
7175

‎CONTRIBUTING.md‎

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -43,56 +43,67 @@ not substitute a bare `bun test` (it also scans
4343

4444
### Title (MUST)
4545

46-
- Imperative, present tense, max **72** characters
47-
- Starts with a verb: `Add`, `Fix`, `Remove`, `Harden`, `Document`, …
48-
- No trailing punctuation, no abbreviations for their own sake
49-
- No filenames or paths in the subject — the diff already lists them
50-
- Match the voice of recent history:
46+
Follow [Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/).
5147

52-
```bash
53-
git log origin/main --format='%s' | head -20
48+
```text
49+
<type>(<scope>): <description>
5450
```
5551

56-
**Banned subject prefixes** (all of them, including habits from other projects):
52+
- **Type** — one of `feat`, `fix`, `perf`, `refactor`, `test`, `docs`, `build`,
53+
`ci`, `chore`, `style`
54+
- **Scope** — the component the change lives in: `feat(executor)`,
55+
`fix(nameref)`, `perf(glob)`, `docs(release)`. Omit it only when a change
56+
genuinely spans the repo
57+
- **Description** — imperative, present tense, lowercase after the colon, no
58+
trailing period. The whole subject line stays within **72** characters
59+
- **Breaking changes** — `!` after the type/scope (`feat(config)!: ...`), or a
60+
`BREAKING CHANGE:` footer in the body
61+
62+
This repo's history used a bare `component: description` prefix (`executor:`,
63+
`nameref:`). New commits keep the component as the **scope** and lead with the
64+
type: `executor: add retry` becomes `feat(executor): add retry`.
65+
66+
Releases use `chore(release): corbits X.Y.Z`. Release notes are generated
67+
from merged pull requests, so there are no hand-written notes commits.
5768

58-
- Conventional Commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`, `ci:`, `perf:`, `style:`, `build:`
59-
- Scoped forms: `docs(changelog):`, `net:`, `frontend:`
60-
- Ticket IDs: `CL-1234:`, `INTR-79:`, `#456:`
69+
**Still banned in the subject:**
70+
71+
- Ticket IDs: `CL-1234:`, `INTR-79:`, `#456:` — linking is a pull-request
72+
concern (see [Issue tracking](#issue-tracking-linear-and-github))
6173
- Status tags: `WIP:`, `[urgent]`, `(security):`
74+
- Filenames and paths — the diff already lists them
75+
- Abbreviations for their own sake
6276

6377
**Good:**
6478

6579
```text
66-
Add retry logic for failed network requests
67-
Fix race condition in transaction verification
68-
Document the permission queue behavior
80+
feat(executor): add retry logic for failed network requests
81+
fix(inference): close race condition in transaction verification
82+
docs(permissions): document the permission queue behavior
83+
perf(glob): stop rescanning ignored directories
6984
```
7085

7186
**Bad:**
7287

7388
```text
74-
feat: add retry logic
75-
fix(auth): race in server.ts
76-
CL-5494: flatten model picker
77-
Update code
89+
add retry logic (no type)
90+
feat: add retry to src/executor.ts (no scope, filename in subject)
91+
fix(auth): CL-5494 race in server.ts (ticket ID, filename)
92+
chore: update code (says nothing)
7893
```
7994

80-
### Why not `feat:` / `fix:` / `docs:` / `ci:`?
81-
82-
Conventional Commits are useful when tools **generate** changelogs, SemVer bumps,
83-
or release notes from commit types. This project does not:
95+
### A note on the previous rule
8496

85-
- Release notes are hand-written in `CHANGELOG.md` and deliberately strip ticket
86-
and PR IDs from public notes.
87-
- Reviewers and `git log` readers need a sentence that stands alone years later,
88-
not a taxonomy debate (`chore` vs `refactor` vs `fix`).
89-
- An imperative subject already encodes the action: `Fix race in the approval
90-
queue` is clearer than `fix: race in the approval queue`.
91-
- Prefixes train agents and humans to smuggle scope, ticket IDs, and file names
92-
into the subject — noise we already reject elsewhere.
97+
This project previously **banned** Conventional Commits and required a plain
98+
imperative subject. That rule rested on the repo generating nothing from commit
99+
types — release notes were hand-written in `CHANGELOG.md`. That is changing:
100+
release notes move to being generated from merged pull requests, so the premise
101+
no longer holds.
93102

94-
The Git and Go projects use the same plain-English model. Familiarity with
95-
Angular-style prefixes is not a reason to adopt them here.
103+
The parts of the old rule that were right are kept: the subject is still an
104+
imperative sentence that stands on its own years later, and the ticket-ID,
105+
status-tag, and filename bans are unchanged. Only the type and scope are new.
106+
Please do not re-open this from reading older `git log` entries.
96107

97108
### Body (usually omit)
98109

@@ -118,9 +129,15 @@ hand, not for the person reviewing this PR today.
118129
- Separate refactors from feature additions
119130
- Separate formatting/whitespace from behavioral changes
120131
- Commit with the operator's local git identity (never invent author metadata)
132+
- **Never** add a `Co-Authored-By` trailer — to a commit, a pull request, a
133+
GitHub issue, or any other artifact. This holds whoever or whatever wrote the
134+
change
121135

122136
## Pull requests
123137

138+
These rules bind humans and agents alike. **A pull request that does not follow
139+
them will be declined** rather than fixed in review.
140+
124141
### Scope (MUST)
125142

126143
1. One concern per PR. See scope discipline in `AGENTS.md`.
@@ -136,9 +153,13 @@ git log origin/main..HEAD --format='%s'
136153

137154
### Title (MUST)
138155

139-
Same rules as [commit titles](#title-must): imperative present-tense sentence,
140-
no prefixes, no ticket IDs, no trailing punctuation. The title describes the
141-
**whole branch**, not a single commit.
156+
Same rules as [commit titles](#title-must): `<type>(<scope>): <description>`,
157+
imperative present tense, no ticket IDs, no trailing punctuation. The title
158+
describes the **whole branch**, not a single commit — pick the type that fits
159+
the branch's main effect.
160+
161+
The pull-request title is what generated release notes quote, so it is read by
162+
people who never see the diff. Write it for them.
142163

143164
### Body (MUST)
144165

‎plugins/corbits-skills/skills/implement/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ Run `make` (or the project's equivalent full pipeline: format, lint, build, test
113113

114114
Update `activeForm` to "Committing: {subject}".
115115

116-
Create the commit. Follow the commit message conventions from the `style` skill. Include the test in the same unit of work as the implementation — same commit when committing — one logical unit — and update the docs when the commit changes documented behavior. Worker-chain branch/PR convention: branch name carries the issue id, the PR body ends with `Fixes CL-…` and carries no AI-attribution lines (CONTRIBUTING: title stays a plain-English sentence, body is Summary/Verification).
116+
Create the commit. Follow the commit message conventions from the `style` skill. Include the test in the same unit of work as the implementation — same commit when committing — one logical unit — and update the docs when the commit changes documented behavior. Worker-chain branch/PR convention: branch name carries the issue id, the PR body ends with `Fixes CL-…` and carries no AI-attribution lines (CONTRIBUTING: title is a Conventional Commits subject, body is Summary/Verification).
117117

118118
### Step 5: Critique Loop
119119

‎plugins/corbits-skills/skills/review/SKILL.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ git log <base>..HEAD --format='%s'
257257

258258
Scan for:
259259

260-
- **Prefix violations.** Any subject starting with a `word:`, `[tag]`, or `(scope)` pattern. Includes Conventional Commits (`feat:`, `fix:`), component or scope prefixes (`Anthropic adapter:`, `mm:`, `[X86]`), ticket IDs (`INTR-79:`), and status tags (`WIP:`). Project convention is plain English sentences; any prefix is a violation regardless of how idiomatic it looks in other ecosystems.
260+
- **Subject-form violations.** Project convention is Conventional Commits: `<type>(<scope>): <description>` with type from `feat`, `fix`, `perf`, `refactor`, `test`, `docs`, `build`, `ci`, `chore`, `style`. Flag a subject with no type (`Anthropic adapter: handle 429s`, `Add retry logic`), an unrecognized type, a ticket ID (`INTR-79:`), or a status tag (`WIP:`, `[urgent]`). Do **not** flag `feat:`/`fix:`-style prefixes themselves — those are the convention.
261261
- **Filename or path references.** Tokens that look like file paths or extensions (`server.ts`, `INFERENCE.md`, `src/foo/bar.py`). The diff lists what changed; subjects describe the change, not the file.
262262
- **Trailing punctuation.** Subjects ending with `.`, `!`, or `?`.
263263
- **Vague subjects.** "Update code," "Fix bug," "Misc changes," "Address review."

‎plugins/corbits-skills/skills/style/SKILL.md‎

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -104,37 +104,54 @@ git log origin/main --format='%s' | head -20
104104

105105
The existing commits document the project's actual subject convention — verb tense, level of detail, voice, capitalization. Match what is there.
106106

107-
The project's log can override the no-prefix rule below, but only when the recent history is **predominantly** prefixed in a single consistent convention — i.e., the prefix is the obvious shape of the last ~20 commits, not a minority pattern visible in a few. Mixed signals fall through to the no-prefix rule; tie goes to no prefix.
107+
**Conventional Commits.** Summary lines follow
108+
[Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/):
108109

109-
**No subject prefixes.** Summary lines are plain English sentences that start with a verb and describe the change directly. Do not prefix the subject with anything — no tag, no scope, no category, no ticket ID, no severity marker. This is a flat rule across every prefix convention, including:
110+
```text
111+
<type>(<scope>): <description>
112+
```
113+
114+
- **Type** — one of `feat`, `fix`, `perf`, `refactor`, `test`, `docs`, `build`,
115+
`ci`, `chore`, `style`
116+
- **Scope** — the component the change lives in. Omit only when the change
117+
genuinely spans the whole project
118+
- **Description** — plain English, imperative, starts with a verb, describes
119+
the change directly
120+
- **Breaking changes** — `!` after the type/scope, or a `BREAKING CHANGE:`
121+
footer
122+
123+
Everything after the colon still obeys the rules below: no abbreviations, no
124+
trailing punctuation, no filenames, self-contained.
125+
126+
**Still banned as subject prefixes**, before or instead of the type:
110127

111-
- Conventional Commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`
112-
- Scope or component prefixes: `Anthropic adapter:`, `mm:`, `[X86]`, `drivers/net:`, `frontend:`
113128
- Ticket IDs: `INTR-79:`, `JIRA-1234:`, `#456:`
114129
- Status or severity tags: `WIP:`, `[urgent]`, `(security):`
115-
116-
Several of these patterns are widespread in well-known projects (Linux kernel, LLVM, Conventional-Commits-adopting projects) and feel idiomatic from sheer exposure. They are still banned here. Familiarity is not a justification.
130+
- Bare component prefixes with no type: `Anthropic adapter:`, `mm:`, `[X86]`,
131+
`drivers/net:`, `frontend:` — the component belongs in the scope, so
132+
`mm: fix leak` becomes `fix(mm): fix leak`
117133

118134
Summary lines also use no abbreviations and do not end with punctuation.
119135

120136
**Good examples:**
121137

122138
```
123-
Add retry logic for failed network requests
124-
Fix race condition in transaction verification
125-
Document API response format
139+
feat(executor): add retry logic for failed network requests
140+
fix(inference): resolve race condition in transaction verification
141+
docs(api): document response format
142+
perf(glob): stop rescanning ignored directories
126143
```
127144

128145
**Bad examples:**
129146

130147
```
131-
feat: add retry logic (Conventional Commits prefix)
132-
Anthropic adapter: handle 429s (component-scope prefix)
148+
Add retry logic (no type or scope)
149+
feat: add retry logic (no scope, and says nothing specific)
150+
Anthropic adapter: handle 429s (bare component, no type)
133151
INTR-79: add retry logic (ticket-ID prefix)
134152
[WIP] refactor the parser (status tag)
135-
Update code (too vague)
136-
Fix bug in server.ts (filename in subject)
137-
Document INFERENCE.md updates (filename in subject)
153+
chore: update code (too vague)
154+
fix: bug in server.ts (filename in subject)
138155
```
139156

140157
**Self-contained:**

‎src/agent/directors/builder/package.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ For implementation work, run the repository-defined typecheck command and releva
8181
8282
**Don't shortcut verify.** The value is in the discipline. Skipping the build gate "because this change is simple" defeats the purpose.
8383
84-
**Keep units focused.** Deliver a working tree that satisfies the brief and report. Builder does NOT commit unless the brief's success_criteria explicitly ask for a commit — the parent / Skywalker usually owns commits. Prefer: working tree + report envelope. Worker-chain branch/PR convention for the parent's handoff: branch name carries the issue id, the PR body ends with \`Fixes CL-…\` and carries no AI-attribution lines (CONTRIBUTING: title stays a plain-English sentence, body is Summary/Verification only).
84+
**Keep units focused.** Deliver a working tree that satisfies the brief and report. Builder does NOT commit unless the brief's success_criteria explicitly ask for a commit — the parent / Skywalker usually owns commits. Prefer: working tree + report envelope. Worker-chain branch/PR convention for the parent's handoff: branch name carries the issue id, the PR body ends with \`Fixes CL-…\` and carries no AI-attribution lines (CONTRIBUTING: title is a Conventional Commits subject, body is Summary/Verification only).
8585
8686
**Discovered extra work** belongs under Blockers / Findings for a future unit — finish the current brief first.
8787

0 commit comments

Comments
 (0)