Single source of truth for all Crystal team GitHub conventions:
labels, templates, naming, workflows. Hosted in Malakof/.github,
versioned by semver tags, propagated to target repos via the pin file
.crystal-governance.yaml and crystal-company/builders/sync_repo_surface.py.
Schema: crystal-governance/v1
Version: 1.0.0
See labels.yaml for the full canonical table.
Application rules on every issue/PR:
priority:p*: exactly one, mandatory.type:*: exactly one, mandatory.status:*: optional —status:triageis set by default on intake.area:*: recommended, free-formarea:<domain-kebab>if no preset matches.release:*: optional, free-formrelease:<milestone-kebab>.stream:*/scenario:*/agent:*/crystal:*/mission:*: per repo (seeapplies_toinlabels.yaml).crystal:agent|stage|status|runtime|mission|parent|child:*: EMITTED ONLY by paperclip kernel. Never set manually.
Strict format:
<type>(<scope>)?: <subject>
[<body>]
[<footer>]
Allowed types: feat, fix, docs, style, refactor, perf,
test, build, ci, chore, revert.
Scopes: per repo in scopes.yaml. Optional but
recommended on repos with multiple functional domains.
Subject: imperative present, ≤ 72 chars, no trailing period, lowercase first letter (unless proper noun).
Footer:
Closes #123/Fixes #123for auto-close.Refs #123for link without close.Co-authored-by: Name <email>for co-authorship.BREAKING CHANGE: <description>for backwards-incompatible changes (triggers MAJOR bump in SemVer).
Sign-off: not required unless explicitly requested per repo.
PR: strict Conventional Commits. The enforce-conventions workflow
rejects any non-conforming title.
Issue:
type:epic→ prefix[EPIC] <subject>(the prefix is set in addition to thetype:epiclabel for human visibility).- All other types →
<type>: <subject>(imperative present subject, ≤ 80 chars).
Body: use the provided ISSUE_TEMPLATE (epic, feature, bug,
mission-intake). Required sections: Context, Acceptance criteria,
Out of scope. Optional sections: Validation, Links.
Source of truth: GitHub native sub-issues.
The epic.yml template reminds to create children as native sub-issues
(API: gh api repos/{owner}/{repo}/issues/{n}/sub_issues). The dark
factory ingests them via the same API.
No mirror Markdown checklist: a child is a real sub-issue,
not a - [ ] line in the body.
| Pattern | Use |
|---|---|
<author>/<topic-kebab> |
Human work branch (e.g. richard/refactor-auth). |
<agent>/<topic-kebab> |
AI agent branch (e.g. codex/openhands-phase-4-parity, claude/spec-review). |
feature/<topic-kebab> |
Long-running feature branch. |
fix/<topic-kebab> |
Short fix. |
chore/<topic-kebab> |
Maintenance. |
release/v<X>.<Y>.<Z> |
Release cut. |
hotfix/v<X>.<Y>.<Z>-<topic> |
Post-release fix. |
Constraints: kebab-case, ≤ 60 chars total, no double separators,
no spaces. Default branch remains main.
Strict SemVer: vMAJOR.MINOR.PATCH. Pre-releases:
v<X>.<Y>.<Z>-rc.<N>, v<X>.<Y>.<Z>-beta.<N>, v<X>.<Y>.<Z>-alpha.<N>.
Bumps:
BREAKING CHANGEorfeat!:→ MAJORfeat:→ MINORfix:,perf:,refactor:→ PATCHchore:,docs:,test:,ci:,build:,style:→ no bump (unless explicit maintainer decision).
- Changelog: Keep-A-Changelog format.
- Release notes: auto-generated from Conventional Commits (workflow
release-notes.yml— provided in V2). - Tag → Release: every SemVer tag publishes a GitHub release.
- Pre-release: tag with
-rc.N/-beta.Npublishes a release markedprerelease: true.
Format: <REPO_PREFIX>-<TYPE>-<NUM>
| Repo | Prefix |
|---|---|
crystal-assistant-ui-poc |
PAUI |
crystal-dark-factory-poc |
DFP |
crystal-dark-factory-target-lab |
DFL |
crystal-discord-bot |
BEACON (historical codename) |
crystal-specs |
SPEC |
crystal-company |
COMP |
Types: FEAT, BUG, SPIKE, DOC, MIGR, OPS.
Num: 3-digit zero-padded, allocated sequentially per repo.
Examples: PAUI-FEAT-001, DFP-BUG-014, BEACON-SPIKE-003.
Reserved (no duplicates, additions via ADR):
| Codename | Domain |
|---|---|
atlas |
Operator contracts (Stream A) |
beacon |
Discord brain migration (Stream C) |
forge |
Durable spine + abstractions (Stream B) |
compass |
Cost ledger + onboarding (Stream D) |
Any new codename must be validated by ADR before use in branches/labels.
| Pattern | Tool |
|---|---|
/private/tmp/<codename>-<release> |
Ephemeral agent branches during a pilot. |
~/.codex/worktrees/<codename> |
Persistent Codex worktrees. |
.claude/worktrees/<codename> |
Claude worktrees (repo-local). |
prepare → spec-contract → implement → review → ship
Projected automatically as crystal:stage:* labels. Never set manually.
| Type | Path | Filename format |
|---|---|---|
| ADR | docs/adr/ |
NNNN-title-kebab.md (4 digits) |
| PRD | docs/prd/ |
NNNN-title-kebab.md (4 digits) |
ADR statuses: proposed | accepted | superseded | deprecated.
| Pattern | Example |
|---|---|
<verb>-<object>.yml |
enforce-conventions.yml, publish-release.yml, sync-labels.yml |
| Reusable workflows | hosted in Malakof/.github/.github/workflows/, called via uses: Malakof/.github/.github/workflows/<name>.yml@v<X.Y.Z> |
Concurrency: concurrency: { group: <verb>-<object>-${{ github.ref }}, cancel-in-progress: true } recommended.
Format: CRYSTAL_<DOMAIN>_<PURPOSE> (uppercase, underscores).
| Example | Use |
|---|---|
CRYSTAL_DISCORD_BOT_TOKEN |
Beacon Discord token. |
CRYSTAL_GITHUB_PAT |
PAT for cross-repo sync. |
CRYSTAL_OPENAI_API_KEY |
OpenAI key. |
CRYSTAL_ANTHROPIC_API_KEY |
Anthropic key. |
CRYSTAL_OPS_VPS_SSH |
VPS ops SSH key. |
Env vars: same rule, same prefixes.
Pattern: crystal-<scope>-<purpose> (kebab-case).
| Example | OK |
|---|---|
crystal-discord-bot |
✓ |
crystal-assistant-ui-poc |
✓ |
crystal-dark-factory-poc |
✓ |
polaris-scratch-20260416T230130Z |
✗ (legacy, archive after 30d) |
Visibility: private by default. Public only after explicit security/secrets review.
Archival: scratch and *-test repos archived after 30 days of
inactivity.
-
Source:
Malakof/.githubrepo, editable onmain. -
Releases: SemVer tags
vMAJOR.MINOR.PATCHon this governance.- Major: breaking change in labels/templates (label removal without alias, namespace change).
- Minor: addition of label/template/skill, non-breaking change.
- Patch: doc, descriptions, colors.
-
Per-repo pin: each Crystal repo carries
.crystal-governance.yamlpinning a version:schema: crystal-governance-pin/v1 governance_version: v1.0.0 source: Malakof/.github
-
Auto bump-PR: on every
Malakof/.githubrelease, theon-release-bump.ymlworkflow opens achore: bump governance to vX.Y.ZPR on each Crystal repo pinning an older version. -
governance-check CI: reusable workflow called from each repo to verify (a)
governance_versionexists in.github, (b) labels are in sync, (c) templates are not overridden locally.
- Add
.crystal-governance.yaml(pin the latest stable version). - Add
.github/workflows/governance-check.ymlcalling the reusable. - Run
gh workflow run governance-check.ymlto validate. - Run
python scripts/sync-labels.py --repo <owner>/<repo>fromMalakof/.githubto apply the canonical taxonomy.
labels.yaml— canonical label tablescopes.yaml— Conventional Commits scopes per repo.github/ISSUE_TEMPLATE/— issue templates.github/PULL_REQUEST_TEMPLATE.md— PR template.github/workflows/enforce-conventions.yml— title/labels validation (deterministic).github/workflows/governance-check.yml— pin + skills check.github/workflows/format-check.yml— LLM-driven validation via GitHub Models (gpt-4o-mini), posts sticky comment with findingsskills/crystal-github-conventions/SKILL.md— AI agents skill (universal Claude + Codex format, propagated to.claude/skills/and.agents/skills/)