refactor: Centralize role types and configuration (#190)
Creates a single source of truth for all worker roles via lib/roles/.
## New: lib/roles/
- **registry.ts** — All role definitions (dev, qa, architect) with
levels, models, emoji, completion results, session key patterns
- **types.ts** — RoleConfig interface
- **selectors.ts** — Query helpers: getRole(), getLevelsForRole(),
resolveModel(), isValidResult(), roleForLevel(), etc.
- **index.ts** — Barrel exports
## Migrated Files
- **lib/tiers.ts** — Now delegates to registry (backward compat kept)
- **lib/dispatch.ts** — Uses registry for emoji resolution
- **lib/bootstrap-hook.ts** — Uses registry for session key pattern
- **lib/services/tick.ts** — Uses registry for level detection
- **lib/services/heartbeat.ts** — Uses registry for role iteration
- **lib/tools/health.ts** — Uses registry for role iteration
- **lib/tools/work-start.ts** — Uses registry for role enum
- **lib/tools/work-finish.ts** — Uses registry for result validation
- **lib/tools/project-register.ts** — Uses registry for level lists
## Key Benefits
- Adding a new role = add entry to registry.ts (single file)
- No more scattered role unions ("dev" | "qa" | "architect")
- Type-safe role/level/result validation from registry
- Session key pattern auto-generated from registry
- All 64 tests passing (22 new registry tests + 42 existing)
This commit is contained in:
75
lib/roles/registry.ts
Normal file
75
lib/roles/registry.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* roles/registry.ts — Single source of truth for all worker roles.
|
||||
*
|
||||
* Adding a new role? Just add an entry here. Everything else derives from this.
|
||||
*
|
||||
* Each role defines:
|
||||
* - Identity (id, displayName)
|
||||
* - Levels and models
|
||||
* - Emoji for announcements
|
||||
* - Valid completion results
|
||||
* - Session key matching
|
||||
* - Notification preferences
|
||||
*/
|
||||
import type { RoleConfig } from "./types.js";
|
||||
|
||||
export const ROLE_REGISTRY: Record<string, RoleConfig> = {
|
||||
dev: {
|
||||
id: "dev",
|
||||
displayName: "DEV",
|
||||
levels: ["junior", "medior", "senior"],
|
||||
defaultLevel: "medior",
|
||||
models: {
|
||||
junior: "anthropic/claude-haiku-4-5",
|
||||
medior: "anthropic/claude-sonnet-4-5",
|
||||
senior: "anthropic/claude-opus-4-5",
|
||||
},
|
||||
emoji: {
|
||||
junior: "⚡",
|
||||
medior: "🔧",
|
||||
senior: "🧠",
|
||||
},
|
||||
fallbackEmoji: "🔧",
|
||||
completionResults: ["done", "blocked"],
|
||||
sessionKeyPattern: "dev",
|
||||
notifications: { onStart: true, onComplete: true },
|
||||
},
|
||||
|
||||
qa: {
|
||||
id: "qa",
|
||||
displayName: "QA",
|
||||
levels: ["reviewer", "tester"],
|
||||
defaultLevel: "reviewer",
|
||||
models: {
|
||||
reviewer: "anthropic/claude-sonnet-4-5",
|
||||
tester: "anthropic/claude-haiku-4-5",
|
||||
},
|
||||
emoji: {
|
||||
reviewer: "🔍",
|
||||
tester: "👀",
|
||||
},
|
||||
fallbackEmoji: "🔍",
|
||||
completionResults: ["pass", "fail", "refine", "blocked"],
|
||||
sessionKeyPattern: "qa",
|
||||
notifications: { onStart: true, onComplete: true },
|
||||
},
|
||||
|
||||
architect: {
|
||||
id: "architect",
|
||||
displayName: "ARCHITECT",
|
||||
levels: ["opus", "sonnet"],
|
||||
defaultLevel: "sonnet",
|
||||
models: {
|
||||
opus: "anthropic/claude-opus-4-5",
|
||||
sonnet: "anthropic/claude-sonnet-4-5",
|
||||
},
|
||||
emoji: {
|
||||
opus: "🏗️",
|
||||
sonnet: "📐",
|
||||
},
|
||||
fallbackEmoji: "🏗️",
|
||||
completionResults: ["done", "blocked"],
|
||||
sessionKeyPattern: "architect",
|
||||
notifications: { onStart: true, onComplete: true },
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user