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

@@ -10,24 +10,24 @@ import path from "node:path";
import os from "node:os";
describe("parseDevClawSessionKey", () => {
it("should parse a standard dev session key", () => {
const result = parseDevClawSessionKey("agent:devclaw:subagent:my-project-dev-mid");
assert.deepStrictEqual(result, { projectName: "my-project", role: "dev" });
it("should parse a standard developer session key", () => {
const result = parseDevClawSessionKey("agent:devclaw:subagent:my-project-developer-medior");
assert.deepStrictEqual(result, { projectName: "my-project", role: "developer" });
});
it("should parse a qa session key", () => {
const result = parseDevClawSessionKey("agent:devclaw:subagent:webapp-qa-mid");
assert.deepStrictEqual(result, { projectName: "webapp", role: "qa" });
it("should parse a tester session key", () => {
const result = parseDevClawSessionKey("agent:devclaw:subagent:webapp-tester-medior");
assert.deepStrictEqual(result, { projectName: "webapp", role: "tester" });
});
it("should handle project names with hyphens", () => {
const result = parseDevClawSessionKey("agent:devclaw:subagent:my-cool-project-dev-junior");
assert.deepStrictEqual(result, { projectName: "my-cool-project", role: "dev" });
const result = parseDevClawSessionKey("agent:devclaw:subagent:my-cool-project-developer-junior");
assert.deepStrictEqual(result, { projectName: "my-cool-project", role: "developer" });
});
it("should handle project names with multiple hyphens and qa role", () => {
const result = parseDevClawSessionKey("agent:devclaw:subagent:a-b-c-d-qa-junior");
assert.deepStrictEqual(result, { projectName: "a-b-c-d", role: "qa" });
it("should handle project names with multiple hyphens and tester role", () => {
const result = parseDevClawSessionKey("agent:devclaw:subagent:a-b-c-d-tester-junior");
assert.deepStrictEqual(result, { projectName: "a-b-c-d", role: "tester" });
});
it("should return null for non-subagent session keys", () => {
@@ -45,14 +45,14 @@ describe("parseDevClawSessionKey", () => {
assert.strictEqual(result, null);
});
it("should parse senior dev level", () => {
const result = parseDevClawSessionKey("agent:devclaw:subagent:devclaw-dev-senior");
assert.deepStrictEqual(result, { projectName: "devclaw", role: "dev" });
it("should parse senior developer level", () => {
const result = parseDevClawSessionKey("agent:devclaw:subagent:devclaw-developer-senior");
assert.deepStrictEqual(result, { projectName: "devclaw", role: "developer" });
});
it("should parse simple project name", () => {
const result = parseDevClawSessionKey("agent:devclaw:subagent:api-dev-junior");
assert.deepStrictEqual(result, { projectName: "api", role: "dev" });
const result = parseDevClawSessionKey("agent:devclaw:subagent:api-developer-junior");
assert.deepStrictEqual(result, { projectName: "api", role: "developer" });
});
});
@@ -61,10 +61,10 @@ describe("loadRoleInstructions", () => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "devclaw-test-"));
const projectDir = path.join(tmpDir, "projects", "roles", "test-project");
await fs.mkdir(projectDir, { recursive: true });
await fs.writeFile(path.join(projectDir, "dev.md"), "# Dev Instructions\nDo the thing.");
await fs.writeFile(path.join(projectDir, "developer.md"), "# Developer Instructions\nDo the thing.");
const result = await loadRoleInstructions(tmpDir, "test-project", "dev");
assert.strictEqual(result, "# Dev Instructions\nDo the thing.");
const result = await loadRoleInstructions(tmpDir, "test-project", "developer");
assert.strictEqual(result, "# Developer Instructions\nDo the thing.");
await fs.rm(tmpDir, { recursive: true });
});
@@ -73,10 +73,10 @@ describe("loadRoleInstructions", () => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "devclaw-test-"));
const defaultDir = path.join(tmpDir, "projects", "roles", "default");
await fs.mkdir(defaultDir, { recursive: true });
await fs.writeFile(path.join(defaultDir, "qa.md"), "# QA Default\nReview carefully.");
await fs.writeFile(path.join(defaultDir, "tester.md"), "# Tester Default\nReview carefully.");
const result = await loadRoleInstructions(tmpDir, "nonexistent-project", "qa");
assert.strictEqual(result, "# QA Default\nReview carefully.");
const result = await loadRoleInstructions(tmpDir, "nonexistent-project", "tester");
assert.strictEqual(result, "# Tester Default\nReview carefully.");
await fs.rm(tmpDir, { recursive: true });
});
@@ -84,7 +84,7 @@ describe("loadRoleInstructions", () => {
it("should return empty string when no instructions exist", async () => {
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "devclaw-test-"));
const result = await loadRoleInstructions(tmpDir, "missing", "dev");
const result = await loadRoleInstructions(tmpDir, "missing", "developer");
assert.strictEqual(result, "");
await fs.rm(tmpDir, { recursive: true });
@@ -96,10 +96,10 @@ describe("loadRoleInstructions", () => {
const defaultDir = path.join(tmpDir, "projects", "roles", "default");
await fs.mkdir(projectDir, { recursive: true });
await fs.mkdir(defaultDir, { recursive: true });
await fs.writeFile(path.join(projectDir, "dev.md"), "Project-specific instructions");
await fs.writeFile(path.join(defaultDir, "dev.md"), "Default instructions");
await fs.writeFile(path.join(projectDir, "developer.md"), "Project-specific instructions");
await fs.writeFile(path.join(defaultDir, "developer.md"), "Default instructions");
const result = await loadRoleInstructions(tmpDir, "my-project", "dev");
const result = await loadRoleInstructions(tmpDir, "my-project", "developer");
assert.strictEqual(result, "Project-specific instructions");
await fs.rm(tmpDir, { recursive: true });