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 — usestatus:needs-triage,status:needs-info,status:ready-for-agent,status:ready-for-human, orstatus:wontfixfor human-readable triage.area:*: recommended, free-formarea:<domain-kebab>if no preset matches.release:*: optional, free-formrelease:<milestone-kebab>.stream:*/scenario:*/agent:*: per repo (seeapplies_toinlabels.yaml).crystal:intake/crystal:backlog/mission:*: optional Dark Factory compatibility metadata. Create these only in a Dark Factory context or with explicit operator intent; do not add them to ordinary issues just to satisfy governance. They are excluded from the default label sync; usesync-labels.py --include-dark-factory-labelsonly for a Dark Factory run.crystal:agent|stage|status|runtime|mission|parent|child:*: EMITTED ONLY by paperclip kernel. Never set manually.
PR titles use strict Conventional Commits:
<type>(<scope>)?: <subject>
Commit subjects use Conventional Commits with a targeted emoji:
<type>(<scope>)?: <emoji> <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: concise, human-readable, no trailing period.
Emoji palette: ✨ feature, 🐛 bug fix, 📝 documentation, ♻️
refactor, ✅ tests, ⬆️ dependency bump, 👷 CI/build, 🔒
security/auth, 🚀 release/deploy, 🧹 cleanup, ⚡ performance.
Footer:
Closes #123/Fixes #123for auto-close.Refs #123for link without close.BREAKING CHANGE: <description>for backwards-incompatible changes (triggers MAJOR bump in SemVer).
Do not add Co-authored-by footers to Crystal commits.
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>where<type>is one offeature,bug,chore,docs,refactor,spike,test.
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.
Branches and PRs are optional delivery structure. Direct main delivery is
allowed for solo work, small trusted changes, documentation, governance
maintenance, local cleanups, or when explicitly requested. Every delivery mode
keeps the same evidence rule: inspect status, preserve unrelated changes, stage
only intended files, use the commit-message format, and report validation.
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 |
crystal-capabilities |
CAP |
crystal-compta |
COMPTA |
crystal-dark-factory-hermes |
HERMES |
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) pushed commit messages follow the Crystal emoji commit format. Historical extra labels are reported but tolerated; delete them only with an explicitsync-labels.py --prunerun.
- 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.
For a Dark Factory run, explicitly add --include-dark-factory-labels to sync
the optional crystal:intake, crystal:backlog, and mission:* labels.
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/)