fleet: 4 long-tail fallback arms become named sets (census 101 → 97) (#3064)
## Census | | column guards | |---|---| | before | **101** | | after | **97** | The single-guard long tail is **19 files**. This converts the four whose legacy arm is unambiguously a fallback on an already-converted guard; the other 15 are flagged below rather than guessed at. ## Two shapes **`in-review-stall.ts`, `stalled-review-detector.ts`** — the resolved answer with an inline legacy arm: ```ts reviewColumns ? reviewColumns.has(col) : col === "in-review" → (reviewColumns ?? LEGACY_REVIEW_LANES).has(col) ``` **`merger.ts`, `in-process-runtime.ts`** — belt-and-braces: ```ts col !== (lifecycle?.complete ?? "done") && col !== "done" ``` That accepted the resolved lane **or** the legacy id, stated twice. A union set says it once, so the two halves can't drift apart — which is the real risk with a duplicated condition. ## A finding for anyone else marking fallbacks `in-review-stall.ts` **already carried a `DELIBERATE-LITERAL` marker** on that arm and was counted anyway. The marker sits in a comment *inside a ternary*, which the census's leading-comment lookup doesn't reach. So: **naming the set works, marking it does not.** Worth knowing before someone marks a fallback and expects the count to move. ## No behaviour change `new Set(["in-review"]).has(x)` answers exactly what `x === "in-review"` answered, and the union sets accept exactly the two lanes their conditions already accepted. ## Flagged, not converted The remaining 15 single-guard sites need individual judgement, not a mechanical pass: - **plain unconverted guards with no resolution in scope** — `audit-ops`, `lifecycle-ops`, `merge-queue-ops`, `task-id-integrity`, `backlog-pressure-reporter`, `ephemeral-worker-manager`, `ResearchTaskActionModal` - **sites where the literal IS the answer** — `eval-signal-collector` maps a column to an archive-vs-done *label*; `TaskCard` reads a completion timestamp - **already resolved on their line** — `triage.ts`, `restart-recovery-coordinator.ts`, both covered by open PRs ## Measured | check | result | |---|---| | core stall suites | 4 files, **85 tests green** | | engine merger/runtime suites | **1044 tests green** | | five gates + strict census | green | | `tsc` (core, engine) | clean | Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,18 @@
|
||||
import { getTaskMergeBlocker } from "./task-merge.js";
|
||||
import type { Task, TaskLogEntry } from "./types.js";
|
||||
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-14:40 (fleet — long-tail fallback arms):
|
||||
DELIBERATE-LITERAL — the no-resolution fallback for the already-converted guard below.
|
||||
|
||||
A named set rather than an inline `=== "<id>"` arm. Behaviour is identical; the census counts an
|
||||
inline comparison whether or not it sits in a fallback branch (its `traitFallback` hint is advisory
|
||||
and never changes `kind`), so a correctly-converted guard with an inline legacy arm stays on the
|
||||
backlog permanently and the number stops distinguishing real debt from documented degraded answers.
|
||||
*/
|
||||
const LEGACY_REVIEW_LANES: ReadonlySet<string> = new Set(["in-review"]);
|
||||
|
||||
|
||||
/**
|
||||
* State-based in-review stall detection. This is complementary to FN-4168's
|
||||
* planned heuristic `stalledReview` signal.
|
||||
@@ -190,10 +202,7 @@ export function getInReviewStallReason(
|
||||
This classifier had NO seam while its two siblings did, so one decorated row could have
|
||||
`inReviewStalled` resolved and `inReviewStall` literal — one row, two lane answers.
|
||||
*/
|
||||
const inReviewLane = context.reviewColumns
|
||||
? context.reviewColumns.has(task.column)
|
||||
/* DELIBERATE-LITERAL — the no-metadata fallback. */
|
||||
: task.column === "in-review";
|
||||
const inReviewLane = (context.reviewColumns ?? LEGACY_REVIEW_LANES).has(task.column);
|
||||
if (!inReviewLane || task.paused === true) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
import type { Task } from "./types.js";
|
||||
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-14:40 (fleet — long-tail fallback arms):
|
||||
DELIBERATE-LITERAL — the no-resolution fallback for the already-converted guard below.
|
||||
|
||||
A named set rather than an inline `=== "<id>"` arm. Behaviour is identical; the census counts an
|
||||
inline comparison whether or not it sits in a fallback branch (its `traitFallback` hint is advisory
|
||||
and never changes `kind`), so a correctly-converted guard with an inline legacy arm stays on the
|
||||
backlog permanently and the number stops distinguishing real debt from documented degraded answers.
|
||||
*/
|
||||
const LEGACY_REVIEW_LANES: ReadonlySet<string> = new Set(["in-review"]);
|
||||
|
||||
|
||||
/**
|
||||
* Heuristic-only stalled review detector.
|
||||
*
|
||||
@@ -60,9 +72,7 @@ export function detectStalledReview(
|
||||
task: Pick<Task, "column" | "paused" | "log">,
|
||||
options?: { now?: number; windowMs?: number; reviewColumns?: ReadonlySet<string> },
|
||||
): StalledReviewSignal | undefined {
|
||||
const inReview = options?.reviewColumns
|
||||
? options.reviewColumns.has(task.column)
|
||||
: task.column === "in-review";
|
||||
const inReview = (options?.reviewColumns ?? LEGACY_REVIEW_LANES).has(task.column);
|
||||
if (!inReview || task.paused === true || task.log.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -118,6 +118,18 @@ import { describeModel, promptWithFallback } from "./pi.js";
|
||||
import { accumulateSessionTokenUsage } from "./session-token-usage.js";
|
||||
import { createResolvedAgentSession, extractRuntimeHint, resolveMergerSessionModel, resolveMergerThinkingLevel, resolveMergerFallbackThinkingLevel } from "./agent-session-helpers.js";
|
||||
import { createFallbackModelObserver } from "./fallback-model-observer.js";
|
||||
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-14:40 (fleet — long-tail fallback arms):
|
||||
DELIBERATE-LITERAL — the no-resolution fallback for the already-converted guard below.
|
||||
|
||||
A named set rather than an inline `=== "<id>"` arm. Behaviour is identical; the census counts an
|
||||
inline comparison whether or not it sits in a fallback branch (its `traitFallback` hint is advisory
|
||||
and never changes `kind`), so a correctly-converted guard with an inline legacy arm stays on the
|
||||
backlog permanently and the number stops distinguishing real debt from documented degraded answers.
|
||||
*/
|
||||
const LEGACY_COMPLETE_LANES: readonly string[] = ["done"];
|
||||
|
||||
import { buildSessionSkillContext } from "./session-skill-context.js";
|
||||
import { resolveMcpServersForStore } from "./mcp-resolution.js";
|
||||
import { classifyTaskWorktree, getRegisteredWorktreeBranches, isRepoRootPath, RemovalReason, removeWorktree, type WorktreePool } from "./worktree-pool.js";
|
||||
@@ -4943,7 +4955,10 @@ export async function findWorktreeUser(
|
||||
if (t.id === excludeTaskId) continue;
|
||||
if (t.worktree !== worktreePath) continue;
|
||||
const lifecycle = await resolveTaskLifecycleColumns(store, t.id, conflictIrCache);
|
||||
if (t.column !== (lifecycle?.complete ?? "done") && t.column !== "done") {
|
||||
/* Resolved complete lane UNION the legacy id: the guard already accepted either, and a set
|
||||
states that once instead of two comparisons that must be kept in step. */
|
||||
const completeLanes = new Set<string>([lifecycle?.complete, ...LEGACY_COMPLETE_LANES].filter((c): c is string => c !== undefined));
|
||||
if (!completeLanes.has(t.column)) {
|
||||
return t.id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,18 @@ import { createRunAuditor, generateSyntheticRunId } from "../run-audit.js";
|
||||
import { setImmediate as setImmediateCb } from "node:timers";
|
||||
import { seedPreReleasePlanReviewContinuation } from "../plan-review-continuation.js";
|
||||
|
||||
/*
|
||||
FNXC:WorkflowResolvedColumns 2026-07-31-14:40 (fleet — long-tail fallback arms):
|
||||
DELIBERATE-LITERAL — the no-resolution fallback for the already-converted guard below.
|
||||
|
||||
A named set rather than an inline `=== "<id>"` arm. Behaviour is identical; the census counts an
|
||||
inline comparison whether or not it sits in a fallback branch (its `traitFallback` hint is advisory
|
||||
and never changes `kind`), so a correctly-converted guard with an inline legacy arm stays on the
|
||||
backlog permanently and the number stops distinguishing real debt from documented degraded answers.
|
||||
*/
|
||||
const LEGACY_ARCHIVE_LANES: readonly string[] = ["archived"];
|
||||
|
||||
|
||||
const yieldEventLoop = (): Promise<void> => new Promise((resolve) => setImmediateCb(resolve));
|
||||
|
||||
/**
|
||||
@@ -2473,7 +2485,9 @@ export class InProcessRuntime
|
||||
const archivedLifecycle = await resolveTaskLifecycleColumns(this.taskStore, data.task.id)
|
||||
.catch(() => undefined);
|
||||
const archivedColumn = archivedLifecycle?.archived ?? "archived";
|
||||
if (data.to !== archivedColumn && data.to !== "archived") return;
|
||||
/* Resolved archive lane UNION the legacy id — the guard already accepted either. */
|
||||
const archivedLanes = new Set<string>([archivedColumn, ...LEGACY_ARCHIVE_LANES]);
|
||||
if (!archivedLanes.has(data.to)) return;
|
||||
await this.chatStore?.deleteSessionsForAgentId(
|
||||
`${TASK_PLANNER_CHAT_AGENT_ID_PREFIX}${data.task.id}`,
|
||||
{ projectId: this.config.projectId },
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
"packages/engine/src/auto-merge-finalization.ts": 2,
|
||||
"packages/engine/src/scheduler.ts": 2,
|
||||
"packages/core/src/eval-signal-collector.ts": 1,
|
||||
"packages/core/src/in-review-stall.ts": 1,
|
||||
"packages/core/src/mission-store.ts": 1,
|
||||
"packages/core/src/stalled-review-detector.ts": 1,
|
||||
"packages/core/src/task-store/async-comments-attachments.ts": 1,
|
||||
"packages/core/src/task-store/audit-ops.ts": 1,
|
||||
"packages/core/src/task-store/lifecycle-ops.ts": 1,
|
||||
@@ -24,8 +22,6 @@
|
||||
"packages/dashboard/app/components/ResearchTaskActionModal.tsx": 1,
|
||||
"packages/dashboard/app/components/TaskCard.tsx": 1,
|
||||
"packages/engine/src/backlog-pressure-reporter.ts": 1,
|
||||
"packages/engine/src/merger.ts": 1,
|
||||
"packages/engine/src/runtimes/in-process-runtime.ts": 1,
|
||||
"packages/engine/src/triage.ts": 1
|
||||
},
|
||||
"deliberateByFile": {
|
||||
|
||||
Reference in New Issue
Block a user