M17-1: Multi-repo support #152

Closed
opened 2026-04-20 14:50:17 +00:00 by code-lead · 0 comments
Collaborator

As an operator, I want the webhook to route against a configurable list of repos, so that the same agent fleet serves charles/loom, charles/proxmox-iac, charles/ws-rpc-test alongside charles/claude-hooks without code changes per repo.

Acceptance criteria

Config & validation

  • config/agents.json grows a top-level repos: [...] list (today one implicit entry)
  • loadWebhookConfig validates each repo string as owner/name
  • Audit every occurrence of charles/claude-hooks across src/*.ts — none should remain as a string literal. Parameterise off incoming webhook payload or config list

Label & sweeper iteration

  • labels.ts reconcile iterates every repo at startup, not just one
  • just labels-bootstrap <owner>/<repo> still works ad-hoc for repos outside the list
  • Each repo gets the canonical area:* + type:* labels on first reconcile; new area labels are additive (don't delete labels already present)
  • sweeper.ts iterates every repo's cache clones + worktrees

Webhook dispatch

  • Dispatch routes by payload.repository.full_name against the config list
  • Unknown repo → log + 404, no dispatch
  • breakdown skill respects the out-of-scope rule "no cross-repo" — dispatches against whichever repo the /breakdown call or trigger-comment originates from, matching one of the config's repos

Tests

  • webhook-config.test.ts: config with 3 repos loads, each accessible via loadWebhookConfig().repos
  • labels.test.ts: reconcile applies the canonical set to 3 different repos in one startup pass
  • webhook-handlers.test.ts: webhook from unknown-repo payload is rejected with a 404 log line, no dispatch

Docs

  • README + CLAUDE.md updated with "Adding a repo to the fleet" runbook

Out of scope

  • Per-repo agent pool sizing (e.g. dev-loom-specialist). Pool stays global; routing is on labels not repos.
  • Repo-specific skills — skills stay in one place (skills/) and apply to every dispatch.
  • GitHub or non-Forgejo remotes.

Dependencies

  • Run AFTER #M17-5 / #M17-3 / #M17-2 land (largest story — touches many files, easier to test-drive on a second repo once the smaller ones close). Can parallel with #M17-4.

References

  • Spec: specs/m17-multi-repo-and-observability.md §Story M17-1
  • Milestone 16 close: #47 (tracker)
As an operator, I want the webhook to route against a configurable list of repos, so that the same agent fleet serves `charles/loom`, `charles/proxmox-iac`, `charles/ws-rpc-test` alongside `charles/claude-hooks` without code changes per repo. ## Acceptance criteria ### Config & validation - [ ] `config/agents.json` grows a top-level `repos: [...]` list (today one implicit entry) - [ ] `loadWebhookConfig` validates each repo string as `owner/name` - [ ] Audit every occurrence of `charles/claude-hooks` across `src/*.ts` — none should remain as a string literal. Parameterise off incoming webhook payload or config list ### Label & sweeper iteration - [ ] `labels.ts` reconcile iterates every repo at startup, not just one - [ ] `just labels-bootstrap <owner>/<repo>` still works ad-hoc for repos outside the list - [ ] Each repo gets the canonical `area:*` + `type:*` labels on first reconcile; new area labels are additive (don't delete labels already present) - [ ] `sweeper.ts` iterates every repo's cache clones + worktrees ### Webhook dispatch - [ ] Dispatch routes by `payload.repository.full_name` against the config list - [ ] Unknown repo → log + 404, no dispatch - [ ] `breakdown` skill respects the out-of-scope rule "no cross-repo" — dispatches against whichever repo the `/breakdown` call or trigger-comment originates from, matching one of the config's repos ### Tests - [ ] `webhook-config.test.ts`: config with 3 repos loads, each accessible via `loadWebhookConfig().repos` - [ ] `labels.test.ts`: reconcile applies the canonical set to 3 different repos in one startup pass - [ ] `webhook-handlers.test.ts`: webhook from unknown-repo payload is rejected with a 404 log line, no dispatch ### Docs - [ ] README + CLAUDE.md updated with "Adding a repo to the fleet" runbook ## Out of scope - Per-repo agent pool sizing (e.g. `dev-loom-specialist`). Pool stays global; routing is on labels not repos. - Repo-specific skills — skills stay in one place (`skills/`) and apply to every dispatch. - GitHub or non-Forgejo remotes. ## Dependencies - Run AFTER #M17-5 / #M17-3 / #M17-2 land (largest story — touches many files, easier to test-drive on a second repo once the smaller ones close). Can parallel with #M17-4. ## References - Spec: `specs/m17-multi-repo-and-observability.md` §Story M17-1 - Milestone 16 close: #47 (tracker)
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#152
No description provided.