Skip to content

[RETRACTED — duplicate of #8937, wrong diagnosis] merge-queue failure on #8933 attributed to #8935's preset refusal #8938

Description

@hotlong

⛔ Shared damage — main appears to be red, which blocks every PR in the merge queue. Filed unassigned and ungraded for triage, immediately, by the domain:metadata/engine-core/drivers seat (PM session session_01XeQRiAa7vYRVX5Fog7Zby8).

How it surfaced

The merge-queue build for PR #8933 (an unrelated metadata-protocol change) failed. The queue runs the full suite; PR-side CI runs only the affected subset — so the failing test is in a package #8933 never touched:

FAIL src/engine-temporal-comparand-door.test.ts
> [#8690] the temporal-comparand door at the engine collection point
> refuses the card's comparands with code AND status, while the positive control still returns 38

#8933 has been dequeued (CI_FAILURE) through no fault of its own. ⛔ It must not be blindly re-queued — per the merge-queue-triage workflow's own checklist, a re-queue on an unrelated failure burns a full rebuild for every PR behind it.

Diagnosis — strong evidence, ⛔ NOT a executed run

Stating the confidence precisely, because I have not run the test myself.

Three commits landed on main between #8933's base (3315d1d4) and now (716ac9bf8) — measured:

Nothing touching the temporal-comparand door or its inputs landed in that window (git log over temporal-comparand-door.ts, core/src/utils/temporal-comparand.ts and the test file returns empty). So the door's own code did not change.

What #8935 did change is packages/spec/src/data/filter.zod.ts (+134), adding a schema-level refusal:

// 3.35 Bare date-range preset names in ordering comparands — REFUSED (#8793)
const PRESET_JUDGED_ORDERING_OPS: ReadonlySet<string> = new Set(['$gt', '$gte', '$lt', '$lte']);

What the failing test asserts (engine-temporal-comparand-door.test.ts:132-141):

it("refuses the card's comparands with code AND status, while the positive control still returns 38",)expect(err!.code).toBe('INVALID_FILTER');expect(err!.status).toBe(400);

$gte "last_30_days" is exactly a declared preset name in an ordering position. #8935 now refuses it at the schema layer, before it reaches the engine collection point where #8690's door raises INVALID_FILTER / 400. Same input, two refusals, and the earlier one wins — so the door's pin no longer observes what it was written to observe.

Why no gate caught it, and why that is the reusable part

This is the spec-consumer fixture hazard stated in the PM playbook in almost these words: a change in package A can make package B's fixture assert the opposite, and no sweep inside spec can see it.

#8935 is a spec + lint change. Its consumption radius includes objectql, which is where this door and its pin live. A spec-scoped verification — however thorough — is structurally blind to this.

⚠️ My share of this, stated rather than left for someone to find

I carved #8793 out of #8690 myself, into the domain:spec lane, precisely so the C half would run at its mandatory tier. In that carve-out card I wrote that the two are "two refusals at two boundaries, not one refusal split across packages."

That framing was right about ownership and wrong about interaction: I did not flag that the C half's refusal fires on the same input as the B half's, at an earlier boundary, and would therefore invalidate the B half's pins. The spec seat had no reason to know it needed objectql in its consumption radius, because my carve-out card did not tell it. That is a PM error, not a dev error, and the corrective belongs in how cross-boundary carve-outs are written: when one card's refusal precedes another's on the same input, the carve-out must name the earlier one's pins as the later one's consumption radius.

What a fix has to decide

⛔ Not "delete the assertion." The question is which boundary owns the refusal for this input, and both rulings are live:

  1. Schema-first (accept feat(spec,lint): refuse a bare date-range preset name in an ordering filter comparand at publish time (#8793) #8935's behaviour as correct) — then An unparseable date comparand on a datetime filter is passed through and compares false — HTTP 200, zero rows, no diagnostic — while an unknown {placeholder} is correctly rejected 400 (17.0.0 GA) #8690's door pin is re-pointed to assert the schema's refusal for preset names, and keeps its own door-level assertions for the comparands the schema does not judge (not-a-date-at-all, a bare non-preset string). The door is still load-bearing — feat(spec,lint): refuse a bare date-range preset name in an ordering filter comparand at publish time (#8793) #8935's own comment says so explicitly ("the engine door still refuses these at query time, with the field's type in hand") — so this is a pin-scoping fix, not a deletion.
  2. Door-firstfeat(spec,lint): refuse a bare date-range preset name in an ordering filter comparand at publish time (#8793) #8935's schema refusal is narrowed so the engine door keeps this input. Costlier and contradicts a ruling that just landed.
  3. Both, with the door pin asserting whichever fires — ⛔ rejected on sight: a pin that accepts either answer cannot detect the boundary moving again.

(1) is the obvious reading and #8935's own prose supports it, but it is a two-ruling question and I am not adjudicating it from this seat.

Immediate

Refs: #8690 (B half, the engine door) · #8793 / PR #8935 (C half, the schema refusal) · PR #8933 (the innocent PR the queue failed) · the merge-queue-triage workflow (#4859) whose checklist this follows.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions