Skip to content

docs(core,rest): the closed-set pins state the durable reason ui-plugin stays refused - #16139

Queued
claude[bot] wants to merge 1 commit into
mainfrom
claude/issue-15640-closed-set-pin-comment
Queued

docs(core,rest): the closed-set pins state the durable reason ui-plugin stays refused#16139
claude[bot] wants to merge 1 commit into
mainfrom
claude/issue-15640-closed-set-pin-comment

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #15640

Both plugin-type-closed-set pins justified their choice of the refused spelling 'ui-plugin' by pointing at something that no longer exists: "the spelling a stale describe() string still uses". PR #15639 corrected the last such .describe() string, so each pin's stated justification read as expired while the pin itself is still correct and still doing real work.

The risk is not that a reader misunderstands what the test does — it is that the sentence states the pin's justification, so a later reader who checks the claim, finds no stale describe anywhere in the tree, and concludes the pin is vestigial may delete a test that is guarding a real contract. This PR replaces the expired reason with the durable one, in both files, so the two parallel texts keep explaining the same pinned value the same way.

The change, in full

packages/core/src/plugin-type-closed-set.test.ts, the comment above the refused-value loop:

         // `'plugin'` / `'module'` are PACKAGE manifest types (ManifestSchema.type),
-        // never plugin types; `'ui-plugin'` is the spelling a stale describe()
-        // string still uses; the casing variant guards against a lax comparator.
+        // never plugin types; `'ui-plugin'` is the LEGACY spelling of today's
+        // `'ui'` — once live, so callers outside this repo may still send it, and
+        // the closed set must keep REFUSING it rather than grow a tolerant alias
+        // (Prime Directive #12); the casing variant guards against a lax comparator.

packages/rest/src/plugin-type-closed-set.pin.test.ts, the @ts-expect-error directive comment:

-            // @ts-expect-error — `'ui-plugin'` (a stale describe() spelling) is
-            // not a `PluginType` (#13925).
+            // @ts-expect-error — `'ui-plugin'` is the LEGACY spelling of today's
+            // `'ui'` — once live, so callers outside this repo may still send it,
+            // and the published union must keep REFUSING it rather than grow a
+            // tolerant alias (Prime Directive #12). Not a `PluginType` (#13925).

The new wording is the durable reason rather than a shorter one: it says what 'ui-plugin' was, why a caller can still send it, and what the pin is therefore protecting — that the closed set keeps refusing it instead of growing a tolerant alias. That last clause is the failure this pin is actually standing in front of, and it does not depend on any describe() string existing anywhere, so it cannot expire the way its predecessor did. The word "legacy" is the tree's own: packages/plugins/plugin-hono-server/src/hono-plugin.ts still carries the comment "Support legacy 'ui-plugin' and new 'ui' type".

What deliberately did NOT change

  • ⛔ The pinned value 'ui-plugin' — unchanged in both files, still refused by PluginSchema and still outside PluginType.
  • ⛔ Every assertion, every fixture, every test name. The diff is 2 files, +8/-4, and every one of those lines starts with //.
  • ⛔ No new assertion was added. A reviewing round on a sibling card suggested converting such a sentence into an assertion over what the system holds; the triage authorisation for this card covers these two comment blocks and nothing else, so that idea is reported to the PM rather than taken unilaterally.

Verification, all at e7ae20930 (this PR's head)

The card's premise, re-measured on this base rather than inherited. Triage read origin/main at 95d5cbb; this branch is cut from 1f2a02ba0. Re-run there: git grep -c "ui-plugin" -- packages/spec/src/kernel/plugin.zod.ts is 0, with the positive control CORE_PLUGIN_TYPES hitting :89 and :123 in that same file, so the zero is a real zero and not an unreadable path. Tree-wide, the only two lines putting ui-plugin and describe together were the two comments this PR rewrites.

Both pin suites green as written — the claim this PR makes is that it changes no semantics, so the suites had to pass unmodified:

  • pnpm --filter @objectstack/core exec vitest run src/plugin-type-closed-set.test.ts — 1 file, 3 tests passed.
  • pnpm --filter @objectstack/rest exec vitest run src/plugin-type-closed-set.pin.test.ts — 1 file, 4 tests passed.

The @ts-expect-error directive is still live, which is the one thing a longer comment block could plausibly have broken (the directive attaches to the next line of code, skipping comment-only lines). pnpm --filter @objectstack/rest typecheck is green, and its test layer reports 0 file(s) / 0 error(s) under the EXACT per-file ratchet — an unattached directive would have surfaced as TS2578 plus the error it stopped suppressing. Measured rather than assumed: tsc -p tsconfig.test.json --listFiles puts this pin file in the program (734 files), resolving @objectstack/core through its built dist/index.d.ts. pnpm --filter @objectstack/core typecheck is likewise green, its 4 test-layer errors being the pre-existing ledgered ones in other files.

Gate union: 45 derived families plus 4 anchor extras, all green at this commit. Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack (which reads the change set from git itself) and run whole — not narrowed on the grounds that the diff is "only comments", because a comment edit moves line numbers and the line-number-anchored census gates are exactly the class that judgement misses. check:system-context-census, check:doc-anchors, check:adr-anchors, check:adr-symbol-anchors and check:scripts-symbol-anchors are all green; no doc anchors point into either edited file. Two families first returned exit 3 PREREQUISITE NOT MET (check:dual-build-cjs-loads, check:type-check-debt) — not a red, nothing measured — and both are green after building the full workspace closure as lint.yml does.

Published surface: unchanged, by ablation. Built at this head, then both edited files swapped back to 1f2a02ba0 content, rebuilt, and all 22 published files of the two packages (dist/** plus README.md and CHANGELOG.md, per each package's files[]) compared by sha256: byte-identical, with the rebuild proven to have really re-run by moved dist mtimes. The files were then restored HEAD-anchored and proven byte-exact against their HEAD blobs. The sourcemap caveat was measured rather than assumed: dist/*.js.map embeds sourcesContent verbatim, and a control confirms it embeds comment text from bundled sources — yet neither map lists any .test.ts among its 59 / 365 sources, and untouched text from each edited file appears in 0 published files. So no text from these files reaches any published artifact, sourcemaps included.

Changeset

This PR carries the skip-changeset label rather than a .changeset/*.md entry, and that is a measurement, not a convention call: the ablation above shows the diff publishes nothing from either released package — both declare files: ["dist","README.md","CHANGELOG.md"], src/**/*.test.ts is excluded from the build config on purpose, and every published byte is identical either side of the change.

Neither edited path is a governed surface, so nothing here is reserved for a maintainer's hand-merge beyond the normal review.

Authorship, stated here in prose because a body edit can drop the footer below: authored by Claude Code in session session_01ARYe3yQTQCUFm5qPYNgKaJ, on branch claude/issue-15640-closed-set-pin-comment, dispatched to the domain:engine execution seat. Card #15638 covers a different residue of the same retired spelling and remains open; triage ruled the two must not be merged, and this PR does not touch it.


Generated by Claude Code

…gin` stays refused

Both `plugin-type-closed-set` pins justified their choice of `'ui-plugin'` by
"the spelling a stale describe() string still uses". No describe string in the
tree uses that spelling any more, so each pin's stated justification read as
expired while the pin itself is still correct and still doing real work — the
failure mode being a later reader who checks the claim, finds nothing, and
deletes a working test as vestigial.

Replaced with the durable reason, identically in both files so the parallel
texts keep explaining the same pinned value the same way: `'ui-plugin'` is the
legacy spelling of today's `'ui'`, callers outside this repo may still send it,
and the closed set must keep refusing it rather than grow a tolerant alias
(Prime Directive #12).

Comment prose only. No assertion, no pinned value and no test semantics change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ARYe3yQTQCUFm5qPYNgKaJ
@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 added the size/s label Sep 6, 2026
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing 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.

What this run could not see
  • 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 — 0 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 932acc3df41e016812cfc17ffe1527fd7b5df538packageMentionDocs.

@claude

claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Out-of-scope finding raised while working this card, filed bare and unassigned rather than fixed here: #16140docs/adr/0026-client-ui-plugin-distribution.md documents a package manifest type: "ui-plugin", a value both ManifestSchema and PluginSchema refuse (measured, with the accepted spelling ui as a firing control on the same instrument).

It is the same family as this PR but deliberately not part of it: different file, outside this card's two-comment authorisation, and docs/adr/** is a governed surface whose changes are merged by the maintainer. #16140 remains open for triage; nothing in this PR depends on it.


Generated by Claude Code

@zhuangjianguo
zhuangjianguo marked this pull request as ready for review September 6, 2026 04:00
@zhuangjianguo
zhuangjianguo added this pull request to the merge queue Sep 6, 2026
Any commits made after this event will not be merged.
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

1 participant