Context
The eigenoid org had 8 repositories with inconsistent names: some inherited from the original monorepo (SPIRE-A2A-Protocol), others with generic names (actions, settings) that did not communicate their purpose, and others following mutually incompatible patterns:
| Previous name | Problem |
|---|---|
github-org-settings | Legacy name, too long, does not follow convention |
actions | Generic name, ambiguous, collides with GitHub Actions |
iac-org-shared-resources | Inconsistent with the 2-3 word pattern |
public-docs | Inconsistent with the docs- category |
access-block-page | No category prefix |
core / studio | No prefix, but legitimate exception (published packages) |
internal-docs | Correct by accident, not by design |
Without an explicit convention:
- New repos were named ad-hoc with no clear guidance.
- The repo creation issue template did not validate or suggest names.
- safe-settings suborgs could not use predictable glob patterns.
- Onboarding new members required explaining what each repo did on a case-by-case basis.
Decision
We adopt a naming convention based on category prefixes for all repositories in the org:
Format
<category>-<descriptive-name>
- kebab-case required
- Category prefix required (determines suborg)
- Descriptive name concise: 2-3 words max
Categories
| Prefix | Description | Example |
|---|---|---|
iac- | Infrastructure as Code (Terraform) | iac-org-shared |
app- | Deployable applications | app-studio, app-block-page |
docs- | Documentation | docs-internal, docs-external |
platform- | Internal org tooling | platform-settings, platform-actions |
tpl- | Template repos | tpl-iac, tpl-app |
svc- | Microservices | svc-api, svc-auth |
Documented exceptions
.github: GitHub convention for org-level defaults. Not modified.- Published packages: use the package name as the repo name (e.g.,
eigenoidfor the pip package). Rationale: the repo name is the public identifier of the package; renaming it would break PyPI URLs, import statements, and external references.
Renames executed
| Previous name | New name | Category |
|---|---|---|
github-org-settings | platform-settings | platform |
actions | platform-actions | platform |
iac-org-shared-resources | iac-org-shared | iac |
public-docs | docs-external | docs |
internal-docs | docs-internal | docs |
access-block-page | app-block-page | app |
core | eigenoid | exception (package) |
studio | app-studio | app |
Automation
The repo creation issue template ("Request new repository" in platform-settings) now:
- Category selection: dropdown with available categories + an
exceptionoption. - Descriptive name: the user enters only the descriptive part; the prefix is added automatically.
- Validation: the workflow validates kebab-case format, allowed characters, topic length, label format, and duplicate names.
- Automatic suborg: the category determines the safe-settings suborg (e.g., category
app→ suborgapp.yml).
Suborgs as a reflection of categories
Each category with 2 or more repos has a file in .github/suborgs/ with shared configuration (labels, properties). Repos are assigned by glob pattern based on the category prefix:
# .github/suborgs/app.yml
suborgrepos:
- "app-*"
Consequences
- Discoverability: any member can infer a repo's purpose from its name without consulting documentation.
- Predictability: names of new repos are predictable before they are created.
- Reliable globs: suborgs, CODEOWNERS, CI filters, and scripts can use
<category>-*patterns with confidence. - GitHub redirects: the renames depend on GitHub redirects, which work for repos but not for webhooks. The safe-settings
ADMIN_REPOenv var had to be updated manually after thegithub-org-settings→platform-settingsrename. - Rename cost: the renames required updating CI (workflows referencing repos by name), internal documentation, and Cloud Run configuration. The cost was one-time and acceptable.
- Limited exceptions: only 2 documented exceptions (
.githuband published packages). Any new exception requires explicit justification. - Breaking change for bookmarks: old URLs redirect automatically (except for webhooks and hardcoded API calls).
Alternatives considered
- Prefixes only, no rename of existing repos: reduces the risk of breaking changes but leaves the historical inconsistency. Rejected: the naming debt is small (8 repos) and better to pay it now than with 50 repos.
- Categories in topics instead of names: more flexible but less visible. A repo
my-appwith topicappis indistinguishable from a repomy-appwith topicdocsin a repo list. Topics complement, they do not replace the name. - Categories in GitHub custom properties: cleaner than topics but invisible in the main UI. Custom properties are useful for programmatic filters but not for human discoverability.
- No categories, just kebab-case: simple but does not solve the discoverability problem and does not allow predictable globs for suborgs.
References
- ADR-0006 — safe-settings for GitHub governance — safe-settings as source of truth, suborgs
- ADR-0007 — Declarative repo lifecycle governance — issue templates for creation/deletion
- GitHub governance — Operational guide — how to add/remove repos
- Runbook: New repository — step-by-step flow with the convention
eigenoid/platform-settings— admin repo with templates, workflows, and config