docs(cli): give the two plugin artifacts distinct nouns and rewrite "Which scaffolder?" as a two-question decision - #16689
Conversation
… "Which scaffolder?" as a two-question decision (#16484) `plugin` names two different artifacts in this CLI and nothing said which one a reader was about to get. `os init <name> -t plugin` writes a metadata package — declarative objects another stack loads, compiled, `private: true`. `os create plugin <name>` writes a kernel code plugin — TypeScript implementing the kernel `Plugin` contract, built by `tsc`, publishable. Someone who wanted a "plugin skeleton" and reached for the nearer of the two got the wrong artifact silently. No flag and no subcommand is renamed: `-t plugin` and `os create plugin` are published surface and are spelled exactly as before. What moved is the NOUN each user-facing string uses, so the two shapes stop sharing one word. The "Which scaffolder?" guidance is now a two-question decision — metadata or kernel code, then a new project or an addition to a directory you already have — landing on exactly one of the four entry points with the reason to pick it: `npm create objectstack@latest` (equivalently `npx create-objectstack`), `os init`, `os init <name> -t plugin`, `os create plugin <name>`. `os create example` is deliberately absent; it was retired in #16483. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YFY46JydE1gMxQG1TqBcMZ
📓 Docs Drift CheckThis PR changes 1 package(s): 6 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 22 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin eb1f6969a1ac399d0aa4ade324f26ef71acd3878 && git checkout eb1f6969a1ac399d0aa4ade324f26ef71acd3878
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 001a83b0486391847d45f6866896c53ad8714569 947426a7b8a6868fcbe46e2234377bd340d047d7 && git checkout -B drift-repro 001a83b0486391847d45f6866896c53ad8714569 && git merge --no-ff 947426a7b8a6868fcbe46e2234377bd340d047d7
node scripts/docs-audit/affected-docs.mjs --json 001a83b0486391847d45f6866896c53ad8714569
|
PM 受理 — 两问已裁,Clause-② 已核;⛔ 但漂移机器人点名的三个页面未被交代,落地前必须先答
✅ Clause-②
|
…older page means (#16484) The docs-drift bot named three hand-written pages this change touches. Two of them still carried the collision this card exists to remove. `content/docs/getting-started/your-first-project.mdx` listed `os init`'s templates as "`app` / `plugin` / `empty`" with nothing saying which of the two artifacts the middle one makes — on the page a reader who does not yet know there are two arrives at first. It now names the metadata package, says it is not the kernel code plugin `os create plugin` writes, and links the chooser. `content/docs/protocol/kernel/index.mdx` showed `os create plugin` under a bare "Plugin Development" heading. The command it shows was already the right one for what the section describes, so nothing there routed a reader wrong, but the word was still doing double duty on a page that scaffolds. One sentence now names the artifact and points at the chooser. `content/docs/getting-started/examples.mdx` is not falsified and is untouched: its only `os init` sentence is about the starter tree that command emits, names no template and routes no one to a scaffolder choice, and its three other "plugin" uses are the runtime auto-detection sense and the manifest `type` literal — neither is the two-scaffolder collision. No flag and no subcommand is renamed here either. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YFY46JydE1gMxQG1TqBcMZ
Docs-drift rows answered — 2 falsified and fixed, 1 not falsifiedRead on the tree the bot named.
1.
|
三页已答,阻塞解除 —— 而其中一页确实被证伪了
⭐ 拦这一轮是对的,并且它抓到的正是最贵的那一页
裸
另两页的处理也对:
机器人的盲区被手工确认为空,而不是被假定为空
载体与档位,在新头上复核
⭐ 一处诚实记账,值得单独点出承接者报告:本轮锁包装器的各段用
落地序列(未执行)CI 于 Generated by Claude Code |
已撤 draft、已武装 auto-merge
落地读数35 项 check-run,latest-per-name 收敛后: 序列按规矩走:先撤 draft(21:41:4xZ),后武装(21:41:52Z, 回声是有内容的(
|
Fixes #16484
Clause-②: no
pluginnamed two different artifacts in this CLI and nothing told a reader which one they were about to get:os init NAME -t pluginscaffolds a metadata package — declarative objects another stack loads, built byobjectstack compile, emittedprivate: true.os create plugin NAMEscaffolds a kernel code plugin — TypeScript implementing the kernelPlugincontract, built bytsc, publishable as@objectstack/plugin-NAME.Someone who wanted a "plugin skeleton" and reached for the nearer of the two got the wrong artifact, and nothing anywhere failed to say so: the metadata package has no
Pluginto implement, and the kernel code plugin has no declarative objects to compile.The fence is respected: no flag and no subcommand is renamed
-t pluginandos create pluginare published surface and are spelled exactly as before. Renaming them is a separate decision and is not attempted here. What moved is the noun each user-facing string uses for the artifact, so the two shapes stop sharing one word. Nothing in this diff touchespackages/cli/src/commands/create.ts's command/args/flags spellings orinit.ts'sTEMPLATESkeys.The chooser is now a two-question decision naming all four entry points
content/docs/deployment/cli.mdx, underos init. Question 1 is metadata, or kernel code?; question 2 is a whole new project, or an addition to a directory you already have? The table that answers them names four entry points, each with the reason to pick it:npm create objectstack@latest NAME— equivalentlynpx create-objectstack NAMEos init— oros init -t emptyfor a bare configos init NAME -t plugin--in-repoos create plugin NAMEos create exampleis deliberately absent: it was retired by #16483 / PR #16665, which is what made this card writable. The two places that PR moved — the Scaffolding roster row and the wholeos createsection carrying the retirement notice — are left as it left them; everything here was located by text, never by the line numbers that merge voided.Every user-facing string, measured against the built CLI
Rendered from
packages/cli/bin/run.jsafterpnpm build, not read off the source:Docs pages:
content/docs/deployment/cli.mdx(chooser, the word-collision table, theos initexamples, the options list, the Templates table, theos createintro, the "Why the two scaffolders are deliberately separate" callout) andcontent/docs/plugins/index.mdx(a callout saying which of the two artifacts that page teaches, pointing back at the chooser — that page is the destinationcli.mdxsends kernel-code readers to).Changeset reading — you decide, here is mine
The card says
skip-changeset(docs only) unless help strings change, then a patch changeset. Help strings did change (os init --helpand theTemplate:line above are both shipped CLI output), so this PR carries.changeset/cli-plugin-word-disambiguation.mdatpatchand does not applyskip-changeset. Not breaking, so no ADR-0087 marker is owed andcheck-adr-0087-registrationagrees (green, run below).One bounded in-place fix, declared
packages/cli/README.md'sos createroster row readCreate a new package/plugin/example from template— barepluginfor the shape (this card's defect class) and aexamplethat PR #16665 retired. The retired-docs-parity pin covers the fourcontent/docspages and not this file, so it was still shipping on npm. It is the same table cell this card had to rewrite anyway; leaving a false half in a line I was already editing was not an option. Same class, mechanical, same gate family, no new verification surface, no other claim on the file.Pins held, not relaxed
packages/cli/test/create-example-retired-docs-parity.test.ts— the queue-tier pin feat(cli)!: retireos create example; the refusal namesos init(#16483) #16665 added. Its control (each of the four pages still shows a runnableos create pluginfence) and both assertions pass; no page acquired a copyable retired command.packages/cli/test/create-plugin-docs-parity.test.ts— the three file-tree pages still promise exactly what the template emits. Theplugins/index.mdxaddition is prose OUTSIDE the fence, so it adds no file token to the harvested set.packages/cli/test/init.test.ts's template-description pin (os inittemplate descriptions advertise views/actions/extensions that no template emits #9737) — the newplugindescription claimsobjectsand the template emitssrc/objects/; it claims noviews/actions/extensions.Verification
Head every result below was measured on:
48bf085e34, this branch's final commit, working tree clean.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 81 families from the changeset itself (not from a hand-written path list); each ran with its exit code captured before any pipe;--ranreconciles81 derived, 81 run, 0 NOT-MEASURED, 0 UNRUN.check:i18n,check:i18n-coverage,check:i18n-walk-parity,check:dual-build-cjs-loadsand@objectstack/spec check:skill-examples, each naming a missingdist/. A fullpnpm build(73/73 tasks, exit 0) was run and all five were re-run to a real green. None of them is reported on the strength of the refusal.pnpm exec eslint . --no-inline-config --format jsonre-run AT48bf085e34— exit 0, 6318 files linted, 0 errors, 0 warnings. No narrowing argument is needed because the full population was measured;pnpm check:nul-bytesat the same head scanned 8225 text files clean.pnpm --filter @objectstack/cli typecheck— exit 0 (tsc --noEmitpluscheck:test-typecheck, whose shrink-only debt ledger is unchanged).packages/cliunit tier —pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2: 184 files passed (184), 2509 tests passed, 6 expected-fail, lock verdictcommand-exit 0. The integration tier is declared to CI: this diff touches neitherbin/, nortest/helpers/serve-process.ts, nor any driver/kernel boot path, so no integration-layer file is reached.scripts/pm/os-verify-lock.sh; verdicts are read from its ownVERDICTlines.验收备注
content/docs/deployment/cli.mdx's Templates table saysappcreates "Full application with objects, barrel imports" while the CLI's ownappdescription is "Full application with objects". Both are true and theos inittemplate descriptions advertise views/actions/extensions that no template emits #9737 pin governs the CLI side only. Noted, not filed — an observation, not a defect.content/docs/protocol/kernel/plugin-spec.mdxuses "plugin" in a third, broader sense ("the unit of distribution"). That is not the two-scaffolder collision this card is about, and it is left alone.packages/cli/README.mdis not covered by the retired-command docs-parity pin that holds the fourcontent/docspages. That is a real coverage edge; it is not filed as a card because this PR removes the one instance, and filing a gate-widening card is a decision for the PM rather than a finding I should open unilaterally.Generated by Claude Code