feat(HAI-078): add configurable task prefix to settings

- Add taskPrefix field to Settings type and use it in allocateId
- Update store listTasks and handleFsChange to support any task prefix
- Update triage duplicate regex to match configurable prefix
- Add Task Prefix input to dashboard SettingsModal UI
- Add tests for prefix-aware task allocation and settings modal
This commit is contained in:
Dustin Byrne
2026-03-26 00:48:38 -04:00
parent 40099be89e
commit 5dea073d22
6 changed files with 143 additions and 10 deletions

View File

@@ -401,6 +401,42 @@ describe("TaskStore", () => {
});
});
// ── Task prefix tests ──────────────────────────────────────────
describe("taskPrefix setting", () => {
it("default prefix produces HAI-001 IDs", async () => {
const task = await store.createTask({ description: "Default prefix" });
expect(task.id).toBe("HAI-001");
});
it("custom prefix produces PROJ-001 IDs", async () => {
await store.updateSettings({ taskPrefix: "PROJ" });
const task = await store.createTask({ description: "Custom prefix" });
expect(task.id).toBe("PROJ-001");
});
it("prefix change mid-stream continues sequence", async () => {
const t1 = await store.createTask({ description: "First" });
const t2 = await store.createTask({ description: "Second" });
expect(t1.id).toBe("HAI-001");
expect(t2.id).toBe("HAI-002");
await store.updateSettings({ taskPrefix: "PROJ" });
const t3 = await store.createTask({ description: "Third" });
expect(t3.id).toBe("PROJ-003");
});
it("listTasks returns tasks regardless of prefix", async () => {
await store.createTask({ description: "HAI task" });
await store.updateSettings({ taskPrefix: "PROJ" });
await store.createTask({ description: "PROJ task" });
const tasks = await store.listTasks();
expect(tasks).toHaveLength(2);
expect(tasks.map((t) => t.id).sort()).toEqual(["HAI-001", "PROJ-002"]);
});
});
describe("agent log persistence", () => {
it("appendAgentLog creates agent.log and getAgentLogs reads it back", async () => {
const task = await createTestTask();