Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Fixes #123
Partial work: Related to CL-1234
No tracker: delete this comment block and leave no magic-word line.

Do not put CL-… or #N in the PR title. Commit subjects stay plain English
with no ticket IDs — see CONTRIBUTING.md.
Do not put CL-… or #N in the PR title. Commit subjects are Conventional
Commits — <type>(<scope>): <description> — with no ticket IDs. See
CONTRIBUTING.md.
-->
14 changes: 9 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,15 @@ same reason.

## Commits, pull requests, and issue tracking

**MUST follow `CONTRIBUTING.md`.** That file is the source of truth for commit
titles and bodies, PR titles and bodies, and Linear/GitHub linking. Do not use
Conventional Commits prefixes (`feat:`, `fix:`, `docs:`, `ci:`, …), ticket IDs
in commit subjects, or free-form PR body sections. Rewrite before push if a
message violates those rules. Commit with the operator's local git identity.
**MUST follow `CONTRIBUTING.md`.** That file is the single source of truth for
commit titles and bodies, PR titles and bodies, and Linear/GitHub linking. It
is not summarized here on purpose — a second copy of the rules is a copy that
goes stale, and the rules have changed before. Read it.

**This binds humans and agents equally. A pull request that violates
`CONTRIBUTING.md` will be declined** — not fixed in review. Check your commit
subjects against that file before you push, and rewrite them if they do not
match. Commit with the operator's local git identity.

## Pushing

Expand Down
91 changes: 56 additions & 35 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,56 +43,67 @@ not substitute a bare `bun test` (it also scans

### Title (MUST)

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

```bash
git log origin/main --format='%s' | head -20
```text
<type>(<scope>): <description>
```

**Banned subject prefixes** (all of them, including habits from other projects):
- **Type** — one of `feat`, `fix`, `perf`, `refactor`, `test`, `docs`, `build`,
`ci`, `chore`, `style`
- **Scope** — the component the change lives in: `feat(executor)`,
`fix(nameref)`, `perf(glob)`, `docs(release)`. Omit it only when a change
genuinely spans the repo
- **Description** — imperative, present tense, lowercase after the colon, no
trailing period. The whole subject line stays within **72** characters
- **Breaking changes** — `!` after the type/scope (`feat(config)!: ...`), or a
`BREAKING CHANGE:` footer in the body

This repo's history used a bare `component: description` prefix (`executor:`,
`nameref:`). New commits keep the component as the **scope** and lead with the
type: `executor: add retry` becomes `feat(executor): add retry`.

Releases use `chore(release): corbits X.Y.Z`. Release notes are generated
from merged pull requests, so there are no hand-written notes commits.

- Conventional Commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`, `ci:`, `perf:`, `style:`, `build:`
- Scoped forms: `docs(changelog):`, `net:`, `frontend:`
- Ticket IDs: `CL-1234:`, `INTR-79:`, `#456:`
**Still banned in the subject:**

- Ticket IDs: `CL-1234:`, `INTR-79:`, `#456:` — linking is a pull-request
concern (see [Issue tracking](#issue-tracking-linear-and-github))
- Status tags: `WIP:`, `[urgent]`, `(security):`
- Filenames and paths — the diff already lists them
- Abbreviations for their own sake

**Good:**

```text
Add retry logic for failed network requests
Fix race condition in transaction verification
Document the permission queue behavior
feat(executor): add retry logic for failed network requests
fix(inference): close race condition in transaction verification
docs(permissions): document the permission queue behavior
perf(glob): stop rescanning ignored directories
```

**Bad:**

```text
feat: add retry logic
fix(auth): race in server.ts
CL-5494: flatten model picker
Update code
add retry logic (no type)
feat: add retry to src/executor.ts (no scope, filename in subject)
fix(auth): CL-5494 race in server.ts (ticket ID, filename)
chore: update code (says nothing)
```

### Why not `feat:` / `fix:` / `docs:` / `ci:`?

Conventional Commits are useful when tools **generate** changelogs, SemVer bumps,
or release notes from commit types. This project does not:
### A note on the previous rule

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

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

### Body (usually omit)

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

## Pull requests

These rules bind humans and agents alike. **A pull request that does not follow
them will be declined** rather than fixed in review.

### Scope (MUST)

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

### Title (MUST)

Same rules as [commit titles](#title-must): imperative present-tense sentence,
no prefixes, no ticket IDs, no trailing punctuation. The title describes the
**whole branch**, not a single commit.
Same rules as [commit titles](#title-must): `<type>(<scope>): <description>`,
imperative present tense, no ticket IDs, no trailing punctuation. The title
describes the **whole branch**, not a single commit — pick the type that fits
the branch's main effect.

The pull-request title is what generated release notes quote, so it is read by
people who never see the diff. Write it for them.

### Body (MUST)

Expand Down
2 changes: 1 addition & 1 deletion plugins/corbits-skills/skills/implement/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ Run `make` (or the project's equivalent full pipeline: format, lint, build, test

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

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

### Step 5: Critique Loop

Expand Down
2 changes: 1 addition & 1 deletion plugins/corbits-skills/skills/review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ git log <base>..HEAD --format='%s'

Scan for:

- **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.
- **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.
- **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.
- **Trailing punctuation.** Subjects ending with `.`, `!`, or `?`.
- **Vague subjects.** "Update code," "Fix bug," "Misc changes," "Address review."
Expand Down
45 changes: 31 additions & 14 deletions plugins/corbits-skills/skills/style/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,37 +104,54 @@ git log origin/main --format='%s' | head -20

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

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.
**Conventional Commits.** Summary lines follow
[Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/):

**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:
```text
<type>(<scope>): <description>
```

- **Type** — one of `feat`, `fix`, `perf`, `refactor`, `test`, `docs`, `build`,
`ci`, `chore`, `style`
- **Scope** — the component the change lives in. Omit only when the change
genuinely spans the whole project
- **Description** — plain English, imperative, starts with a verb, describes
the change directly
- **Breaking changes** — `!` after the type/scope, or a `BREAKING CHANGE:`
footer

Everything after the colon still obeys the rules below: no abbreviations, no
trailing punctuation, no filenames, self-contained.

**Still banned as subject prefixes**, before or instead of the type:

- Conventional Commits: `feat:`, `fix:`, `chore:`, `docs:`, `refactor:`, `test:`
- Scope or component prefixes: `Anthropic adapter:`, `mm:`, `[X86]`, `drivers/net:`, `frontend:`
- Ticket IDs: `INTR-79:`, `JIRA-1234:`, `#456:`
- Status or severity tags: `WIP:`, `[urgent]`, `(security):`

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.
- Bare component prefixes with no type: `Anthropic adapter:`, `mm:`, `[X86]`,
`drivers/net:`, `frontend:` — the component belongs in the scope, so
`mm: fix leak` becomes `fix(mm): fix leak`

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

**Good examples:**

```
Add retry logic for failed network requests
Fix race condition in transaction verification
Document API response format
feat(executor): add retry logic for failed network requests
fix(inference): resolve race condition in transaction verification
docs(api): document response format
perf(glob): stop rescanning ignored directories
```

**Bad examples:**

```
feat: add retry logic (Conventional Commits prefix)
Anthropic adapter: handle 429s (component-scope prefix)
Add retry logic (no type or scope)
feat: add retry logic (no scope, and says nothing specific)
Anthropic adapter: handle 429s (bare component, no type)
INTR-79: add retry logic (ticket-ID prefix)
[WIP] refactor the parser (status tag)
Update code (too vague)
Fix bug in server.ts (filename in subject)
Document INFERENCE.md updates (filename in subject)
chore: update code (too vague)
fix: bug in server.ts (filename in subject)
```

**Self-contained:**
Expand Down
2 changes: 1 addition & 1 deletion src/agent/directors/builder/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ For implementation work, run the repository-defined typecheck command and releva

**Don't shortcut verify.** The value is in the discipline. Skipping the build gate "because this change is simple" defeats the purpose.

**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).
**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).

**Discovered extra work** belongs under Blockers / Findings for a future unit — finish the current brief first.

Expand Down
Loading