Skip to content

docs(platform-objects): make the vitest alias rationale independent of a suite count - #16188

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-16081-vitest-alias-rationale
Sep 6, 2026
Merged

docs(platform-objects): make the vitest alias rationale independent of a suite count#16188
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-16081-vitest-alias-rationale

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #16081

What was wrong

packages/platform-objects/vitest.config.ts justified its @objectstack/lint alias
with a count:

One entry, for managed-api-method-affordance-sweep.test.ts (#7934) — the only suite
here that imports a sibling package as a VALUE.

That sentence licenses a removal it no longer justifies: a future author trimming test
config on the strength of "the only suite" could delete the entry after deleting or
rewriting one test, and take the other importers down with it. The failure mode is
quiet — the suites resolve to lint/dist instead of lint/src and keep reporting on
build state.

Re-measured on today's main (4e090ecde), by text, not by line number

Value imports of @objectstack/lint under packages/platform-objects4, not 1:

file line imported values
src/managed-api-method-affordance-sweep.test.ts 92 MANAGED_API_METHOD_UNAFFORDABLE, validateManagedApiMethods
src/identity/sys-user-preference.organization-unique.test.ts 4 lintUnscopedDeclaredIndexes, UNIQUE_UNSCOPED_DECLARED_INDEX
src/pages/canonical-expression-envelopes.test.ts 42 auditPageExpressionEnvelopes, renderBareExpressionFindings
src/audit/sys-email.highlight-fields-resolve.test.ts 4 runRuntimeAuthoringRules

Classified, not bare-grepped. Type-only imports are erased before resolution and need no
alias, so counting them would make the correction wrong in the other direction. Both
type-only detectors return 0 inside packages/platform-objects and both fire
elsewhere on the same corpus and the same command — import type at
packages/cli/src/lint/score.ts:20, inline type specifier at
packages/cli/test/authoring-rule-command-parity.test.ts:31. So the 4 are all values.

Pathspec control: plain directory pathspecs throughout (-- packages/platform-objects),
never a **/ glob. The same pathspec reaches 35 suites, 5 of which sit directly in
src/ — including the very file the comment named. That is the file class a **/
pathspec drops silently.

And on the sentence's literal reading — "a sibling package", not just
@objectstack/lint — the count is far higher still: suites here import
@objectstack/spec/* (58 + 22 + 16 + 4 + 2 + 2 + 1 occurrences across its subpaths),
@objectstack/metadata-core (3), @objectstack/formula (2) and @objectstack/core (1)
as values. So the sentence was false on both readings.

The repair, and why this one

Correcting the count is the most brittle fix available — a fifth suite makes it false
again, and the failure is silent. What went stale is the enumeration, so the version that
survives states the mechanism instead: the entry is keyed on the specifier, so it
governs whatever set imports that specifier, and pnpm check:test-source-alias — not a
reading of one test file — is what decides whether the entry may go. A rationale with no
count in it cannot rot the way this one did.

The alias entry itself is untouched, and no test file is touched.

The alias's own necessity — measured, not asserted

The filing card noted the alias's necessity had never been re-measured. It has now been,
by ablation on a committed tree:

  • mutation proven on disk before measuring: whole-line anchor matched exactly once,
    find: /^@objectstack count 1 to 0, injected alias: [], count 1, blob
    44dbdea70 to 5fcc23a2e (not equal to the HEAD blob, so not a no-op edit);
  • with the entry removed, pnpm check:test-source-alias goes red, naming exactly
    @objectstack/platform-objects: NEW unaliased artifact import(s) ... @objectstack/lint.
    That red also proves this package is inside the gate's swept population, so the green
    either side is a statement about this package and not about other ones;
  • restore proven byte-exact in the same shell: blob back to 44dbdea70 and equal to the
    HEAD blob, git diff HEAD empty across the whole tree, git status --porcelain empty,
    the removed text back at count 1 and the injected text at count 0;
  • re-run on the restored tree: green, 72 packages with tests scanned.

Independently, @objectstack/lint's exports["."] resolves to ./dist/index.js, so an
unaliased specifier really does land on the build artifact — the premise the surrounding
paragraphs already state. The alias is load-bearing.

The change is behaviourally inert, and that is measured too

The evaluated config is identical either side of the diff. Loading
vitest.config.ts through tsx at the base commit 4e090ecde and at this head yields
byte-identical normalised objects: test.disableConsoleIntercept: true, one alias entry
with find /^@objectstack\/lint$/ (flags empty) and the same resolved replacement path.
The instrument is proven to discriminate: aimed at a variant whose alias array is emptied,
the same dump differs. So "identical" here is a measurement, not a blind spot.

Verification

  • pnpm --filter @objectstack/platform-objects exec vitest run --maxWorkers=2 at
    b7f516e8b, after building the dependency closure
    (pnpm --filter '@objectstack/platform-objects^...' run build, 8 packages):
    35 test files passed, 528 tests passed. This is the reading that covers the edited
    file, because vitest is what loads it.
  • pnpm --filter @objectstack/platform-objects typecheck (both programs): green — but
    it says nothing about the edited file. tsc --listFiles finds
    vitest.config.ts 0 times in either program (control: src/index.ts appears 1),
    because the package tsconfig is include: ["src/**/*"] and the root tsconfig excludes
    packages entirely. Reported as a coverage fact, not as a pass.
  • Gate family re-derived from the diff with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
    (no hand-built path list): 39 runnable families. 36 of 39 green at b7f516e8b,
    including check:test-source-alias, check:published-files, check:nul-bytes,
    check:i18n-stale-fill, check:system-context-census, check:cross-package-test-inputs,
    check:doc-authoring and both closing-keyword parity runs.
  • The remaining 3 are NOT MEASURED, not passes: check:dts-closure,
    check:dual-build-cjs-loads and check:i18n each exited 3 = PREREQUISITE NOT MET
    in their own words ("nothing was swept", "this is NOT a pass"), because they read a
    built tree this worktree does not have. They are left to CI, which builds. Narrowing
    declared rather than assumed, and this diff is provably outside all three input sets:
    nothing in the repo imports vitest.config.ts (control: app-showcase/vitest.config
    fires 5 times on the same command), it is not among tsup's 11 declared entries, and the
    i18n extract config imports only ../src/**.
  • A line-count-changing edit is not a no-op for a gate that cites a line number, so that
    was checked rather than judged: no file in the tree anchors
    packages/platform-objects/vitest.config.ts:LINE. Control: 35 files under
    content/+docs/ do carry PATH.ts:LINE anchors, so the instrument fires.

Publishing and labels

Clause-2: no. This diff publishes nothing. @objectstack/platform-objects declares
files: ["dist", "README.md", "CHANGELOG.md"]; npm pack --dry-run lists
vitest.config.ts 0 times (control: package.json 1), and check:published-files
states on its pass path that every whitelist "admits no test, test-harness config or
build script". No declaration file, no runtime module and no docs page can move for this
diff. Hence the skip-changeset label rather than a changeset file, per AGENTS.md:
that label is for a diff that publishes nothing from any released package.

Not fixed here, deliberately

The trailing comment in the same file still opens No test block: this package had no vitest config until now, while a test block with disableConsoleIntercept: true sits
at the top of the file, and it claims "this file's only effect the alias above". Same
defect class, different sentence, and outside this card's declared surface — filed
separately rather than ridden in on this PR.


Generated by Claude Code

…f a suite count

The alias comment named `managed-api-method-affordance-sweep.test.ts` (#7934) as
"the only suite here that imports a sibling package as a VALUE". That licensed a
removal it no longer justified: four suites in this package import
`@objectstack/lint` as a value, and on the sentence's literal reading (any
sibling package) the count is far higher still.

Replace the enumeration with the mechanism — the entry is keyed on the
SPECIFIER, so it governs whatever set imports it, and `check:test-source-alias`
is the thing that decides whether the entry may go. A rationale with no count in
it cannot go stale the way this one did.

The alias entry itself is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ARYe3yQTQCUFm5qPYNgKaJ
@github-actions github-actions Bot added the size/s label Sep 6, 2026
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 6, 2026
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 1 changed file(s) yielded no anchor (packages/platform-objects/vitest.config.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/platform-objects/vitest.config.ts) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 2 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 53cf263eb66526474813d623bdcde7fd1de957a7packageMentionDocs.

@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Cross-link: the out-of-scope finding named in this PR's last section is now filed as #16189 — the trailing No test block / this file's only effect the alias comment in the same file. Unassigned and ungraded, with its dedupe controls; deliberately not ridden in on this PR.


Generated by Claude Code

@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Ready to release — held only by a tooling channel, not by anything in this PR

Recording this once rather than leaving the draft state unexplained. All three landing
pre-checks are measured and hold:

condition reading
① in-seat contract review N/A — the card declares Clause-②: no in the fixed spelling
check-clause2-carriers --pair REAL_EXIT=0, run from a worktree at current origin/main, checker blob 751b4a6e
③ every check green 0 failing, 0 running, and the legacy combined status is success (⛔ not a required-checks subset)

⛔ The one remaining step — marking the PR ready for review — is only reachable through the
GitHub MCP channel, which is currently answering "API rate limit already exceeded" for its
own token. That limit is separate from this seat's REST budget (measured: REST core
15000/15000 at the same moment), and PATCH /pulls/{n} {draft:false} over REST is a
silent no-op — it returns 200 with draft still true, verified twice tonight — so
there is no REST substitute and none will be attempted.

⇒ Nothing is wrong with this branch. The PM seat will retry on each check-in until it goes
through. A maintainer who wants it sooner can mark it ready for review directly; the release
conditions above are already satisfied.


Generated by Claude Code

@zhuangjianguo
zhuangjianguo marked this pull request as ready for review September 6, 2026 06:04
@zhuangjianguo
zhuangjianguo added this pull request to the merge queue Sep 6, 2026
Merged via the queue into main with commit cf8cc8c Sep 6, 2026
39 checks passed
@zhuangjianguo
zhuangjianguo deleted the claude/issue-16081-vitest-alias-rationale branch September 6, 2026 06:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate tests

Projects

None yet

2 participants