Skip to content

fix(console,cli): stop printing install instructions for packages nobody can install - #11266

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-10921-out-of-repo-package-names
Aug 23, 2026
Merged

fix(console,cli): stop printing install instructions for packages nobody can install#11266
os-zhuang merged 1 commit into
mainfrom
claude/issue-10921-out-of-repo-package-names

Conversation

@os-zhuang

@os-zhuangos-zhuang commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Fixes#10921

The measurement was re-taken, and it splits the four names 1 / 3 — not 3 / 1

The ruling of 2026-08-22 made this card's first step a measurement. That measurement was re-run here (unauthenticated GET https://registry.npmjs.org/@objectstack%2FPKGNAME), and the registry half reproduces exactly:

nameHTTPdist-tags.latest
@objectstack/framework404
@objectstack/security-enterprise404
@objectstack/organizations404
@objectstack/service-tenant2004.1.0
@objectstack/spec(positive control)20017.1.0
@objectstack/cli(positive control)20017.1.0

⚠️ The strict claim a 404 supports is "not publicly resolvable", never "does not exist" — npm answers 404 for a private package too, and this probe is unauthenticated.

What changes is the reading, not the numbers. The dispatching analysis took the three 404s as three fabricated names. Measured against this tree, they are not one population:

  • @objectstack/framework — fabricated. Nothing in this tree calls it enterprise, cloud, or private. The opposite: packages/console/README.md presents it as the default public install (| Use | … | Default install for @objectstack/framework consumers |). There is no umbrella package, and the real public onboarding path — npx create-objectstack, whose template is packages/create-objectstack/src/templates/blank/package.json — never mentions one.
  • @objectstack/organizations and @objectstack/security-enterprise — real, and deliberately not public. This tree calls them "closed-source" (serve.ts:2576) and "cloud-private" (serve.ts:229, packages/verify/src/harness.ts:44) in roughly a dozen places, one citing cloud#1013. security-enterprise is declared with provenance in PLATFORM_CAPABILITY_PROVIDERS (packages/spec/src/kernel/platform-capabilities.ts) as edition: 'enterprise'. Their 404 is the private-package caveat above, not evidence of fabrication.
  • @objectstack/service-tenant — published at 4.1.0, exactly as platform-object-names.ts describes it. Untouched, as instructed.

On the A/B fork: a roster already exists, so this adds none

The card's option A was "a declared roster, one row per out-of-repo package, with where it ships". That roster is PLATFORM_CAPABILITY_PROVIDERS in packages/spec/src/kernel/platform-capabilities.ts: package + edition (open / enterprise / cloud) + a prose note, drift-tested 1:1 against the capability vocabulary and read by both the CLI preflight and cloud's objectos-runtime. Three out-of-repo packages already have rows.

Adding a second one would be the exact failure that file's header warns about — "A second description nobody checks is how that happens; one exported list is how it stops." So this PR adds no roster, no gate script and no check: alias.

The one real gap — @objectstack/organizations has no row, because the map is keyed by requires token and that package is plugins[]-wired off the tenancy posture — needs a packages/spec/** edit, which was fenced out of this card. Routed to #11263 for the spec seat rather than done here.

What actually changed

packages/console/README.md no longer opens with pnpm add @objectstack/framework. The mechanism it described is real and just misnamed: @objectstack/cli declares @objectstack/console as a dependency (packages/cli/package.json), and both sit in the Changesets fixed group, so any app that installs the CLI already gets a version-matched Console. Corrected rather than deleted — a reader is left with something runnable (npx create-objectstack).

packages/cli/src/utils/console.ts carried the same fabricated name in the resolution-strategy docblock; same correction.

packages/cli/src/commands/serve.ts — the multi-org fail-fast told an operator to add @objectstack/organizations to their app and never said the runtime ships only with an enterprise/cloud subscription. That is the un-followable "add it to your dependencies" that framework#3366 exists to make legible — the boundary platform-capabilities.ts states in its own words. The remedy now says so, so an operator without a licence can see that the two bullets below it are their actual path. The declared-unresolvable branch is untouched (that operator does have the package), and the strings the e2e suite pins — to THIS APP and NODE_PATH — are both preserved verbatim.

What deliberately did NOT change

The test pin at capability-preflight.test.ts is strengthened, not loosened

The card flagged this assertion as the interesting one — it guaranteed we keep printing an install hint for an out-of-repo package. It stays, because the hint is correct; what it lacked was any proof that the hint carries its edition context. It now asserts the message contains the roster's noteverbatim, read from PLATFORM_CAPABILITY_PROVIDERS rather than copied as a literal — a copy here could drift from spec with both sides green.

Ablation, both legs rebuilt-or-argued and confirmed on disk. The subject is imported relatively (../src/utils/capability-preflight.js), and packages/cli/vitest.config.ts aliases only @objectstack/service-cache and create-objectstack — so no exports/dist resolution is involved and the mutation takes effect without a rebuild. (@objectstack/spec/kernel, where the note is read from, does resolve through dist, and was built first.) Replacing const note = p!.note ? … with an empty string:

MUTATION CONFIRMED ON DISK: removed-anchor count 0, injected marker count 1
MUTANT: FAIL enterprise provider hint names plugins[] wiring AND carries the edition boundary
AssertionError: expected 'Capability "hierarchy-security" is pr…' to contain 'ADR-0057 hierarchy scopes ship in the…'
Tests 1 failed | 14 passed (15)
RESTORE CONFIRMED ON DISK: restored-anchor count 1, marker count 0
RESTORED: Tests 15 passed (15)

Predicted direction was RED on that assertion alone; observed exactly that. The script carried a trap … EXIT INT TERM restore.

Verification — all on the final commit ce44f6057

pnpm --filter @objectstack/cli exec vitest run test/capability-preflight.test.ts15 passed (15); pnpm --filter @objectstack/cli typecheck → clean.

Gate families re-derived from the actual diff with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (no paths passed — the script reads its own change set), which added four the dispatch lead did not name, via its convention-triggered bucket. All 21 green, each exit code captured before any pipe:

check:nul-bytes · check:changeset-gate-self-tests · check:objectui-changeset · check:published-files · check:route-envelope · check:slot-lookup · check:test-source-alias · check:type-check-coverage · check:type-source-resolution · check:cross-package-test-inputs · check:query-options-erasure · check:engine-double-contract · check:where-matcher · check:type-check-debt · check-adr-0087-registration · check-changeset-no-major · check-empty-changeset · check-ci-filter-parity · check-plugin-teardown-shape · check-affected-docs · check-published-readme-exports

Quoting each gate's own verdict rather than a bare exit code:

✓ check:published-readme-exports — 60 published document(s) across 78 workspace package(s);
212 import statement(s), 51 workspace type entr(ies), 197/197 @objectstack/ specifier(s)
naming a workspace member.
check-type-check-coverage --re-measure: OK — 33 ledger entr(ies) re-measured in 225.2s,
1897 raw tsc error(s) total, none above its recorded number.
✓ check:published-files — 69 publishable package(s) of 78 workspace member(s) …
✓ No empty-frontmatter changeset introduced by this diff (0 declaring changeset(s) added).
✓ This diff introduces no `major` bump.

check:type-check-debt was run against the built workspace closure (turbo run build --filter=./packages/* --filter=./packages/*/* → 70/70 successful), so its verdict is a measurement, not a refusal.

Repo-wide pnpm lint was narrowed, and the narrowing is measured rather than assumed — three pieces of evidence, all read from the tooling rather than guessed:

  1. The population came from ESLint's own resolution, not from my judgement of "which files count": run over all 5 changed paths, it reported 3 linted and 2 (.md) as "File ignored because no matching configuration was supplied."
  2. Counts read from --format json: 5 results, 0 errors, 0 real warnings.
  3. Invariance for untouched files: eslint.config.mjs states, with its own recorded positive control, that this repo "runs one eslint.config.mjs, which never enables type-aware linting (no parserOptions.project, no typed @typescript-eslint rules) for ANY file" — so nothing in this diff can move the verdict on a file it does not touch.

Findings filed, not fixed

Note for triage: per the ruling's standing execution note, #10920 waits on this same prior fact and is unblocked by what lands here.

ℹ️ Read-path note, corrected: the probe URL above is spelled PKGNAME rather than with an angle-bracket placeholder because an earlier read of this body appeared truncated there. Measured afterwards against the REST API, that was not GitHub's sanitizer — raw storage keeps such fragments intact, and the dispatch comment on #10921 still holds its own angle-bracket placeholders verbatim. What drops them is the MCP issue/PR read path used to review the body. Nothing was lost on write; the plain placeholder is kept only so the URL reads correctly through either path.


Generated by Claude Code


Generated by Claude Code

…ody can install
`@objectstack/framework` is not a real package. Measured against the public npm
registry (unauthenticated, with `@objectstack/spec` and `@objectstack/cli` as
positive controls) it is 404, and unlike the other out-of-repo names in this
tree nothing describes it as enterprise, cloud or private — it is presented as
the default *public* install. There is no umbrella package and there never was.
The mechanism its README described is real, just misnamed: `@objectstack/cli`
declares `@objectstack/console` as a dependency and both ship at one version
from the Changesets `fixed` group, so every app that installs the CLI already
gets a version-matched Console. The instruction is corrected rather than
deleted.
`serve`'s multi-org fail-fast told operators to add `@objectstack/organizations`
to their app without saying the runtime ships only with an enterprise/cloud
subscription — the un-followable "add it to your dependencies" that
framework#3366 exists to make legible. The remedy now states it.
`@objectstack/security-enterprise` is deliberately untouched: it is a real
enterprise package, declared with provenance in PLATFORM_CAPABILITY_PROVIDERS,
and its hint already names the edition boundary. The test pinning that hint is
strengthened — it now asserts the message carries the roster's edition note
verbatim, so the note cannot be stripped while the test stays green.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SPBxLsqQGCVL5z5UXvgipH
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/cli, @objectstack/console, touching 1 documentable anchor(s).

16 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: node scripts/docs-audit/affected-docs.mjs --json e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4.

4 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails.

What this run could not see
  • 2 changed file(s) yielded no anchor (packages/cli/src/utils/console.ts, packages/console/README.md) — pages documenting those are invisible to this run
  • 1 name(s) were too generic to anchor anything (single lowercase words)

Coarse fallback — 28 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 e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4packageMentionDocs.

Which tree this was computed on

This run read content/docs from 5adac686f59476c33480b9b007236ea96fe4f2fe — the merge of head ce44f60579d424787791077601d4a7f2a1a518fc into base e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 5adac686f59476c33480b9b007236ea96fe4f2fe && git checkout 5adac686f59476c33480b9b007236ea96fe4f2fe
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4 ce44f60579d424787791077601d4a7f2a1a518fc && git checkout -B drift-repro e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4 && git merge --no-ff ce44f60579d424787791077601d4a7f2a1a518fc
node scripts/docs-audit/affected-docs.mjs --json e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs e7d2cc67fdef7fee9d2c6d65d7363fe1c78ce6a4 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation tests tooling labels Aug 23, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 23, 2026 07:57
@os-zhuang
os-zhuang added this pull request to the merge queueAug 23, 2026
Merged via the queue into main with commit a2ec377Aug 23, 2026
38 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-10921-out-of-repo-package-names branch August 23, 2026 08:07
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/steststooling

Projects

None yet

2 participants

@os-zhuang@zhuangjianguo