Skip to content

[finding][spec] strictness-ledger.test.ts's z.object(…).strict() fixture is a borrowed live site on a treadmill — it has moved three times in three PRs, and the #4001 campaign's own direction is to convert every remaining carrier #6940

Description

@os-project-manager

Observation-class. Found while implementing #6805 (PR #6935), which moved this fixture for the third time. Filed unassigned, no pm:queue — nothing a user hits today; this is a dated fuse under a gate's regression cover.

The mechanism

packages/spec/scripts/strictness-ledger.test.ts has a case named "reads the OLDER z.object(…).strict() spelling as strict too". It exists because the ledger's AST posture reader must keep making that reading — packages/spec is not the only tree it reads — and a strictObject(-only count reads automation/ as 0 strict when it has 8.

To make the reading, the test picks a real live site in the tree and asserts its posture/idiom. That site is borrowed, not owned. And the #4001 campaign's entire direction is to convert every remaining z.object(shape, { error }).strict() carrier to strictObject. So each conversion wave evicts the fixture:

Fixture Evicted by
security/permission.zod.ts (four sites) #5593 migrated all four
TenancyConfigSchema (data/object.zod.ts) #6619 / PR #6804 folded its map
ObjectCapabilities (same file) #6805 / PR #6935 folded its map
PerOperationRequiredPermissionsSchema (same file) — current

Three moves in three PRs. The test's own comment handles each move correctly ("move this fixture rather than deleting the assertion"), and every author so far has obeyed it — so this is not a defect report against any of them.

Why it is still worth recording

Two properties make the treadmill different from ordinary churn:

  1. The instruction's cost rises as the population falls. Today data/object.zod.ts still has other z.object(…).strict() sites. The campaign's stated goal leaves fewer each wave. The terminal state is a tree with zero in-repo carriers, at which point the instruction "move it" has nowhere to point and the next author faces exactly the choice the comment forbids — delete the assertion — with no third option written down.
  2. The current carrier is better but not immune. PerOperationRequiredPermissionsSchema was chosen deliberately: it carries no guidance/aliases table, so nothing pulls it toward the helper the way a prescription table does. That is a reason it is unlikely to be converted, not a reason it cannot be. It remains an authorable surface the ratchet may reach on other grounds.

Shape of a fix (non-binding)

The reading under test is a property of the reader (scripts/lib/strictness-ledger.ts), not of any file in the tree. The posture reading describe block already has the machinery for this: its mutate() helper analyses a written-out temp copy of a source, and two neighbouring cases (reads the strictObject( helper as strict — and as strip once un-converted, reads a default site as strip — and as strict once closed) use it to make a reading over source the tree does not have to contain.

So the same case could read a small owned fixture (a temp file, or a __fixtures__ source) spelling z.object(shape, { error }).strict(), with the live-site assertion kept alongside as a control while any carrier survives — which preserves what the borrowed site really buys (evidence the idiom exists in the wild) without making the gate's cover depend on it.

⚠️ Explicitly NOT proposing to drop the live-site reading. That reading is what connects the instrument to reality; the point is only that it should not be the sole carrier of the assertion.

Not in scope / dedup

Provenance

Measured at PR #6935's head while relocating the fixture; the eviction history above is read from the test's own comment chain plus the #5593 / #6619 / #6805 diffs.

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