fix(ci): align tests/docs with issue-fix commits (recoveryRehome args, pi-ai mock Unknown/Record, new agent tools doc, hex-pattern comment reword)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,11 @@ These tools are **not** part of the user-invokable extension surface. They are i
|
||||
| `fn_task_document_read` | triage, executor, heartbeat | Read one task document or list all | `key?` (string) |
|
||||
| `fn_workflow_list` | executor | List the project's custom workflows (read-only built-ins plus user definitions) | none |
|
||||
| `fn_workflow_select` | executor | Assign a custom workflow to a task (defaults to the current task) | `workflow_id` (string), `task_id?` (string) |
|
||||
| `fn_workflow_create` | executor | Create a custom workflow definition from a graph IR (validated server-side) | `name` (string), `description?` (string), `ir` (object), `layout?` (object) |
|
||||
| `fn_workflow_update` | executor | Update a custom workflow definition's name/description/ir/layout (built-ins cannot be edited) | `workflow_id` (string), `name?` (string), `description?` (string), `ir?` (object), `layout?` (object), `rehome_to?` (string) |
|
||||
| `fn_workflow_delete` | executor | Delete a custom workflow definition (built-ins cannot be deleted); selecting tasks are re-homed to the default workflow's entry column | `workflow_id` (string) |
|
||||
| `fn_task_promote` | executor | Promote a held task out of a manual-release hold column (defaults to the current task) | `task_id?` (string) |
|
||||
| `fn_trait_list` | executor | List the registered column trait catalog (built-in and plugin traits) | none |
|
||||
| `fn_memory_search` | triage, executor, heartbeat | Search project memory plus per-agent layered memory snippets | `query` (string), `limit?` (number) |
|
||||
| `fn_memory_get` | triage, executor, heartbeat | Read a bounded memory file window (including bounded per-agent layered paths) | `path` (string), `startLine?` (number), `lineCount?` (number) |
|
||||
| `fn_memory_append` | executor, heartbeat (when writable backend enabled) | Append memory notes with explicit scope: `scope="agent"` for private operating context, `scope="project"` for workspace-wide durable knowledge | `scope?` (`project` \| `agent`), `layer` (`long-term` \| `daily`), `content` (string) |
|
||||
|
||||
@@ -144,7 +144,7 @@ function isAgentCreatedTask(task: Task): boolean {
|
||||
|
||||
// ── Constants ───────────────────────────────────────────────────────────────
|
||||
|
||||
// #1403: widened to ColumnId so `.has(task.column)` accepts custom column ids
|
||||
// Issue 1403: widened to ColumnId so `.has(task.column)` accepts custom column ids
|
||||
// (which are not members and correctly resolve to false).
|
||||
const EDITABLE_COLUMNS: Set<ColumnId> = new Set<ColumnId>(["triage", "todo"]);
|
||||
|
||||
@@ -2004,7 +2004,7 @@ function TaskCardComponent({
|
||||
className="card-progress-fill"
|
||||
style={{
|
||||
width: `${progressPercent}%`,
|
||||
// #1403: custom columns have no legacy progress color → fall back to accent.
|
||||
// Issue 1403: custom columns have no legacy progress color → fall back to accent.
|
||||
backgroundColor:
|
||||
(COLUMN_PROGRESS_COLOR_MAP as Record<string, string>)[task.column] ?? "var(--accent)",
|
||||
}}
|
||||
|
||||
@@ -10,6 +10,12 @@ vi.mock("@earendil-works/pi-ai", () => ({
|
||||
Array: (schema: unknown, opts?: unknown) => ({ type: "array", items: schema, ...((opts as object) ?? {}) }),
|
||||
Union: (schemas: unknown[], opts?: unknown) => ({ anyOf: schemas, ...((opts as object) ?? {}) }),
|
||||
Literal: (value: unknown) => ({ const: value }),
|
||||
Unknown: (opts?: unknown) => ({ ...((opts as object) ?? {}) }),
|
||||
Record: (_key: unknown, value: unknown, opts?: unknown) => ({
|
||||
type: "object",
|
||||
additionalProperties: value,
|
||||
...((opts as object) ?? {}),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ describe("reliability interactions: executor no-fn_task_done vs worktree reclaim
|
||||
branch: null,
|
||||
worktreeSessionRetryCount: 1,
|
||||
}));
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4601", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4601", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
// FN-4806: session-start missing-worktree is engine self-heal, must not burn retry budget
|
||||
// and must not mark the task failed.
|
||||
expect(store.updateTask).not.toHaveBeenCalledWith(
|
||||
|
||||
@@ -82,7 +82,7 @@ describe("FN-5219 reliability interactions: in-progress limbo recovery", () => {
|
||||
|
||||
expect(first).toBe(1);
|
||||
expect(second).toBe(0);
|
||||
expect(mockStore.moveTask).toHaveBeenCalledWith("FN-5149", "todo", { preserveProgress: true });
|
||||
expect(mockStore.moveTask).toHaveBeenCalledWith("FN-5149", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
expect(mockStore.recordRunAuditEvent).toHaveBeenCalledWith(expect.objectContaining({
|
||||
mutationType: "task:auto-recover-in-progress-limbo",
|
||||
target: "FN-5149",
|
||||
|
||||
@@ -87,8 +87,7 @@ describe("reliability interactions: FN-4917 worktree incomplete session-start",
|
||||
}),
|
||||
}));
|
||||
|
||||
expect(store.moveTask.mock.calls).toContainEqual(["FN-4917-T", "todo"]);
|
||||
expect(store.moveTask.mock.calls.some((call: any[]) => call.length > 2)).toBe(false);
|
||||
expect(store.moveTask.mock.calls).toContainEqual(["FN-4917-T", "todo", { moveSource: "engine", recoveryRehome: true }]);
|
||||
for (const call of store.logEntry.mock.calls) {
|
||||
const leaked = call.some((arg: unknown) => typeof arg === "string" && /Refusing to start coding agent/.test(arg));
|
||||
expect(leaked).toBe(false);
|
||||
@@ -113,7 +112,7 @@ describe("reliability interactions: FN-4917 worktree incomplete session-start",
|
||||
|
||||
await runRecovery(store, task, "Refusing to start coding agent in incomplete worktree: /tmp/wt", events);
|
||||
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4917-T", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4917-T", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
expect(store.moveTask.mock.calls).not.toContainEqual(["FN-4917-T", "todo"]);
|
||||
for (const call of store.logEntry.mock.calls) {
|
||||
const leaked = call.some((arg: unknown) => typeof arg === "string" && /Refusing to start coding agent/.test(arg));
|
||||
|
||||
@@ -235,6 +235,12 @@ vi.mock("@earendil-works/pi-ai", () => ({
|
||||
Array: (schema: unknown, opts?: unknown) => ({ type: "array", items: schema, ...((opts as object) ?? {}) }),
|
||||
Union: (schemas: unknown[], opts?: unknown) => ({ anyOf: schemas, ...((opts as object) ?? {}) }),
|
||||
Literal: (value: unknown) => ({ const: value }),
|
||||
Unknown: (opts?: unknown) => ({ ...((opts as object) ?? {}) }),
|
||||
Record: (_key: unknown, value: unknown, opts?: unknown) => ({
|
||||
type: "object",
|
||||
additionalProperties: value,
|
||||
...((opts as object) ?? {}),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
vi.mock("@earendil-works/pi-coding-agent", () => {
|
||||
|
||||
@@ -118,7 +118,7 @@ describe("recoverInProgressLimbo", () => {
|
||||
taskDoneRetryCount: null,
|
||||
sessionFile: null,
|
||||
}));
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-5149", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-5149", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
expect(store.recordRunAuditEvent).toHaveBeenCalledWith(expect.objectContaining({
|
||||
domain: "database",
|
||||
mutationType: "task:auto-recover-in-progress-limbo",
|
||||
|
||||
@@ -458,6 +458,8 @@ describe("SelfHealingManager", () => {
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-001", "todo", {
|
||||
preserveProgress: true,
|
||||
preserveStatus: true,
|
||||
moveSource: "engine",
|
||||
recoveryRehome: true,
|
||||
});
|
||||
expect(store.updateTask).toHaveBeenLastCalledWith("FN-001", expect.objectContaining({
|
||||
stuckKillCount: 7,
|
||||
@@ -494,6 +496,8 @@ describe("SelfHealingManager", () => {
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-001", "todo", {
|
||||
preserveProgress: true,
|
||||
preserveStatus: true,
|
||||
moveSource: "engine",
|
||||
recoveryRehome: true,
|
||||
});
|
||||
expect(store.updateTask).not.toHaveBeenCalledWith("FN-001", expect.objectContaining({
|
||||
paused: false,
|
||||
@@ -530,6 +534,8 @@ describe("SelfHealingManager", () => {
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-001", "todo", {
|
||||
preserveProgress: true,
|
||||
preserveStatus: true,
|
||||
moveSource: "engine",
|
||||
recoveryRehome: true,
|
||||
});
|
||||
expect(store.logEntry).toHaveBeenCalledWith(
|
||||
"FN-001",
|
||||
@@ -1364,7 +1370,7 @@ describe("SelfHealingManager", () => {
|
||||
"FN-1473",
|
||||
expect.stringContaining("no-progress no-task_done failure"),
|
||||
);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-1473", "todo");
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-1473", "todo", { moveSource: "engine", recoveryRehome: true });
|
||||
|
||||
managerWithRecovery.stop();
|
||||
});
|
||||
@@ -2233,7 +2239,7 @@ describe("SelfHealingManager", () => {
|
||||
"FN-3900",
|
||||
expect.stringContaining("session-start unusable-worktree assertion"),
|
||||
);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-3900", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-3900", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
|
||||
managerWithRecovery.stop();
|
||||
});
|
||||
@@ -2277,7 +2283,7 @@ describe("SelfHealingManager", () => {
|
||||
"FN-4559",
|
||||
expect.stringContaining("session-start unusable-worktree assertion"),
|
||||
);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4559", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4559", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
|
||||
managerWithRecovery.stop();
|
||||
});
|
||||
@@ -2309,7 +2315,7 @@ describe("SelfHealingManager", () => {
|
||||
"FN-4560",
|
||||
expect.stringContaining("session-start unusable-worktree assertion"),
|
||||
);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4560", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4560", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
|
||||
managerWithRecovery.stop();
|
||||
});
|
||||
@@ -2349,7 +2355,7 @@ describe("SelfHealingManager", () => {
|
||||
"FN-4651",
|
||||
expect.stringContaining("Auto-recovered (no-progress): session-start refused unusable worktree"),
|
||||
);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4651", "todo");
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-4651", "todo", { moveSource: "engine", recoveryRehome: true });
|
||||
|
||||
managerWithRecovery.stop();
|
||||
});
|
||||
@@ -2574,7 +2580,7 @@ describe("SelfHealingManager", () => {
|
||||
"FN-2164",
|
||||
expect.stringContaining("Auto-retry 1/3"),
|
||||
);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-2164", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-2164", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
|
||||
managerWithRecovery.stop();
|
||||
});
|
||||
@@ -3912,7 +3918,7 @@ describe("SelfHealingManager", () => {
|
||||
"FN-1572",
|
||||
expect.stringContaining("in-review task still had incomplete steps"),
|
||||
);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-1572", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-1572", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
|
||||
managerWithRecovery.stop();
|
||||
});
|
||||
@@ -3971,7 +3977,7 @@ describe("SelfHealingManager", () => {
|
||||
const result = await managerWithRecovery.recoverStaleIncompleteReviewTasks();
|
||||
|
||||
expect(result).toBe(1);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-407-test-1", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-407-test-1", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
|
||||
managerWithRecovery.stop();
|
||||
});
|
||||
@@ -3999,7 +4005,7 @@ describe("SelfHealingManager", () => {
|
||||
const result = await managerWithRecovery.recoverStaleIncompleteReviewTasks();
|
||||
|
||||
expect(result).toBe(1);
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-407-test-2", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-407-test-2", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
|
||||
managerWithRecovery.stop();
|
||||
});
|
||||
@@ -5808,7 +5814,7 @@ describe("SelfHealingManager", () => {
|
||||
|
||||
expect(result).toBe(1);
|
||||
expect(store.updateTask).not.toHaveBeenCalled();
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-9003", "todo", { preserveProgress: true });
|
||||
expect(store.moveTask).toHaveBeenCalledWith("FN-9003", "todo", { preserveProgress: true, moveSource: "engine", recoveryRehome: true });
|
||||
|
||||
managerWithRecovery.stop();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user