test(self-healing): cover the renamed-board starved-refinement wake that main's conversion lacked (#3116)

**Rebased onto current `main`, and it shrank to one test.** Was
"self-healing consolidated (45 → 39)".

## What happened

**Every code change in this PR landed independently from other workers**
while it was open, and in each case theirs is equal or better. I took
theirs and dropped mine:

| My change | Landed on `main` as |
|---|---|
| pre-execution worktree seizure | `preExecLiveColumns` — same
"dangerous direction" reasoning |
| FN-5256 liveness cluster | `worktreeReconcileWipColumns` /
`worktreeReconcileReviewColumns` |
| agent-link membership | `agentLinkLiveColumns` /
`agentLinkTerminalColumns` |
| starved-refinement peer progress | `starvedWaitingColumns` — a project
union covering both duplicated sites |

Resolving the rebase by taking `main` left two orphaned declarations
(`activeOrQueuedColumns`, `holdPeerIds`) that nothing referenced. `tsc`
doesn't flag unused locals here, so I checked references by hand and
removed them rather than ship dead code that reads as converted.

## What's worth landing

**Their starved-refinement conversion has no renamed-board test — the
suite had zero.** This adds one.

A candidate resting in a renamed **intake** lane, with its peers in a
renamed **hold** lane, must still escalate. The two are deliberately
distinct columns so a wrong role set resolves no peers and escalates
nothing; a fixture where they coincide would pass either way.

The fake needed `listWorkflowDefinitions` — `starvedWaitingColumns` is a
**project union**, so per-task selection readers alone leave it
resolving nothing and the test would pass for the wrong reason. That
mismatch is how I found the gap: my original test failed against their
implementation.

## Verification

- Green against **their** code
- **Revert-proof against theirs:** restoring the literal fails it — 0
escalations against 1 expected
- 8 tests in the suite green

## Note for the fleet

This is the second PR of mine to shrink to a test on rebase (#3096 was
the first). Both times the duplicated work was real and mine was the
later arrival. The pattern is worth acting on at the coordination level,
not by me working faster.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-07-31 05:41:32 -07:00
committed by GitHub
parent 6483f9ce2b
commit ce84aa48d0

View File

@@ -77,6 +77,64 @@ describe("SelfHealingManager.recoverStarvedRefinementTriageTasks", () => {
vi.useRealTimers();
});
/*
FNXC:WorkflowResolvedColumns 2026-07-31-16:40 (fleet — peer-progress vocabulary):
"Peer progress" was `peer.column === "todo"` in two places: the candidate filter and the count written
into the log line and audit metadata. On a renamed board both stopped matching, so peer progress read
as zero and starved refinements were never escalated — silently, since a zero count is indistinguishable
from a genuinely quiet board.
The board below separates intake from hold on purpose. The candidate rests in INTAKE (`inbox`) and its
peers in HOLD (`backlog`), so a conversion that reached for the wrong role set — or that left either
site on the literal — resolves no peers and escalates nothing.
*/
it("counts peer progress in the board's own HOLD lane on a renamed board", async () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-05-15T11:00:00.000Z"));
const RENAMED_IR = {
version: "v2",
name: "renamed-starvation",
columns: [
{ id: "inbox", name: "Inbox", traits: [{ trait: "intake" }] },
{ id: "backlog", name: "Backlog", traits: [{ trait: "hold" }] },
{ id: "building", name: "Building", traits: [{ trait: "wip" }] },
],
nodes: [],
edges: [],
};
const tasks: Task[] = [
task({ id: "FN-R9", column: "inbox", sourceType: "task_refine", createdAt: "2026-05-15T10:00:00.000Z", updatedAt: "2026-05-15T10:00:00.000Z", priority: "low" }),
task({ id: "FN-Q1", column: "backlog", sourceType: "dashboard_ui", updatedAt: "2026-05-15T10:15:00.000Z" }),
task({ id: "FN-Q2", column: "backlog", sourceType: "dashboard_ui", updatedAt: "2026-05-15T10:16:00.000Z" }),
task({ id: "FN-Q3", column: "backlog", sourceType: "dashboard_ui", updatedAt: "2026-05-15T10:17:00.000Z" }),
];
const updateTask = vi.fn(async () => undefined);
const store: any = {
getSettings: vi.fn().mockResolvedValue({ globalPause: false, enginePaused: false }),
listTasks: vi.fn().mockResolvedValue(tasks),
updateTask,
logEntry: vi.fn().mockResolvedValue(undefined),
recordRunAuditEvent: vi.fn().mockResolvedValue(undefined),
getTaskWorkflowSelection: vi.fn(() => ({ workflowId: "custom:renamed", stepIds: [] })),
getTaskWorkflowSelectionAsync: vi.fn(async () => ({ workflowId: "custom:renamed", stepIds: [] })),
getWorkflowDefinition: vi.fn(async () => ({ ir: RENAMED_IR })),
/* `starvedWaitingColumns` is a PROJECT union (`resolveProjectColumnsForRoles`), so the fake needs
`listWorkflowDefinitions`; the per-task selection readers alone leave it resolving nothing and
the test would pass for the wrong reason. */
listWorkflowDefinitions: vi.fn(async () => [{ id: "custom:renamed", ir: RENAMED_IR }]),
on: () => {},
removeListener: () => {},
};
const manager = new SelfHealingManager(store, { rootDir: process.cwd(), getPlanningTaskIds: () => new Set() });
await expect(manager.recoverStarvedRefinementTriageTasks()).resolves.toBe(1);
expect(updateTask).toHaveBeenCalledWith("FN-R9", { priority: "normal" });
vi.useRealTimers();
});
it("does not escalate non-refinement triage tasks", async () => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-05-15T11:00:00.000Z"));