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:

FixtureEvicted 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

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions