fix(docs): plugin-spec's package.json example silently installs a 2.x CLI — both @objectstack/* ranges repaired to ^17.0.0 - #18186
Merged
Conversation
…t `^2.0.0`, a range today's 17.4.0 cannot satisfy `content/docs/protocol/kernel/plugin-spec.mdx`'s published plugin `package.json` example declared `"@objectstack/core": "^2.0.0"` and `"@objectstack/cli": "^2.0.0"`. Both packages publish at `17.4.0`, and `^2.0.0` pins the major, so an author copying the block resolves `2.0.7` — the last 2.x on npm, fifteen majors behind — and then runs the page's own `os plugin build` on a 2.x CLI. Both lines now read `^17.0.0`, matching the repo's two other hand-written carriers (`packages/create-objectstack/src/templates/blank/package.json`, `skills/objectstack-platform/SKILL.md`). The prose under the block already named `SCAFFOLD_TYPESCRIPT_RANGE` as the authority for the `typescript` floor; it now names `getCliVersion()` in the same file as the authority for the `@objectstack/*` ranges, so the page teaches one range style rather than two. Claude-Session: https://claude.ai/code/session_017ef78bLdybu3AffehKkhfk Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Sep 14, 2026
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 free
to 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 #17378
Clause-②: no
This diff is one hand-written docs page. It adds no schema key, no closed-set member, no published export and no registry entry — nothing an author can write gets wider.
The defect
content/docs/protocol/kernel/plugin-spec.mdxpublishes the protocol's own plugin-packagingpackage.jsonexample. Its dependency block declared:Both packages ship at 17.4.0 (
packages/cli/package.json,packages/core/package.json, confirmed against the registry:npm view @objectstack/cli version→17.4.0,dist-tags.latest→17.4.0; same for@objectstack/core). A caret pins the major, so^2.0.0admits no 17.x — the card's arithmetic (17.4.0is not in^2.0.0) holds on today's tree.What an author actually gets — measured, not assumed
The card deliberately did not claim whether a 2.x was ever published, because it does not change the verdict. It is worth recording anyway, because it names the failure mode:
@objectstack/cli— 160 published versions, including2.0.0…2.0.7.@objectstack/core— 157 published versions, including2.0.0…2.0.7.So the block resolves. It is not an install error — it is worse than one: an author copying the page silently installs
@objectstack/cli@2.0.7, fifteen majors behind, and then runs the page's own"package": "os plugin build"script on that 2.x CLI. A failed install is loud; this is quiet.Both packages are public — no
private: true,publishConfig.access: public,files: ["dist", "README.md", "CHANGELOG.md"]— and@objectstack/cliis the right devDependency for this example, since it is the package whosebinprovides theosbinary the block's ownscriptsinvoke.The range chosen, and the reading behind it
^17.0.0— the current major's floor, caret.packages/create-objectstack/src/templates/blank/package.json:26andskills/objectstack-platform/SKILL.md:607, both"@objectstack/cli": "^17.0.0"beside"typescript": "^5.3.0". Picking anything else would make this page the only carrier teaching a third style.packages/cli/src/commands/init.tsresolves every scaffolded@objectstack/*range throughgetCliVersion()/pkgVersion(), which caret-pins to the running CLI's own version, over a comment that states the rule: every@objectstack/*package in this monorepo is published on one shared release version. That is caret-on-the-current-major with a live floor. A hand-written page cannot carry a live floor, so it carries the major's — which is what the two carriers above do.^17.4.0was rejected: it admits exactly the same set for a reader installing today, and rots on every minor release, while^17.0.0only moves when the major does. The page now says so in one sentence so the next reader knows what to update and when.The prose under the block already named
SCAFFOLD_TYPESCRIPT_RANGEas the authority for thetypescriptfloor — the shape #16756 established on the adjacent line. This PR extends the same sentence to namegetCliVersion()for the@objectstack/*ranges, so the page teaches one range style rather than two.⭐ Declared: the fix covers TWO lines in the block, not the one on the card
The card names
@objectstack/cliat what was then line 707.@objectstack/core, one line above inside the samepackage.jsonexample, carried the identical defect —^2.0.0against a published 17.4.0 — and the card's triage comment anticipated exactly this ("a census keyed to one literal repairs one key and leaves its neighbours ... re-derive the whole block against publishable versions").Repairing only the
cliline would have left the block still uninstallable-as-intended, so the ruling's invariant ("the published example resolves to today's line") would not have been restored. Both lines are in the same JSON object, same defect class, same mechanical shape, and no other claim holds that section. Nothing else in the file was touched.⛔ NOT touched — reported, not swept
Five further
^2.0.0occurrences exist on this page. None is the same defect and none was changed:'@objectstack/core': '^2.0.0'dependencies, aRecordof packageId to versionRange resolved by the kernel, not by npm. Different surface, different resolver.'@objectstack/ui': '^2.0.0'peerDependencies, which the page's own callout marks proposal-only ("the schema declares neither, so nothing resolves them").'@objectstack/core': '2.0.0', // Not '^2.0.0'One further finding surfaced while measuring those and is reported, not filed and not fixed:
@objectstack/uireturns 404 from the registry (npm view @objectstack/ui version→E404 ... is not in this registry), so those two manifest lines name a package nobody can install. It sits on a surface the page already labels proposal-only, so it is a different card from this one.Verification
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no path list — derived from git): 40 families, all run, exit codes captured to disk before any pipe. 40/40 exit 0.dispatch-gates --ran→40 derived, 40 run, 0 NOT-MEASURED, 0 UNRUN(a derived zero — every family recorded an exit code and none is 3).exit 3PREREQUISITE NOT MET results (@objectstack/lint,@objectstack/formula,@objectstack/client-reactunbuilt). Those are NOT MEASURED, not failures: the prerequisites were built and the whole sweep was re-derived and re-run. The 40/40 above is that second sweep.scripts/pm/os-verify-lock.sh(slotissue-17378), bothVERDICT command-exit 0.eslint content/docs/protocol/kernel/plugin-spec.mdx --no-inline-config --format json→ exit 0, 1 result entry, 0 errors, 1 warning, and that warning isFile ignored because no matching configuration was supplied.① Population read from eslint's own config: everyfiles:selector ineslint.config.mjsis a TS/JS glob (**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}and narrower);.mdxmatches none, and the programmaticESLint#isPathIgnoredon this path answerstrue. ② Count read from--format json, as above. ③ Invariance:eslint.config.mjsstates, and grep confirms, that no config block setsparserOptions.projectand no typed@typescript-eslintrule is enabled — with type-aware linting off, this diff cannot move the verdict on any untouched file. This PR's eslint result is therefore identical tomain's, by construction.grep -o | wc -lthroughout, each count paired with a firing control: the two replaced literals were1and1before and0and0after, the two single-quoted manifest occurrences stayed2throughout (they must not move), and the card's nonsense probe"@objectstack/zzzz"returns0.grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'→ no match (exit 1), with the class proven to fire on an injected\x01.Build DocsandTest Coreare path-scheduled CI jobs with no local invocation; declared to CI, NOT MEASURED here.Changeset
skip-changeset. Measured on the publish surface rather than asserted:apps/docsisprivate: true, and enumerating thefiles[]array of everypackage.jsonin the workspace finds no published package shipping anycontent/path (firing control on the same probe:packages/cli'sfiles[]reads back["dist","README.md","CHANGELOG.md"], so the probe is reading real arrays). This diff publishes nothing.Acceptance notes
content/docs/protocol/kernel/plugin-spec.mdxis also the subject of docs + scaffold:plugin-spec.mdxstops promising the non-existent@objectstack/testingand points at@objectstack/verify; thecreate-objectstackblank template ships a test story (epic hotcrm#1579, step 5b) #15952 (pm:epic, reserved). That card edits a later section of the page; this change is confined to the npmpackage.jsonexample and the paragraph immediately under it.@objectstack/*version range incontent/docs/**is covered by any gate.check:vendor-version-stampsexists and is green, but it does not read these. Successor: none identified; the next author to touch this page has no mechanical signal, which is why this same block drifted twice.Generated by Claude Code