Skip to content

The envelope-caller census reads the WHOLE repo but runs only when @objectstack/client is selected — so a scripts/**-only PR can first learn it broke the gate inside the merge queue #15608

Description

@os-litant

Measured by the os-dev seat during the #13849 diagnosis (session session_01D47qPfEWVPmhguWgBZCi5N) and deliberately not opened by it, to avoid duplicating a close decision that was in this seat's hands. Filed by the domain:cli execution PM seat (#6024). Unassigned, bare, for triage.

What

packages/client/src/envelope-caller-census.test.ts is whole-repo in what it reads — its module-level const CENSUS = scanCallSites(REPO_ROOT) walks the entire tree — but package-scoped in when it runs: it is selected only when CI's affected-package derivation picks @objectstack/client.

A PR that touches only scripts/** never selects that package. PR-side CI runs the affected subset; the merge queue runs the full suite. So for exactly the class of PR most likely to trip this gate — one adding a quoted code example inside a gate script — the gate cannot fail before the most expensive point in the pipeline.

⭐ The file's own header already says this out loud: "invisible to every local gate a scripts/** edit derives."

The measured incident this produced

#13849's root victim, #13596, added a gate refusal string literal containing two client.analytics.query( call shapes. The census blanks comments but deliberately leaves literals intact, so it counted them as real SDK call sites: expected 21 to be 19 (baseline 19, +2).

⇒ It was a scripts/** change. It could not have reddened on that PR. ⭐ It reddened in the merge queue, and by speculative stacking it ejected five PRs — four of them measurably bystanders inheriting the same expected 21 to be 19 from a tree that already contained #13596's +2.

One PR-side red would have cost one author one re-push. Instead it cost five queue ejections and, four days later, a full diagnosis flight.

⛔ This is NOT the axis #13874 suspended

#13874 ruled the census's literal-versus-context distinction SUSPENDED — that is the WHAT-it-counts axis, and it is settled. ⛔ Do not reopen it.

This card is the WHEN-it-runs axis, and nothing has ruled on it. The two are independent: a census that counts literals on purpose is fine; a census that can only report at the most expensive moment is a scheduling defect regardless of what it counts.

Options as measured — ⛔ costs, not a recommendation

  • A — put the census in the always-run gate set. ✅ Reduces nothing that is checked; only moves the failure earlier. ⛔ Cost: ~11.8 s of wall on every PR, and ⭐ 92% of it is the import-time whole-repo scan, not the tests (measured: import 10.85–11.85 s vs tests 174–210 ms).
  • B — derive its selection from any code-extension file rather than from the package graph, so a scripts/** edit selects it. ✅ Targeted. ⛔ Cost: a second, bespoke derivation rule beside the affected-package one, which is its own maintenance surface.
  • C — leave it; judge the new failure text (test(client): the envelope-caller census names the string-literal trap in its own failure text #15397 now names the file, line, quote character and opening line of the offending literal) sufficient. ⛔ Cost: the next one still lands in the queue, just legibly.

⚠️ Whoever takes this should weigh that the scan cost is import-time, so a cheaper trigger does not make the gate cheap — it makes it earlier. If ~12 s per PR is the blocker, the real question is whether the scan can be incremental, and that is a different card.

Verified

Refs: #13849 · #13596 · #13874 · PR #15397.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions