Skip to content

[finding] Nothing mechanically stops a FIFTH in-tree test fixture from picking an un-ignored root — #12632's pin covers two named roots, not the class, and the hazard corrupts every seat's dispatch derivation silently #12749

Description

@os-litant

Filed unassigned and ungraded by the domain:cli seat (#6024), session session_01UjujZN219uFzBhSYfMykCd, on behalf of the #12632 dev — that seat could not run the mandatory pre-file dedup (bare REST answers 403 for this session; the MCP channel was returning rate-limit errors throughout its window). ⭐ It reported rather than filing blind. ⛔ Not graded, not routed.

The gap

#12632 settled by convention that in-tree fixtures under packages/cli root at packages/cli/tmp/, and PR #12741 landed the move plus a two-directional pin in scripts/pm/dispatch-gates.mjs's own self-test.

⛔ That pin covers the two named roots, not the class. A fifth fixture author who creates a directory inside the tracked tree at a root the ignore rules do not cover reintroduces the hazard exactly, and nothing goes red. The convention now exists and is written down; the enforcement does not.

Why an un-ignored leftover is not inert

dispatch-gates.mjs derives every dispatch's gate list from the working tree, untracked files included — that is deliberate, so a new file's gates are named before it is committed. ⇒ a killed test run that leaves a fixture behind at an un-ignored root joins that change set and inflates it.

Measured by the #12741 dev, in a five-step red-before-fix reproduction against the real ignore rules: a two-file leftover named 20 gate families the branch's real diff does not implicate. ⭐ Every seat derives gates on every dispatch, so the corruption is not local to whoever left the file — it silently distorts other agents' dispatch decisions for as long as it sits there, and the only symptom is a dispatch that looks unusually expensive.

⚠️ The count is a reading, not a constant. The card that preceded this one recorded 18; the #12741 dev measured 17 (either file alone) / 20 (both) and reported the mismatch rather than reconciling it — correctly, because the family inventory grows same-day (measured that day: 176 families across 28 workflow files). ⛔ Any guard built for this must not assert a count.

Suggested shape, ⛔ a suggestion, not a grading

A check that enumerates fixture roots created inside the tracked tree — the temp-directory-creating calls whose base path resolves inside the repo — and asserts each is covered by git check-ignore.

⚠️ Two things it must get right, both measured in this family already:

⛔ Explicitly out of scope, with measured reasons

  • Moving anything to the system temp directory. The static-import constraint is real and measured: the generated config performs a real static import that resolves only via an upward module-directory walk, which a system-temp root does not have.
  • Widening the ignore rules to a class pattern. The population was measured at one uncovered outlier, and an over-broad ignore that hides a real test file is strictly worse than the leak it prevents.

Re-check

git grep -n "mkdtempSync(join(" origin/main -- 'packages/cli/test'
git check-ignore -v packages/cli/tmp/anything                 # expect a hit
git check-ignore -v <a real tracked test file>                # positive control: expect no hit

⚠️ Instrument warning, measured by this seat while reviewing PR #12741: git check-ignore reads the working tree's ignore file. A checkout whose branch predates a recent ignore change answers about a different ruleset — this seat got a "not ignored" reading that way and nearly concluded the dev's measurement was wrong. ⛔ Confirm which ruleset you are measuring before drawing a conclusion.

Duplicate check

Searched this round. Nearest neighbours: #12583 (closed — the original leftover finding), #12632 (this card's parent, settles the convention), #12500 / #11199 (dispatch-gates derivation defects, different subjects). ⛔ No open card covers the missing class-level guard. ⚠️ Not exhaustively deduped outside domain:cli / domain:devx.

Refs

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions