Uh oh!
There was an error while loading. Please reload this page.
fix(spec): dist-freshness refusal derives package label and build remedy from pkgDir - #11471
Merged
Merged
Conversation
…edy from pkgDir inspectDistFreshness() / inspectBundleFreshness() hardcoded packages/spec in their refusal cause strings and the pnpm --filter @objectstack/spec build remedy line, regardless of pkgDir. Every real caller passed SPEC_DIR until #10969 gave check:skill-examples a second surface (packages/client-react / packages/client) -- confirmed live: a stale-dist refusal on that surface misnamed the stale package and printed a non-actionable remedy. Both cause strings now interpolate a packages/<name> label derived from pkgDir's own path, and the build-remedy line reads pkgDir/package.json#name -- both falling back sensibly when the shape doesn't match / the file is unreadable. dist-freshness.test.ts's pinned literals are updated to match, and two new cases prove the derivation is genuine: a non-spec-shaped pkgDir (packages/widgets, package.json name @acme/widgets), and the package.json- missing fallback. Fixes#11250 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01T9cDbY2NBiVJWYx3BpWfH2
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. |
os-steve
marked this pull request as ready for review
August 23, 2026 21:13
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes#11250
What
inspectDistFreshness()/inspectBundleFreshness()(packages/spec/scripts/lib/dist-freshness.ts)take an arbitrary
pkgDir, but their refusalcausestrings and the printedpnpm --filter PKG buildremedy line hardcodedpackages/spec/@objectstack/specregardless of it.
causestrings now interpolate apackages/NAMEdisplay label derived frompkgDir's own path (packageDirLabel— finds the lastpackagespath segment andtakes the one after it; falls back to the raw
pkgDirwhen the shape doesn't match).pkgDir/package.json#name(packageName— falls backto the same directory label when the file is missing or unparsable), since that's what
pnpm --filteractually resolves against, not the directory label.rerunline (the caller's own re-run command) is unchanged — see "Decisions"below.
Why
Every real caller passed
SPEC_DIRuntil #10969 gavecheck:skill-examplesa secondsurface (
packages/client-react/packages/client), so a stale-dist refusal on thatsurface printed a wrong package name in both diagnostic lines.
Live confirmation (issue comment, 2026-08-23 15:29Z): while working #11026, the
refusal printed
with
packages/spec/distholding 44 fresh.d.tsfiles — the actually-unbuilt packageswere
clientandclient-react(dts=0each). Following the printed remedy(
pnpm --filter @objectstack/spec build) verbatim rebuilds an already-fresh package andreds again identically — the message was not merely mislabelled, it was non-actionable
for the surface it fired on.
Decisions
pkgDir. Both now trace to the realstale package, whichever surface fired.
rerunline at thecheck-skill-examples.tscall site: left as-is. The issue askedme to weigh per-surfacing it.
check-skill-examples.tspasses one fixed'pnpm --filter @objectstack/spec check:skill-examples'for every surface it loopsover — but that command is correct for every surface:
check:skill-examplesitselfis a
packages/specscript that type-checks all three surfaces (skills+docs,packages/spec/src, and the client SDK) in one run, so re-running it is the right fixregardless of which surface's dist was stale. Per-surfacing it would print a command
that doesn't exist (there is no
check:skill-examplesthat runs only the client-SDKsurface). So the printed remedy is actionable as shipped: build the named package, then
re-run the one real gate command.
Tests
dist-freshness.test.ts: updated the two pinned-literal assertions that hardcodedpackages/spectext against the (non-packages/spec-shaped)sandboxfixture toassert against the dynamically-derived label instead, and added a package.json seed to
the one case that needs the build-remedy line to keep naming
@objectstack/spec.Added two new cases:
pkgDir(packages/widgets,package.json#name=@acme/widgets)proving both the cause label and the build-remedy line are genuinely derived, not a
surviving
packages/spechardcode with different test data;packageNamefallback branch (nopackage.jsonat all) falls back to thedirectory label rather than throwing.
dist-freshness-adoption.test.ts(the end-to-end suite coveringcheck:dual-source-exports/check:exported-any/check:skill-examplesagainst realspawned gate runs) is unaffected — every one of its cases exercises
tree.spec, agenuinely
packages/spec-shaped sandbox with a real@objectstack/specpackage.json,so the dynamically-derived label there is correctly
packages/specbefore and afterthis change.
Verification transcript (at
ca8116159855bc936c3b443666bd73caa3653b6e)pnpm --filter @objectstack/spec build— exit 0.pnpm --filter @objectstack/spec exec vitest run scripts/dist-freshness.test.ts scripts/dist-freshness-adoption.test.ts --reporter=verbose --maxWorkers=2— 25/25 passed (15 + 10). Also ran the fullpnpm --filter @objectstack/spec testonce (419 files / 11163 tests, all green) — an accidental over-broad run (a stray--defeated the vitest path filter), kept only as extra confirmation, not the intended scope.packages/spec/scripts/lib/dist-freshness.tschecked out fromorigin/main(pre-patch) and the new/updated test bodies unchanged, 4 tests fail as expected — most tellingly, the non-spec-shaped case fails withexpected '\n❌ packages/spec/dist/**/*.d.ts is O…' to contain 'OLDER than packages/widgets/src', i.e. the pre-patch code reproduces the exact live-confirmed bug (printspackages/specfor apackages/widgetspkgDir). Restored the fix fromHEADafterward and confirmed byte-identity (git hash-objecton the working-tree file equalledgit rev-parse HEAD:plus the path) before re-running the suite green (25/25).node scripts/check-cross-package-test-inputs.mjs --self-test && node scripts/check-cross-package-test-inputs.mjs— both exit 0 (104/104 self-test cases;OK: 14 package(s) … all declared).eslinton both touched files (--no-inline-config --format json) — 0 problems.node scripts/pm/dispatch-gates.mjs(not hand-picked) — 18 path-derived + 4 convention-triggered (test-file-add) local gates identified. Ran all of them: 21 green (check:changeset-gate-self-tests, speccheck:empty-state/check:liveness/check:strictness-ledger/check:variant-docs,check:merge-driver,check:objectui-changeset,check:published-files,check:slot-lookup,check:test-source-alias,check:type-source-resolution,check-adr-0087-registration,check-changeset-no-major,check-ci-filter-parity,check-empty-changeset,check-plugin-teardown-shape,check-affected-docs,check:query-options-erasure,check:type-check-coverage,check:engine-double-contract,check:where-matcher). 2 red for the same declared reason:check-dev-prereqsandcheck:type-check-debt --re-measureboth refuse outright ("NOT MEASURED", not a false verdict) because this worktree has only@objectstack/specbuilt, not the full 67-package closure their measurement needs —check:type-check-debtnames the exact remedy itself:pnpm exec turbo run build --filter='./packages/*' --filter='./packages/*/*'. That full-workspace build is alint.yml-CI-side precondition, not something this diagnostic-text-and-tests-only diff can affect either way; declared here rather than silently skipped.Clause-② confirmed not triggered: diff touches only
packages/spec/scripts/lib/dist-freshness.tsand
packages/spec/scripts/dist-freshness.test.ts— nopackages/spec/src/**, no accept/rejectcontract change, diagnostic text + tests only.
Generated by Claude Code