Skip to content

fix(cli): retire generate --from, a declared flag whose no-op exited 0 (objectui#11488) - #11495

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-11488-retire-generate-from
Oct 2, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-11488-retire-generate-from

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #11488

Clause-②: yes

What

objectui generate declared --from SOURCE ("Generate schema from external source (openapi.yaml, prisma.schema)"), and the CLI docs listed it as experimental. Its action branch printed "not yet implemented", exited 0 and wrote nothing, so a script or CI step read the no-op as success. Triage ruled it retired at once, with no placeholder and no alias (ruling comment 5957399263 on the card), on the precedent of --output (objectui#11476, PR objectui#11487). This PR is the same move for --from:

  • packages/cli/src/cli.ts: removes the --from option line from the generate command, and the options.from branch, which nothing can reach once the option is gone. The action now takes (type, name) only.
  • content/docs/utilities/cli.mdx: --from was the last row of the generate flag table, so the whole table goes (header, separator and row). The section now reads like the other flagless commands (add, doctor): the heading objectui generate TYPE NAME (alias g), "Generate new resources.", and the three-line example block. That matches what objectui generate --help prints today: the two arguments and -h, --help, nothing else. Only that table is touched, region-disjoint from draft PR objectui#11069, which edits the validate and check sections of the same file.
  • packages/cli/src/__tests__/cli-bin.test.ts: the generate row of "flag contracts (locked-in by docs)" now asserts the documented positional arguments (TYPE NAME in the usage line), since it has no documented flag left. The objectui#11476 pins are extended to --from (see Pins).
  • .changeset/11488-retire-generate-from.md: @object-ui/cli minor, BREAKING banner, a FROM → TO line, a Clause-② line.

No new refusal code was needed. The program sets no allowUnknownOption, passThroughOptions or allowExcessArguments (a grep of cli.ts for those three spellings exits 1; allowUnknownOption alone has 4 hits in commander's own lib/command.js, so the pattern is live). Measured on the BASE build before any edit: g page Probe --bogus openapi.yaml exits 1 with error: unknown option '--bogus' and writes nothing, and g page Probe --from openapi.yaml exits 0, prints the two "not yet implemented" lines and writes nothing (the card's reproduction, confirmed).

Serial: PR objectui#11487 (objectui#11476) landed as 9de0b3483, which is this branch's base.

Contract notes

  • The accept set narrows (Clause-② yes). The published objectui bin's generate command no longer accepts --from. FROM objectui generate TYPE NAME --from SOURCE (exit 0, "not yet implemented", nothing written) TO a non-zero exit with commander's unknown-option error and nothing written. No alias, no deprecation window, no placeholder that exits non-zero, and no silent accept.
  • Nothing replaces it. No OpenAPI or Prisma importer exists, so the FROM → TO line says "drop the flag". Triage measured no producer of the flag and ruled the importer a new capability with no pull.
  • Unchanged. Without the flag, generate writes exactly where it wrote before: pages/NAME.json for a page, objects/NAME.json for an object, plugins/NAME/ for a plugin. generate.ts is not edited. No exported symbol of @object-ui/cli moves, because cli.ts is the bin entry and not part of the package's exports.
  • Readers enumerated at BASE with git grep -n -- '--from' and git grep -n -i 'not yet implemented' over packages/cli, content/docs, packages/*/README.md, scripts and examples. The generate hits are the four this PR edits (the option, the branch's message, the docs row, the two test lines). The other hits are unrelated spellings and are left alone: the Dockerfile COPY --from=builder line in content/docs/guide/deployment.md, the --from claims.json flag of scripts/render-changeset-claims-comment.mjs and its test, and the ObjectMap "API provider not yet implemented" sentence in content/docs/plugins/plugin-map.mdx. packages/cli/README.md documents generate without flags and needs no change.

Pins

They live in packages/cli/src/__tests__/cli-bin.test.ts and run through the built dist/cli.js, in the describe now titled generate refuses its retired flags (objectui#11476, objectui#11488):

  1. exits non-zero naming %s as an unknown option, and writes nothing, an it.each over --output custom/ and --from openapi.yaml. Each case runs g page Probe FLAG VALUE in an empty temp directory and asserts a non-zero exit, that stderr names the kind (unknown option) and the flag, and that the directory stays empty. The --output case keeps the exact test name objectui#11476 gave it.
  2. still writes pages/NAME.json when the flag is absent: unchanged. It is the control both refusals are read against.
  3. lists neither --output nor --from in generate --help (was does not list --output in generate --help). Its lit control used to be "--from SOURCE is listed", which this PR makes false, so the control moved to generate's own usage line (objectui generate|g … TYPE NAME).

Reverse verification

I wrote each prediction down before its run.

  • BASE leg. The new pins ran against the dist built from BASE 9de0b3483, before the fix was built. Predicted: the --from refusal case and the help pin red, everything else green, Tests 2 failed | 42 passed (44). Observed: Tests 2 failed | 42 passed (44). The refusal case failed on expected +0 not to be +0; the help pin failed on expected 'Usage: objectui generate|g [options] …' not to match /--from\b/.
  • Ablation. The fix was committed first, as 5d1d51704. The option line and its branch were then planted back through objectstack's scripts/ablation-replace.mjs in wrap mode, inside a script that also carries its own trap restore on an absolute path. Anchor x1 -> x0, replacement x0 -> x1, blob ab22eb7e6fa6 -> 6b9bbbbf7eb6, which is byte-for-byte the BASE blob of cli.ts. Mutant source carried the option spelling once; the CLI was rebuilt; the mutant dist/cli.js carried it once too. Predicted the same two reds. Observed: Tests 2 failed | 42 passed (44), on the same two names.
  • Restore. The tool restored with git checkout HEAD -- on the absolute path: blob after restore ab22eb7e6fa6 equals the HEAD blob, git diff HEAD is empty, git status --porcelain is empty. The CLI was rebuilt; the restored dist/cli.js carries the option spelling 0 times; Tests 44 passed (44).
  • objectstack's ablation-dist-preflight.mjs is rooted in the objectstack tree, so the dist side was proven by hand: a grep -c of the option spelling in packages/cli/dist/cli.js on each leg (BASE 1, mutant 1, fix and restore 0).

Tests and gates

Everything below ran on final head 5d1d51704.

  • pnpm --filter @object-ui/cli build: exit 0. The dist carries 0 hits of the --from SOURCE spelling and 0 of "not yet implemented", against 2 for the --watch control.
  • pnpm --filter @object-ui/cli type-check (tsc --noEmit): exit 0. --listFiles shows it covers both cli.ts and cli-bin.test.ts.
  • pnpm exec vitest run packages/cli/ plus the four cross-package readers of cli.mdx or of the generator (page-node-headings-drawn-11436, toc-anchor-parity, nested-page-children-11223, body-dialect-census): Test Files 28 passed (28), Tests 498 passed (498).
  • The card's reproduction on the built CLI: node packages/cli/dist/cli.js g page Probe --from openapi.yaml exits 1 with error: unknown option '--from', and the directory stays empty. The same command without the flag exits 0 and writes pages/probe.json.
  • pnpm docs:check-links: Links are valid across 17 scan roots.
  • pnpm check:doc-fences: ✅
  • node scripts/markdown-test-inputs.mjs --audit: 115 candidate test files, all adjudicated; 82 declared entries, all present.
  • pnpm check:control-bytes: ✅ OK. A self-scan of the four edited files for control bytes also comes back empty.
  • pnpm check:new-line-citations: VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only -> exit 0
  • node scripts/check-changeset-presence.mjs: ✅. check-changeset-no-major.mjs: ✅. check-changeset-overwrite.mjs: ✅
  • pnpm check:changeset-claims (report-only): two pending changesets name a file this change touches. 7658-toc-code-span-anchor-parity names cli.mdx for its headings, and this PR moves no heading. 7694-chart-series-chart-type-alias-refusal names cli.ts as the home of objectui validate, which it still is. I re-read both paragraphs, and both are still true.
  • check-doc-component-types.mjs, check-doc-example-ids.mjs, check-shell-escape-residue.mjs, check-test-path-roots.mjs, check-vi-mock-override-shape.mjs: ✅
  • node scripts/check-governed-queue-guard.mjs --test over the four paths: NOT GOVERNED.
  • ESLint, as a proved narrowing. ① Population: CI lints this package through turbo run lint, which runs @object-ui/cli's eslint src against the root eslint.config.js (the package has no config of its own). I ran that same eslint src. ② --format json counts 51 files linted, equal to the 51 tracked ts/js files under packages/cli/src. It reports 0 errors and 5 warnings, all in untouched files; both edited files read 0/0. ③ Invariance: the config enables no type-aware linting (no parserOptions, project or projectService) and no import plugin, and no rule under eslint-rules/ reads the filesystem. So this diff cannot move a verdict on a file it does not touch. cli.mdx and the changeset sit outside every package's eslint src. The repo-wide pnpm lint is left to CI.
  • NOT MEASURED: check-doc-snippet-types, reason: it exits 2 (PRECONDITION NOT MET, the 34 packages its snippets import are not built in this worktree). The docs edit removes one table and touches no fenced block, so the gate reads no changed input. CI runs it. The full pnpm test is CI's as well.

Acceptance notes

  • Same family, a different command, measured on this branch's built CLI: objectui add Input prints "Feature not implemented yet.", exits 0 and writes nothing, while the docs say it adds "a new component renderer scaffold to your project". It is left untouched here and reported to the dispatching seat.

Implemented by the os-dev agent dispatched by the domain:ui seat 1 PM, session https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37.


Generated by Claude Code

…d 0 (objectui#11488)

`objectui generate` declared `--from <source>` ("Generate schema from
external source (openapi.yaml, prisma.schema)") and the CLI docs listed
it as experimental. Its branch printed "not yet implemented", exited 0
and wrote nothing, so a script read the no-op as success. Triage ruled
it retired at once, on the precedent of `--output` (objectui#11476).

- cli.ts: drop the option and its unreachable `options.from` branch;
  commander's default unknown-option refusal now applies.
- cli.mdx: drop the generate flag table, whose last row it was.
- cli-bin.test.ts: the documented-flags row for generate now asserts
  its positional arguments; the built-CLI refusal pin covers --from
  next to --output, and the help pin asserts neither is listed.
- changeset: @object-ui/cli minor, BREAKING, FROM -> TO, Clause-②.

Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests package: cli labels Oct 2, 2026
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 2 pending changeset(s) describe a file this change touches

Their bodies publish verbatim into the CHANGELOG at the next release, so this is a request to re-read them against your diff — addressed here because you are the one seat that can answer it without re-deriving anything.

⛔ Nothing here blocks, and nothing here is a verdict on your change. This gate exits 0, is not a required context, and judges name resolution, never meaning: it asked whether a pending body names a file you touched. "Is this sentence still true?" is the one question it will not answer, and the one you are being asked to answer.

.changeset/7658-toc-code-span-anchor-parity.md

  • names content/docs/utilities/cli.mdx → content/docs/utilities/cli.mdx — edited by this change

    Seven live headings in this repo's own docs were affected (content/docs/utilities/cli.mdx, content/docs/utilities/runner.mdx, packages/cli/README.md). Pinned against the real render pipeline rather than a second derivation of the slug rules: the new test renders each heading through MarkdownImpl and compares extractToc's id to the id attribute rehype-slug actually emitted.

.changeset/7694-chart-series-chart-type-alias-refusal.md

  • names packages/cli/src/cli.ts → packages/cli/src/cli.ts — edited by this change

    • Before: series: [{ name: 'revenue', chartType: 'line' }] validated green through @object-ui/types/zod (safeValidateSchema, objectui check / objectui validate, any pipeline that keeps parse()'s output) — and the key was gone from the output, so a consumer of the parse result drew that series in the chart's own family, precisely what the author was overriding. On the TypeScript face the key was merely an excess property on a fresh literal; a widened object carrying it assigned structurally. - After: the same document REFUSES at series[i].chartType (issue code invalid_type) with one message on both channels — the parse-time issue and the .describe() metadata: Unrecognized key(s) on this chart series: \chartType`. Did you mean `chartType` → `type`? …followed by the reason and the remedy. Writetype: 'bar' | 'line' | 'area'. On the TypeScript face ChartDataSeries.chartTypeis a?: nevertombstone, so both the fresh literal and the widened assignment aretsc errors. - **Both written** ({ type: 'bar', chartType: 'line' }) is refused at chartTypealone — the key is not folded ontotypeand no precedence is minted between the two spellings. - **Which documents to scan.** The narrowing does not stop atChartDataSeriesSchema; it reaches every document through the parents that embed it — ChartSchema.series (zod/data-display.zod.ts, z.array(ChartDataSeriesSchema)) and, one level further out, ReportSectionSchema.chart (zod/reports.zod.ts, ChartSchema.optional()). Authors meet it through safeValidateSchema() (zod/index.zod.ts, which parses AnyComponentSchema) and through the CLI's objectui validate command (packages/cli/src/cli.ts). In practice: every chartnode'sseries[], and every report section whose chart` carries one.

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Compared the checked-out tree with 9de0b3483 (merge-base with origin/main): 3 file(s) changed outside .changeset/, read against 2031 pending declaration(s) that publish a body (2660 pending in total). · run

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3550.7 KB 3574.6 KB
Main entry chunk (gzip) 150.4 KB 350 KB
Entry file index-CmM6RpAi.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) 16.88KB 6.25KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.17KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
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) 27.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 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) 569.83KB 136.77KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 230.46KB 63.94KB
fields (index.js) 261.25KB 66.11KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.49KB 9.23KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 39.36KB 11.18KB
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) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
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) 16.04KB 3.92KB
plugin-calendar (index.js) 53.17KB 15.46KB
plugin-charts (index.js) 83.53KB 22.84KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 141.23KB 38.00KB
plugin-designer (index.js) 231.28KB 48.76KB
plugin-detail (index.js) 245.27KB 64.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 172.73KB 44.50KB
plugin-gantt (index.js) 179.14KB 45.06KB
plugin-grid (index.js) 232.66KB 63.77KB
plugin-kanban (index.js) 49.51KB 15.54KB
plugin-list (index.js) 116.60KB 28.96KB
plugin-map (index.js) 25.60KB 8.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 38.80KB 11.71KB
plugin-tree (index.js) 14.51KB 5.15KB
plugin-view (index.js) 90.23KB 22.73KB
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.81KB 3.58KB
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) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.06KB 2.68KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 21.42KB 7.05KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 3.32KB 1.64KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
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) 5.07KB 2.39KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
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) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.25KB
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

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 5d1d517045741ea7279179ffa0ca87b8de99866a
Local-runs: none
Rendered: 2026-10-02T18:00Z

PR objectui#11495 (card objectui#11488), judged against triage's ruling 5957399263 ("Ruling: retire", on objectui#11476's precedent; PR objectui#11487 and its contract record 5957439389 are that precedent). Read for this record: the card body and all four comments on it; the PR body and its 4-file list; the net diff of the head against main (merge-base 9de0b3483..head, +38 / −27 over .changeset/11488-retire-generate-from.md, content/docs/utilities/cli.mdx, packages/cli/src/__tests__/cli-bin.test.ts, packages/cli/src/cli.ts; main has since moved one commit to f560ded15, and its diff over those paths and packages/cli is empty); and the check-runs on the head, polled at one-minute intervals until every run had completed. Nothing was built, run or re-run locally: the dev's reverse-verification legs are read as reported, and the head's own check-runs are the gate verdicts. Spellings with angle brackets are written here as TYPE NAME and --from SOURCE.

① Derived judgments

  1. The published bin's accept set narrows — right. objectui generate (alias g) no longer declares --from SOURCE. At the head, packages/cli/src sets no allowUnknownOption, passThroughOptions, allowExcessArguments, enablePositionalOptions or exitOverride (grep: none), and the CLI runs commander ^15, whose default refuses an undeclared option with error: unknown option '--from' and a non-zero exit before the action runs. So the retirement is a refusal, not a silent accept, and nothing is written — the ruling's shape. No bespoke refusal branch was needed, and none was added.
  2. The no-op branch goes with the option, and nothing stands in for it — right. The options.from branch (two console lines and process.exit(0)) is deleted, the action now takes (type, name) only, and no .option with another spelling appears. That satisfies the ruling's two ⛔ clauses: no placeholder kept (a placeholder exiting non-zero would still be a declared flag that does nothing), no alias. chalk is still read 17 times in cli.ts, so the deletion strands no import; the narrowed action signature is type-safe against commander's extra arguments (judged by Type Check, tally below).
  3. generate --help narrows, and the docs-to-bin lock stays consistent — right. --from leaves the help text. The generate row of "flag contracts (locked-in by docs)" in cli-bin.test.ts now asserts the positional arguments TYPE NAME in the usage line, since the command has no documented flag left. The objectui#11476 help pin's lit control used to be "--from SOURCE is listed", which this diff makes false; it moved to generate's own usage line (objectui generate|g … TYPE NAME), so the pin still proves it read generate's help and not some other command's.
  4. The docs surface narrows — right, and the whole-table removal is the correct unit. --from was the only row of the generate flag table in content/docs/utilities/cli.mdx (the diff shows header, separator and that one row, nothing else), so the ruling's "its docs row" leaves no table behind; an orphaned header would have been the wrong shape. The section now reads as add and doctor do (heading, one sentence, example block), and it matches what generate --help prints: two arguments and -h, --help. No heading in cli.mdx moves (the heading list at main and at the head is identical). packages/cli/README.md documents generate without a flag table and needs no change.
  5. No reader is left dangling — right. At the head, git grep -- '--from' over the whole tree finds, besides this PR's changeset and pins, only the objectstack CLI's os migrate meta --from N prescriptions in changelogs and messages, the Dockerfile COPY --from=builder line in content/docs/guide/deployment.md, and the --from claims.json flag of scripts/render-changeset-claims-comment.mjs (and its workflow and test). None passes --from to objectui generate. git grep -i 'not yet implemented' finds only the plugin-map / plugin-calendar / plugin-gantt API-provider warnings and a plugin-form test comment; openapi.yaml / prisma.schema survive only in the changeset and the it.each case. No skill, example, workflow or README is affected.
  6. Where generate writes is unchanged — right. packages/cli/src/commands/generate.ts is not in the diff (its diff against main is empty); it still writes objects/NAME.json, pages/NAME.json and plugins/NAME/index.ts under the current directory. The control pin still writes pages/NAME.json when the flag is absent is unchanged, which is the ruling's second pin (g page Probe is unchanged).
  7. No programmatic export moves — right. @object-ui/cli's exports is ./dist/index.js, which re-exports serve and init only; cli.ts is the bin entry (tsup builds cli and index as separate entries). package.json is not in the diff. The "no exported symbol moves" sentence in the PR body and the changeset holds.
  8. The pins pin the ruling, through the built bin — right. Under generate refuses its retired flags (objectui#11476, objectui#11488): the refusal is an it.each over --output custom/ and --from openapi.yaml (exit non-zero, stderr matches unknown option and contains the flag, the work directory stays empty); the %s rendering keeps the --output case's name byte-identical to the one objectui#11476 gave it; the control (exit 0, exact tree pages, pages/probe.json) is untouched; the help pin asserts neither --output nor --from is listed. They spawn dist/cli.js as a child process, where the card measured the defect. The dev's reverse verification is read, not re-run: BASE dist 2 failed / 42 passed on the two predicted names; the ablation re-planted the BASE blob of cli.ts (the diff's own index line, 6b9bbbbf7..ab22eb7e6, names the same two blobs the dev reports) and failed the same two; restored, 44 passed. cli-bin.test.ts is a *.test.ts file, not in the dist project (whose glob is packages/*/src/**/*.dist.spec.tsx), so the pins are judged by the eight Test (shard N/8) runs on the head (tally below).
  9. Serial and base — right. The merge-base 9de0b3483 IS the landing commit of PR objectui#11487 (objectui#11476), the ruling's named predecessor, and it is an ancestor of main. main has moved one commit past it (f560ded15, PR objectui#11490, percent faces); git diff --stat of that movement over packages/cli, cli.mdx and the new changeset is empty, so not merging main was right, and current main still carries the --from option at cli.ts:155, so the retirement is still live, not already landed.
  10. Repository surface — right. One commit; its trailer pair is the model-free pair AGENTS.md prescribes; no model identifier in the PR title, body, changeset or commit. Governed Surface Queue Guard is green (4 paths, not a governed surface). The PR body's region-disjointness claim against draft PR objectui#11069 is outside this brief's inputs and not re-read; a textual overlap, if any, is mechanical under "whichever lands second merges main".

Nothing in the diff is judged wrong.

② Semver level

  • .changeset/11488-retire-generate-from.md declares '@object-ui/cli': minor. The diff removes something an author can write at the command line, so in semver terms it is BREAKING; this repo's release model (AGENTS.md's version-number policy: the 39-package fixed group's major follows the @objectstack major, objectui's own breaking changes ship as minor with the break spelled out, and scripts/check-changeset-no-major.mjs behind Changeset Bump Policy refuses major) makes minor right. patch would understate a narrowing; major is refused outside the once-per-objectstack-major sync. The changeset says so itself in its parenthetical, in the same form as PR objectui#11487's.
  • The body carries what a breaking changeset owes: the BREAKING banner naming the package, the FROM → TO line with the one-line fix (drop the flag; no external-source import exists, so nothing replaces it), the why, the command-line delta (non-zero exit, nothing written, --help and the docs table) and Clause-②: yes. Every sentence matches the diff and the measured bin behaviour.
  • Not a skip-changeset case: packages/cli/src/cli.ts is the published bin of a released package (@object-ui/cli 17.6.0, in the fixed group), so a changeset is owed and present (Changeset Declaration green). Changeset Bump Policy, Changeset Overwrite Report, Changeset Claim Re-read and Changeset Fixed Group Check are green too.
  • The claim re-read's two pending changesets, read against the diff: 7658-toc-code-span-anchor-parity names cli.mdx for its headings, and no heading moves (verified above); 7694-chart-series-chart-type-alias-refusal names cli.ts as the home of objectui validate, which still declares .command('validate') at the head. Both bodies stay true; no correction owed.
  • Clause-②: line — right. PR body line 3 reads Clause-②: yes; the seat's claim 5957801998 and the changeset say the same. It is a narrowing: an option the published bin accepted (and answered with a no-op exit 0) is now refused. No gate at the head reads an arm on the line (scripts/ and .github/ hold no Clause-② reader; the one spelling, in check-handler-key-read-sites.mjs, is a comment, and check-governed-queue-guard.mjs states objectui has no check-clause2-carriers.mjs), and 78 pending changesets at the head carry the bare Clause-②: yes, so the spelling follows the repo's own precedent.

③ Boundary flags

Dev report 5958059563: open_questions: []. Its deviations and findings, each answered:

  1. PR assignee not set (the --assign write was refused by the permission layer before any request left) — an administrative mirror outside the contract; the seat's ACCEPT 5958107550 records it as the seat's own and leaves it; the PR's assignee list is still empty at review time. Escalated to the seat; no bearing on this verdict.
  2. pnpm install --config.engine-strict=false — brief-directed and local to the dev's container; nothing on the head depends on it. Answered.
  3. Whole generate flag table removed rather than one row — answered right in ①.4: the row was the table.
  4. The objectui#11476 describe and help pin renamed — nothing outside the test file reads either old title (git grep at the head: 0 hits), and the --output refusal case keeps its rendered name through %s. Answered.
  5. Model-free trailer pair instead of the harness's model-named trailer — AGENTS.md's commit-message rule; not a deviation. Answered.
  6. check-doc-snippet-types.mjs NOT MEASURED locally (unbuilt packages) — answered by Doc Snippet Type Check on the head (tally below); the docs edit touches no fenced block.
  7. "CI in_progress, not awaited per contract" — answered by the completed set below.
  • Out-of-scope finding, objectui add COMPONENT prints "Feature not implemented yet.", exits 0 and writes nothing — escalated: the seat filed it as objectui#11496 (open, created 2026-10-02T17:49Z), the third surface of the same declared-not-enforced family, for triage. Right to leave it out of this diff: the ruling retires --from only, and retire-vs-implement for a whole command is triage's call.
  • The dev's ESLint narrowing proof and its dist-side grep -c substitute for the preflight tool — reporting only; Lint on the head is the gate (tally below).

Check-runs on the head

43 check-runs on 5d1d517045741ea7279179ffa0ca87b8de99866a, every one completed (the aggregate Test landed last, at 2026-10-02T17:59Z): 40 success · 3 skipped · 0 failure (0 cancelled, 0 timed out, 0 neutral, 0 action required). The three skipped are the push-only coverage lanes (Test (coverage), Test (coverage shard N/4)) and dependabot; none is a verdict on this diff. Green and material here: Test (shard 1/8) through Test (shard 8/8) (the lane that runs cli-bin.test.ts: the two-case refusal it.each, the unchanged control and the help pin), Test (the per-shard roll-up), Test (dist pins), Type Check (the narrowed action signature), Lint (the edited files and the retained chalk import), Build & E2E, Build Docs, Internal Docs Link Check, Doc Snippet Type Check (the gate the dev could not measure locally), Doc Fence Language Check, Doc Component Type Check, Doc Example Id Check, Changeset Declaration, Changeset Bump Policy, Changeset Overwrite Report, Changeset Claim Re-read, Changeset Fixed Group Check, Line Citation Gate, Governed Surface Queue Guard, Spec Main Shape Gate. These conclusions are the gate verdicts; none was re-run here.

Implemented-by: claude/issue-11488-retire-generate-from
Reviewed-by: session_01YLg8XqWGJ785fwQ5v4pH37

VERDICT: PASS

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 2, 2026 18:03
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit 1fe05ff Oct 2, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-11488-retire-generate-from branch October 2, 2026 18:18
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: cli tests

Projects

None yet

1 participant