fix(fnxc): three future-dated scheduler stamps — main red through three closed fixes (#3280)
**`check-fnxc-future-dates` exits 1 on `origin/main`.** ``` packages/engine/src/scheduler.ts: 3 future-dated stamps, baseline allows 2 FNXC:ConcurrencyAdmission 2026-08-06-09:00 (six days out) FNXC:WorkflowLifecycleColumns 2026-08-01-05:00 FNXC:WorkflowScheduling 2026-08-01-01:05 ``` All three repointed to `2026-07-31`, times preserved. Gate now exits 0. ## This red has outlived three owners #3270, #3272 and #3274 were each opened against it and each **closed without merging**. Main has been red on this gate for hours while three fixes came and went. Claimed with `check-file-claimed.mjs` before starting — only #3262 touches `scheduler.ts`, and it is a terminal-role refactor rather than a stamp fix, so this was genuinely unowned. ## Why this keeps recurring Seven incidents in roughly two hours. The mechanism, in one line: **the date check runs only in CI** (`pr-checks.yml:66`, no pre-commit or pre-push hook), so every PR is validated against main's baseline *at its own CI time* and cannot see a concurrent or later change. Two PRs stamping the same file both pass, then compose into a red main. One case (#3273) was a stale branch **reverting** an already-merged fix. Patching instances has not converged — this PR is the eighth attempt at the same class. Two structural options, neither of which I am landing unilaterally since the second changes the gate's contract: - run the date check at **author time** (pre-push); it needs no baseline for "is this date in the future", so it cannot be raced - make the date rule **baseline-free** — a future-dated stamp is always wrong, unlike a lifecycle literal that may be a deliberate fallback `2026-08-06` being six days out also suggests these are not off-by-one timezone slips but stamps written from an intended future date. ## Verification - `check-fnxc-future-dates` — **exit 0** (was exit 1 on main) - `scheduler` suites — **148 pass** - `tsc --noEmit` (engine) — 0 errors - comment-only diff, no behaviour change Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -960,7 +960,7 @@ export class Scheduler {
|
||||
logger: schedulerLog,
|
||||
});
|
||||
/*
|
||||
FNXC:ConcurrencyAdmission 2026-08-06-09:00:
|
||||
FNXC:ConcurrencyAdmission 2026-07-31-09:00:
|
||||
FN-8453's union must outlive a single scheduler poll. A temporary provider
|
||||
was gone before planning/merge asked for capacity, allowing newer work to
|
||||
overtake ready execute work. The refreshed map is the durable lane view.
|
||||
@@ -1404,7 +1404,7 @@ export class Scheduler {
|
||||
|
||||
const deletedParked = await resolveTaskParkedColumns(this.store, task.id);
|
||||
/*
|
||||
FNXC:WorkflowLifecycleColumns 2026-08-01-05:00:
|
||||
FNXC:WorkflowLifecycleColumns 2026-07-31-05:00:
|
||||
A HALF-CONVERTED PAIR, one line apart. The hold read above already resolved its lane while
|
||||
the wip read below stayed on the literal, so on a renamed board this dependent sweep saw
|
||||
the queued cards and none of the running ones — a dependency held by an in-flight task was
|
||||
@@ -2255,7 +2255,7 @@ export class Scheduler {
|
||||
&& typeof task.worktree === "string" && task.worktree.length > 0)
|
||||
.map((task) => task.id);
|
||||
/*
|
||||
FNXC:WorkflowScheduling 2026-08-01-01:05 (self-deadlock in the widened ledger, observed live):
|
||||
FNXC:WorkflowScheduling 2026-07-31-01:05 (self-deadlock in the widened ledger, observed live):
|
||||
A planned Ready card RETAINS its planning worktree for execution reuse, so counting it as a
|
||||
holder must not block ITS OWN release — on release the slot TRANSFERS (the card executes in
|
||||
the same worktree), it does not add. Without this exclusion the first unpause released only
|
||||
|
||||
Reference in New Issue
Block a user