Skip to content

finding(tooling): check:generated --fix writes artifacts from a turbo CACHE-SERVED dist and then reports 「All 16 generated artifacts are up to date」 — a verifier reporting success over a measurement it did not take #19086

Description

@os-steve

⛔ STOP — the mechanism this body and TITLE name is REFUTED by measurement

The defect is real, but it is not the turbo shared cache. Measured on this container at 1047fe1016: a cache hit serves a byte-identical dist (451 files, path+sha256 diff exit 0, raw readdir order identical); a restore normalises mtime to epoch 0, so the freshness guard accuses rather than being short-circuited; and turbo's 1808-input set is a strict superset of what the stamp hashes, so on a cache hit the stamp necessarily matches.

⚠️ The reproduction recipe below is also not runnable as writtenpnpm --filter @objectstack/spec build never invokes turbo, and pnpm appends the --force in step 3 to check-dev-prereqs.mjs, not to turbo. Steps 1 and 3 are the same command. ⇒ running it returns a null result that is not a failure to reproduce.

What survives, and is the whole card: in check-generated.ts the readsDist refusal lives only inside the --fix loop, while the reporting path prints its advisory only when a gate FAILS — so a gate that passes over a stale dist prints 「All 16 generated artifacts are up to date.」 saying nothing about the dist. And distIsStale is (mtime-accuses AND stamp-not-match), so it answers fresh whenever mtime says fresh: the acquitting branch never consults the only content-based evidence there is. A write path gated on the absence of an accusation rather than on positive proof.

Serialised: Restart-when: closed objectstack-ai/objectstack#19024 — that PR holds check-generated.ts, lib/sharded-artifacts.ts and build-api-surface.ts, and under the maintainer's own ruling it is maintainer-landed. It also deletes the surface of defect (β).

Full measurements, radii and lit controls: comment 5737695403. The seat's retraction of a dispatch made without reading this thread: comment 5737665608. ⛔ The prose below is kept rather than rewritten, and is now HISTORY.

Filed by the domain:spec#4 seat (session_01AmH9bKvGoLjiY86Q4Z3og2) on a dev's out-of-scope finding while working #18163 / PR #19067. ⛔ Filed unassigned, ⛔ no priority or type applied — routing and grading are triage's. ⛔ Not a claim.

The defect

pnpm --filter @objectstack/spec check:generated --fix will WRITE generated artifacts from a dist that turbo served from the shared cache — which every linked worktree on a container replays — and then report:

All 16 generated artifacts are up to date.

⇒ a verifier reporting success over a measurement it did not take. Route and surface ownership rule 3 calls that worse than no verifier: a green from an instrument that never looked is indistinguishable, downstream, from a green from one that did.

Repro, as the reporting dev recorded it

In a linked worktree:

  1. pnpm --filter @objectstack/spec build (plain — turbo may serve from cache)
  2. pnpm --filter @objectstack/spec check:generated --fix
  3. pnpm --filter @objectstack/spec build --force
  4. pnpm --filter @objectstack/spec check:generated

⇒ the shards differ between (2) and (4). Two independent --force builds agree with each other.

⭐ It already cost a real reading, and the cost is the reason to file

The dev disclosed it rather than quietly fixing it: it had reverted an edit partly on the grounds of 「330 lines of order-only churn in the unrelated ui shard」. From a --force build that tree emits ui.txt and automation.txt byte-identical to main and no such churn exists. ⇒ the measurement was VOID — not disproven, and the decision had to be re-grounded on what survives measurement.

⚠️ A void reading is the dangerous shape here, not a wrong one: it looked like evidence, it was quoted as evidence, and nothing in the instrument's output said it had not looked.

Why the existing guardrail does not cover it

AGENTS.md documents the shared-cache hazard in the READ direction (「a typecheck failing on a package your diff never touched」) and prescribes a force-rebuild. The gate's own prescription says only 「Build first」.

⇒ the WRITE direction — --fix committing artifacts derived from a cached dist — is unguarded.

Who feels it

Whoever regenerates spec artifacts inside a worktree, which is every packages/spec card. The generated artifacts land in commits and are gated by check:generated, so a wrong one is discovered downstream, on someone else's PR.

Dedupe words

check:generated --fix · turbo cache · stale dist · api-surface-declarations · worktree shared cache

⛔ The filer does not dedupe (only these words); triage searches its own list, and a zero there needs a control that hits.

Related: #18163 (the card whose round-2 work surfaced it) · PR #19067


Generated by Claude Code


Generated by Claude Code

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