|
| 1 | +--- |
| 2 | +"@objectstack/spec": patch |
| 3 | +--- |
| 4 | + |
| 5 | +fix(devx): gate `pnpm dev` on a STALE `packages/spec/dist`, not only a missing one (#5864) |
| 6 | + |
| 7 | +`check:dev-prereqs` (PR #5863) asserted that every workspace package's declared |
| 8 | +`dist/` entry point exists. That covered one half of #5726 — a **missing** |
| 9 | +artifact, which fails loudly — and left the other half ungated: a dist that is |
| 10 | +present but **stale**, which does not fail at all. It lies, and it lies about |
| 11 | +somebody else's code. #5726's 20+ TypeScript errors read exactly like real |
| 12 | +contract drift while `isAppResolvedDefaultToken` was exported from `src/` the |
| 13 | +whole time and merely absent from a stale `packages/spec/dist`. |
| 14 | + |
| 15 | +Worse, the existence gate made that half slightly more misleading than before: |
| 16 | +the developer was told the workspace was fine seconds before the fake drift |
| 17 | +appeared, so a green line was vouching for something it had never checked. |
| 18 | + |
| 19 | +**The definition, so a gate can decide it.** `packages/spec`'s build now records |
| 20 | +a sha256 of its own build inputs into `packages/spec/dist/.build-input-hash` as |
| 21 | +its last step; `check:dev-prereqs` recomputes that hash and compares. Stale ⇔ |
| 22 | +the two differ. Inputs are everything under `src/`, the package manifest, the |
| 23 | +package's own tsconfig/tsup config, and turbo.json's `globalDependencies` — |
| 24 | +read from turbo.json rather than restated, so the build's own declaration of a |
| 25 | +global input is also the gate's. |
| 26 | + |
| 27 | +**Content, never mtime.** PR #5863 refused this half because comparing source |
| 28 | +mtimes against `dist` false-reds after any checkout, and a gate that cries wolf |
| 29 | +on day one gets switched off. A content hash is immune to all of it — `git |
| 30 | +worktree add`, `git checkout`, restored backups, clock skew, `touch`. Verified |
| 31 | +on the real tree: a source file rewritten with identical bytes and an mtime one |
| 32 | +hour in the future (so `src` is strictly newer than `dist`) stays green. |
| 33 | + |
| 34 | +**Scope, stated rather than implied.** Freshness is asserted for `packages/spec` |
| 35 | +alone — AGENTS.md §9's stale-artefact table names exactly one dist that presents |
| 36 | +as *other people's* contract drift. The pass line now says which claim is which: |
| 37 | +existence for all 67 packages, freshness for the one. An unstamped amplifier |
| 38 | +dist is red rather than a warning, because that is precisely the tree #5726 was |
| 39 | +run on, and a gate that cannot find its freshness input has verified nothing |
| 40 | +(#4690). |
| 41 | + |
| 42 | +**For consumers of `@objectstack/spec`:** no API, type or runtime change. The |
| 43 | +published tarball gains one 65-byte file, `dist/.build-input-hash`, which is the |
| 44 | +build's own input digest and is read only by this repo's dev gate. |
0 commit comments