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)
76 lines
1.9 KiB
TypeScript
76 lines
1.9 KiB
TypeScript
/**
|
|
* 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 },
|
|
},
|
|
};
|