Skip to content

docs(types): let package.json own the spec floor, and fold the duplicate Links section - #8608

Merged
os-warren merged 1 commit into
mainfrom
claude/issue-8037-types-readme-spec-floor-and-links
Sep 8, 2026
Merged

os-warren merged 1 commit into
mainfrom
claude/issue-8037-types-readme-spec-floor-and-links

Conversation

@os-warren

Copy link
Copy Markdown
Collaborator

Fixes #8037

Two repairs in one file, packages/types/README.md. Triage (comment 5583380673) declined to split them; the whole diff is 4 insertions(+), 7 deletions(-).

1. The protocol floor now names its authority instead of a number

The "Architecture: The Inheritance Chain" diagram named @objectstack/spec (v15.x) as the "Highest Law" while packages/types/package.json declares "@objectstack/spec": "^17.3.0" — so the page told a reader to pin a version this package refuses to install against.

The repair deliberately does not write v17.x. That recreates the identical defect one major later, and the manifest is a moving target by design: scripts/check-spec-range-floors.mjs tightens these floors as symbols land, which is exactly why this range moved from ^17.0.0 (at filing) to ^17.3.0 (at triage) while the card sat open. The diagram now names package.json as the authority and states no version of its own, so the next bump cannot silently falsify it:

@objectstack/spec                   left-arrow The "Highest Law" - Universal protocol. The
                                      required range is declared in package.json,
                                      the authority; a copy here goes stale unnoticed.

(The literal arrow glyph is spelled out above only in this PR description; the file itself carries the same arrow character every other row of the diagram uses, and column alignment at char 36 is preserved.)

Re-derived, not taken on trust

  • Manifest on current main (ce45a03): packages/types/package.json dependencies -> ^17.3.0. It has not moved a third time since triage measured it — the PM brief's assumption (a) is falsified, and the range is unchanged from comment 5583380673.
  • Installed copy in this workspace: @objectstack/spec@17.3.0 (the card recorded 17.2.0 at filing).
  • Sites located by content (git grep 'Highest Law', grep '^## '), per standing ruling objectui#7853, not by the line numbers in the card. They happen to land on the same :32 / :324 / :337 triage recorded, so assumption (b) is falsified too — but the location method is the content search either way.
  • git grep 'v15.x' finds this spelling in exactly one tracked file, so it was one line and not a population. Widening the sweep to any @objectstack/spec vNN claim in markdown returns only CHANGELOG / ROADMAP / changeset entries, which are dated historical records rather than current claims. Triage's p2 re-grade trigger therefore does not fire; the grade stays p3.

2. One ## Links section, on the host this package itself declares

The page carried two ## Links sections with ## License between them, disagreeing on host. They are folded into one, in the first position.

Which host is canonical was re-derived rather than assumed. The repo states no canonical-host rule anywhere — there is no lychee or site setting for it — so the evidence is:

evidence reading
packages/types/package.json "homepage" https://www.objectui.org/docs/api/schema-reference — this package's own manifest names the www. form of exactly the Documentation URL the two sections disagreed about
root package.json "homepage" https://www.objectui.org
repo-wide count 141 occurrences of https://www.objectui.org against 21 without www.

So the first section (already www.) stays and the second is deleted. Its one entry the first section did not already carry — the repository root link — is kept as a new bullet, so the merge loses nothing. Nothing in the tree references either heading anchor (git grep 'types/README.md#' is empty), so deleting the second heading breaks no link.

check-doc-links.mjs was green over both spellings because it judges reachability, not canonicity; that is unchanged and not something this PR alters.

Verification

Gates derived from the repo's own package.json check:* scripts and every .github/workflows/*.yml trigger block, against the actual changed path. Exit codes captured before any pipe (cmd redirected-to file; EXIT=$?).

Which workflows this diff actually reaches. lint.yml and ci.yml both gate their expensive steps on a Decide whether this change needs a full run step whose diff excludes **/*.md; ci.yml's docs job gates on apps/site/ and content/ only. A README-only PR therefore reports those contexts green having run nothing in them, and the gates that really judge it are the unconditional per-gate workflows.

Ran on the final commit 76a9175, all exit 0:

check-doc-links, check-doc-fence-languages (+ --self-test), check-control-bytes, check-shell-escape-residue, check-changeset-presence, check-action-ref-convention, check-doc-component-types, check-docs-route-eager-closure, check-pre-install-import-graph (+ --self-test), check-skill-eval-tokens (+ --self-test), check-skills-paths, check-vi-mock-specifiers, check-vi-mock-inherit, check-changeset-fixed, check-doc-expression-carriage, and check-governed-queue-guard --test packages/types/README.md (which answers NOT GOVERNED).

Declared narrowing — two gates that read package READMEs were not run to a verdict locally, because both need a whole-tree dist/ this container has not built (check-readme-exports wants all 40 ./packages/* built; check-doc-snippet-types wants the 34-package closure its --build-filter names). Both are unconditional on this PR, so CI runs them. In their place, three measurements show their input is unchanged rather than assuming it:

  1. Population read from the gate's own code, not guessed. analyze() from check-doc-snippet-types.mjs reports 244 documents, 240 covered, and packages/types/README.md is in the covered set — it has left UNGATED_DOCS. Its own scanFences() returns 7 blocks for this file before the edit and 7 after, every one typescript, at fence lines [58,85,108,219,236,250,271] -> [60,87,110,221,238,252,273]. The edited diagram fence is not among them: it carries no language, so the scanner never returns it. That is fence 2 of the triage comment, measured — leaving the ledger did not make line 32 watched.
  2. The compilable corpus is byte-identical. sha256 over every language-tagged fenced block of the file: f9f0949bda14ba2e3dbb9067d571d5601da7a3b007d0b69adbf76cc9e02c8128 before and after. Block counts 9 total / 8 tagged / 1 untagged, unchanged; the single untagged block contains no import line.
  3. The shipped gate says so itself. check-readme-exports.mjs run twice in the same unbuilt state, once with --readme pointing this path at the PRE-EDIT copy (spelled without angle brackets on purpose: GitHub's body sanitizer eats tag-shaped fragments, backticks included), prints a byte-identical census both times — 408 fenced block(s) (308 parsed as code, 6 untagged); 751 import binding(s) — and the only difference in the entire run output is the +2 line-number shift on the same 19 findings for this file, in the same order, with the same symbols. Both legs share the same pre-existing 36 unbuilt prerequisite, which CI's build step satisfies.

Also self-scanned for control bytes beyond the gate: grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]' packages/types/README.md returns nothing (exit 1).

Changeset decision: none, deliberately

README.md is published — it is listed in packages/types/package.json files[], so it ships in the tarball. It still owes no changeset, and that is the repo's own rule rather than a judgement call. scripts/check-changeset-presence.mjs is the authority AGENTS.md names, its header subtracts "documentation and licences (*.md, LICENSE*), which do ship in the tarball but are not behaviour", and run against this working tree it prints:

Compared the working tree with ce45a03 (merge-base with origin/main): 1 file(s) changed, 0 of them published source of a package the release covers, 0 of them a manifest whose published contract moved, 0 under a package changesets ignores, 0 changeset(s) added.
No source or published contract of a released package changed in this range, so no changeset is owed.

Stated plainly so nobody has to re-derive it: this repo does not cut a release for a README-only change, so the corrected page reaches npm with the next release of @object-ui/types for some other reason. Adding an empty-frontmatter changeset would also have breached this dispatch's one-file surface, and empty frontmatter is for declining a release the gate demands — which it does not here.

Acceptance notes (out of scope, noted and not filed)

  • Gate-scope question, left where triage put it. Whether doc-version-claims' scan should reach unlabelled fenced blocks is that gate owner's decision with its own false-positive budget (triage fence 1). Not filed and not ridden in here. Taker: the scripts/__tests__/doc-version-claims.test.ts owner, whenever they next widen that scan.
  • The bare-host spelling is a small population, not just this page. https://objectui.org/... without www. also appears in packages/app-shell/README.md (1), packages/components/README.md (2), packages/core/README.md (1), packages/react/README.md (2) and apps/console/src/sdui-tiers-preview.tsx (1). Hits in scripts/__tests__/check-doc-links.test.ts and packages/sdui-parser/src/__tests__/inline-whitespace.test.tsx are deliberate fixtures. This is presentation with every URL resolving, so it is none of the three filing classes; noted rather than filed, and out of this card's one-file surface. Taker: none today.

Draft on purpose: not enqueued, no auto-merge, no self-approval.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Jmxdo7bmeqCQHLSfmLVX9w


Generated by Claude Code

…ate Links section (objectui#8037)

The architecture diagram named `@objectstack/spec (v15.x)` as the "Highest
Law" while `packages/types/package.json` declares `^17.3.0`, so the page told
a reader to pin a version this package refuses to install against.

The repair does not write `v17.x`: that recreates the identical defect one
major later, and the manifest is a moving target by design --
`scripts/check-spec-range-floors.mjs` tightens these floors as symbols land
(it is why this one already moved `^17.0.0` -> `^17.3.0` while the card was
open). The diagram now names `package.json` as the authority and carries no
version of its own, so the next bump cannot silently falsify it.

Second repair: the page carried two `## Links` sections separated by
`## License`, disagreeing on host -- `https://www.objectui.org/...` against
`https://objectui.org/...`. The `www.` form is this package's own stated
homepage (`packages/types/package.json` "homepage" is exactly that
Documentation URL) and the repo's dominant spelling, so the first section
stays and the second is deleted, keeping its one unique entry (the repository
root link) as a new bullet. Nothing links to either anchor.

Neither item is reachable by a gate: line 32 sits in an unlabelled fenced
diagram, which `check-doc-snippet-types.mjs` does not see even though the
page has left its `UNGATED_DOCS` ledger, and `check-doc-links.mjs` judges
reachability rather than canonicity.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jmxdo7bmeqCQHLSfmLVX9w
@github-actions github-actions Bot added documentation Improvements or additions to documentation package: types labels Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3476.3 KB 3512.7 KB
Main entry chunk (gzip) 143.9 KB 350 KB
Entry file index-CFuSIsFQ.js —
Status PASS —

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 498.93KB 114.12KB
core (index.js) 7.48KB 2.96KB
create-plugin (index.js) 10.12KB 3.28KB
data-objectstack (index.js) 192.72KB 53.55KB
fields (index.js) 243.74KB 61.55KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 6.57KB 2.76KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 15.16KB 3.68KB
plugin-calendar (index.js) 49.00KB 13.91KB
plugin-charts (index.js) 71.39KB 19.92KB
plugin-chatbot (index.js) 194.53KB 46.34KB
plugin-dashboard (index.js) 131.43KB 34.44KB
plugin-designer (index.js) 213.21KB 43.63KB
plugin-detail (index.js) 250.72KB 64.81KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.30KB 56.63KB
plugin-kanban (index.js) 55.44KB 15.73KB
plugin-list (index.js) 112.74KB 27.70KB
plugin-map (index.js) 20.49KB 6.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 30.10KB 8.74KB
plugin-tree (index.js) 9.33KB 3.25KB
plugin-view (index.js) 84.54KB 20.84KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.55KB 2.45KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 13.64KB 4.59KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@os-warren
os-warren marked this pull request as ready for review September 8, 2026 16:18
@os-warren
os-warren added this pull request to the merge queue Sep 8, 2026
Merged via the queue into main with commit 52bc1f8 Sep 8, 2026
32 checks passed
@os-warren
os-warren deleted the claude/issue-8037-types-readme-spec-floor-and-links branch September 8, 2026 16:35
os-justin pushed a commit that referenced this pull request Sep 8, 2026
Second sync during the same run: #8601, #8607 and #8608 landed while this
branch was being re-verified. None of them touches
`packages/types/src/__tests__/zod-mirror-parity.test.ts`, so this merge is
clean; #8601 does move a DECLARATION the parity ledger reads
(`packages/types/src/record-components.ts`), which is why the branch is
re-measured on top of it rather than left behind.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YBWFb5YgMU5dw8p2VKj16S
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation package: types

Projects

None yet

Development

Successfully merging this pull request may close these issues.

packages/types/README.md names @objectstack/spec v15.x against a ^17.0.0 manifest, and carries two divergent Links sections

2 participants