Repo bootstrap: auto-provision label set at service startup / on new repo connection #97
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks#97
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
User story
As the operator, I want the routing labels (
area:design,area:design-review, the type labels, etc.) to be present on every repo the webhook points at, without having to create each one through the Forgejo UI — so that a fresh repo connected to claude-hooks just works.What happens today
Each repo the service processes must have the routing labels created by hand before certain flows work. Concrete examples from today:
area:design-review(id 87 on claude-hooks) — didn't exist when PR #86 merged. Designer added it to #70 →add_issue_labelssilently no-op'd at the server level (label didn't resolve). Design-reviewer never fired. Hit live on #70 at 20:08 UTC; had tocurlthe Forgejo API to create the label manually. PR #86 explicitly flagged this setup step but didn't automate it.area:design(id 86) — created by hand during #56 rollout for the same reason.area:*andtype:*label in~/.claude/CLAUDE.md's label scheme — operator docs say "set up labels and a milestone before creating issues", which is fine for a person but not for an auto-connected repo.Proposed shape
Pick one of:
A — on service startup, reconcile labels for every repo in
config/agents.jsonStartup reads a canonical label list (lives in
config/labels.jsonor baked into TS), iterates every repo the service watches, calls the Forgejocreate_labelAPI for missing names with the right color + description. Idempotent; operator's "connect a new repo to claude-hooks" flow becomes "add the repo + rebuild".B — on
repository.createdorrepository.connectedwebhookReact to the webhook Forgejo fires when a repo is added. Same reconcile logic, but event-driven. Narrower but more precise than A.
C —
just labels-bootstrap <repo>recipeOperator-triggered. Low effort, explicit. Matches today's
just containers-rebuildergonomics.Recommend A + C: auto-reconcile at startup for the always-on case, plus the manual recipe for ad-hoc repos that aren't in
agents.json. B is nice-to-have; not worth the webhook wiring yet.Canonical label set (reference)
From global CLAUDE.md + this repo's current labels:
area:agents#0ea5e9area:dashboard#8b5cf6area:design#ec4899area:design-review#be185darea:infra#16a34aarea:meta#6b7280area:sessions#2563ebarea:webhook#06b6d4area:workdir#ea580ctype:user-story#ec4899type:meta#374151type:bugtype:choreThe area:* set is repo-specific; the type:* set is repo-agnostic. Bootstrap should probably split these into two lists.
Acceptance criteria
Core
config/labels.json(or equivalent) defines the canonical labels as{name, color, description, scope: "area" | "type"}.src/labels.tsexposesreconcileLabels(repo)thatPOST /api/v1/repos/{repo}/labelsfor any missing name and leaves existing labels alone (no color / description overwrites — idempotent).main.tsstartup callsreconcileLabelsfor every repo the service's webhook config knows about.just labels-bootstrap <repo>recipe wraps the same call for ad-hoc use.Safety
[labels] created area:design-review on charles/claude-hooks (id=87)on create,[labels] already present: area:designon skip.Tests
labels.test.ts: reconcile on a stubbed repo with partial label set adds the missing ones and skips existing ones.labels.test.ts: reconcile tolerates 404 / 403 from the API.Docs
CLAUDE.mdgains a short "Bootstrap labels on a new repo" section replacing the current "for new repos, set up labels and a milestone" line in the global CLAUDE.md.Out of scope
charles/*repos; org-wide reconcile can wait until the service watches >1 org.References
area:design-reviewlabel dependency.config/agents.json— where the repo list lives today (implicitly, via tokens).Dependencies
main.