refactor: migrate role handling from tiers to roles module

- Removed the deprecated tiers.ts file and migrated all related functionality to roles/index.js.
- Updated tests and tools to reflect the new role structure, replacing references to "dev", "qa", and "architect" with "developer", "tester", and "architect".
- Adjusted workflow configurations and state management to accommodate the new role naming conventions.
- Enhanced project registration and health check tools to support dynamic role handling.
- Updated task creation, update, and completion processes to align with the new role definitions.
- Improved documentation and comments to clarify role responsibilities and usage.
This commit is contained in:
Lauren ten Hoor
2026-02-15 18:32:10 +08:00
parent 6a99752e5f
commit 0e24a68882
44 changed files with 1162 additions and 762 deletions

View File

@@ -1,8 +1,13 @@
/**
* Model selection for dev/qa tasks.
* Keyword heuristic fallback — used when the orchestrator doesn't specify a level.
* Returns plain level names (junior, mid, senior).
* Model selection heuristic fallback — used when the orchestrator doesn't specify a level.
* Returns plain level names (junior, medior, senior).
*
* Adapts to any role's level count:
* - 1 level: always returns that level
* - 2 levels: simple binary (complex → last, else first)
* - 3+ levels: full heuristic (simple → first, complex → last, default → middle)
*/
import { getLevelsForRole, getDefaultLevel } from "./roles/index.js";
export type LevelSelection = {
level: string;
@@ -39,60 +44,59 @@ const COMPLEX_KEYWORDS = [
];
/**
* Select appropriate developer level based on task description.
* Select appropriate level based on task description and role.
*
* All roles use consistent levels:
* - junior: simple tasks (typos, single-file fixes, CSS tweaks)
* - mid: standard work (features, bug fixes, multi-file changes)
* - senior: deep/architectural (system-wide refactoring, novel design)
* Adapts to the role's available levels:
* - Roles with 1 level → always that level
* - Roles with 2 levels → binary: complex keywords → highest, else lowest
* - Roles with 3+ levels → full heuristic: simple → lowest, complex → highest, else default
*/
export function selectLevel(
issueTitle: string,
issueDescription: string,
role: "dev" | "qa" | "architect",
role: string,
): LevelSelection {
if (role === "qa") {
return {
level: "mid",
reason: "Default QA level for code inspection and validation",
};
}
const levels = getLevelsForRole(role);
const defaultLvl = getDefaultLevel(role);
if (role === "architect") {
const text = `${issueTitle} ${issueDescription}`.toLowerCase();
const isComplex = COMPLEX_KEYWORDS.some((kw) => text.includes(kw));
return {
level: isComplex ? "senior" : "junior",
reason: isComplex
? "Complex design task — using senior for depth"
: "Standard design task — using junior",
};
// Roles with only 1 level — always return it
if (levels.length <= 1) {
const level = levels[0] ?? defaultLvl ?? "medior";
return { level, reason: `Only level for ${role}` };
}
const text = `${issueTitle} ${issueDescription}`.toLowerCase();
const wordCount = text.split(/\s+/).length;
// Check for simple task indicators
const isSimple = SIMPLE_KEYWORDS.some((kw) => text.includes(kw));
const isComplex = COMPLEX_KEYWORDS.some((kw) => text.includes(kw));
const lowest = levels[0];
const highest = levels[levels.length - 1];
// Roles with 2 levels — binary decision
if (levels.length === 2) {
if (isComplex) {
return { level: highest, reason: `Complex task — using ${highest}` };
}
return { level: lowest, reason: `Standard task — using ${lowest}` };
}
// Roles with 3+ levels — full heuristic
if (isSimple && wordCount < 100) {
return {
level: "junior",
level: lowest,
reason: `Simple task detected (keywords: ${SIMPLE_KEYWORDS.filter((kw) => text.includes(kw)).join(", ")})`,
};
}
// Check for complex task indicators
const isComplex = COMPLEX_KEYWORDS.some((kw) => text.includes(kw));
if (isComplex || wordCount > 500) {
return {
level: "senior",
level: highest,
reason: `Complex task detected (${isComplex ? "keywords: " + COMPLEX_KEYWORDS.filter((kw) => text.includes(kw)).join(", ") : "long description"})`,
};
}
// Default: mid for standard dev work
return {
level: "mid",
reason: "Standard dev task — multi-file changes, features, bug fixes",
};
// Default level for the role
const level = defaultLvl ?? levels[Math.floor(levels.length / 2)];
return { level, reason: `Standard ${role} task` };
}