@object-ui/fields declares a ./style.css export but nothing builds dist/index.css for it — the subpath quick-start teaches looks unresolvable #4059
Description
Out-of-scope finding from the #3883 / #3884 docs sweep (PR pending). Not fixed there — that PR's file surface is content/docs/guide/*.md only.
What was checked, on origin/main @ 11c1e71
packages/fields/package.json declares the subpath:
"exports": {
".": { "types": "./dist/index.d.ts", "import": "./dist/index.js", "require": "./dist/index.cjs" },
"./style.css": "./dist/index.css"
}but nothing in that package appears to produce dist/index.css:
packages/fields/package.jsonscripts.buildistsc && vite build— no CSS step. The only package with one is@object-ui/components:"build": "vite build && node scripts/build-css.mjs", andscripts/build-css.mjsexists only there (grep -rln build-css --include=package.json packages/returns one file).packages/fields/srccontains no.cssfile at all, and no module under it imports one (grep -rn 'import.*\.css' packages/fields/srcis empty). Vite's library build emits a stylesheet only when one is in the entry graph.packages/fields/vite.config.tshas no CSS entry orcssCodeSplithandling.- Nothing inside this repo imports the subpath, so no build here would have noticed: repo-wide,
@object-ui/fields/style.cssoccurs only incontent/docs/guide/quick-start.md. The three real in-repo consumers all import the components one (packages/plugin-gantt/demo/main.tsx,packages/plugin-grid/demo/main.tsx,packages/plugin-grid/demo/bulk-actions.tsx).
Why it matters
content/docs/guide/quick-start.md:57 teaches consumers to write @import "@object-ui/fields/style.css"; as step 3 of the first-run setup. If the file is not in the published tarball, a bundler resolving that @import fails the consumer's build outright — a harder failure than the missing-utilities class #3883 / #3884 are about, and on the same page.
What I did NOT verify, and how to settle it
I did not run the build: this was a docs-only worktree with no install, and the #3883 dispatch's measurement basis explicitly scoped me to cheap spot-verification. So the evidence above is a source read, not a measurement. The deciding runs are:
pnpm --filter @object-ui/fields build && ls packages/fields/dist/index.csspnpm --filter @object-ui/fields exec npm pack --dry-runand check whetherdist/index.cssis in the file list.
If it is genuinely absent, the two ends are (a) give fields a CSS entry plus a build step mirroring components/scripts/build-css.mjs, or (b) drop the ./style.css export and the quick-start.md:57 line that teaches it. Which one is right depends on whether the fields widgets carry styling of their own beyond the components palette — not a call this finding makes.
Dedup
Searched open issues for fields style.css, "@object-ui/fields" css, exports dist/index.css build, subpath export missing file. Hits were only #3883 / #3884 (the sweep this came from), #3890 (CLI temp-app alias table) and #4043 (spec symbol derivation) — none covers this export.
Generated by Claude Code
Activity
yinlianghui commentedon Aug 10, 2026
Measurement upgrade (objectui seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3, 2026-08-10): the filer flagged this as a source read pending the deciding build. The published-artifact reading settles it without a build — inspected the npm tarballs directly:@object-ui/fields@17.3.0—https://registry.npmjs.org/@object-ui/fields/-/fields-17.3.0.tgzcontains zero.cssfiles (grep over the fulltar -tzflisting). The"./style.css": "./dist/index.css"export is a phantom: a consumer's@import '@object-ui/fields/style.css'fails to resolve against the shipped package.@object-ui/components@17.3.0tarball shipspackage/dist/index.cssas expected.So this is a real, user-visible defect in the published package, not a hypothesis. Consequence already acted on: PR #4060 (the #3883/#3884 docs sweep) was sent back for a targeted rework to stop teaching the fields import on all three guide pages — the docs half of this defect dies there; what remains for this card is the package half (either build real CSS for fields or remove the phantom export — and if fields' class shapes are not a subset of components' published utilities, removal alone under-styles fields, so the disposition needs that one measurement first).
Generated by Claude Code
docs(guide): stop teaching the phantom @object-ui/fields/style.css im…
yinlianghui commentedon Aug 10, 2026
Triage + release board (objectui seat PM — this repo's board producer):
pm:queue+target:v17, class ② — the published@object-ui/fields@17.3.0package declares a"./style.css"export that resolves to nothing (zero.cssfiles in the tarball, measured above): a shipped contract surface that lies. The docs half died in PR #4060; this card is the package half.Claim: PM loop round 2
Session:
session_017Qqyix2QcnpUC9XeYVDzx3Branch:
claude/issue-4059-fields-style-exportWorktree:
objectui-issue-4059Domain:
repo:objectui(whole-repo seat)File surface:
packages/fields/package.json(exports), possiblypackages/fieldsbuild config, + tests/gates pinning the disposition. ⛔ Region-exclusive vs the in-flight #3569 branch: do not touchGridField*/source component files inpackages/fields. Stop on breach; explain in the report.Container & model: M,
mode:subagent,model: opusSerial constraints cleared: #3569's pushed branch touches
packages/fieldssource (GridField.tsx), disjoint from packaging/exports; no other claim or PR onpackages/fieldspackaging.Delegated ruling with a falsifiable premise (maintainer authorized seat rulings from the long-term-stability standpoint, 2026-08-10; veto window open):
"./style.css"frompackages/fields' exports + a gate asserting every declared subpath export resolves to a file that ships), premised on: fields' class shapes are a subset of the utilities already published in@object-ui/components'dist/index.css. The premise must be measured first (the quick-start 教的两条 @source node_modules 行是冗余的:实测多产 100 kB CSS、14 条没人用的选择器,且补不回它看似要补的主题 utility #3884-style read: extract class-shaped tokens from fields' builtdist/*.js, compare against components' publisheddist/index.cssrule set).Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
Ruling premise measured — FALSIFIED. No PR opened; the disposition is back with the PM.
The delegated ruling (retire the phantom export) was premised on: fields' class shapes are a subset of the utilities already published in
@object-ui/components'dist/index.css. Measured first, per the instruction. It is not a subset.1. The phantom export, confirmed three independent ways (on
origin/main@0a09793f2)pnpm --filter @object-ui/fields build-> exit 0,find packages/fields/dist -name '*.css' | wc -l= 0.@object-ui/fields@17.3.0: 274 entries, zero.css. Itspackage.jsonstill declares"./style.css": "./dist/index.css".@object-ui/components@17.3.0: shipspackage/dist/index.css(165 871 bytes).2. Premise measurement (#3884's method)
Compiled fields' built
dist/index.js+dist/index.cjs— the exact surface anode_modulesglob can see — against components' own@theme(itssrc/index.css, with only the@sourceline repointed), then compared the produced rule set against components' publisheddist/index.css(downloaded tarball, not a local build).@object-ui/components@17.3.0publisheddist/index.cssMethod control (the same pipeline pointed at components' own dist, reproducing #3884's reading): 0 classes / 0 selectors missing — 1358 vs 1358, i.e. components' pre-built CSS really is a strict superset of its own scan surface, exactly as #3884 measured. The pipeline is therefore validated, and the 152 are real.
Spot-traced to fields source, so these are not bundling artifacts:
cursor-crosshairpackages/fields/src/widgets/SignatureField.tsx:113group/emailpackages/fields/src/index.tsx:1165text-indigo-700packages/fields/src/index.tsx:922(tag colour map)min-w-[8ch]packages/fields/src/widgets/TagsField.tsx:79hover:fill-yellow-500packages/fields/src/widgets/RatingField.tsx:833. The split that decides the fork
Of the 152, 17 depend on the ObjectUI
@themeblock, which lives inpackages/components/src/index.cssand is not published (filesshipsdistonly). No consumer-side@sourcecan regenerate them — #3780 measured that grid already:bg-background/60,bg-destructive/5,bg-muted/60,bg-primary/20,border-background,border-border/40,border-muted-foreground/25,border-muted-foreground/30,focus-visible:ring-ring/60,focus:ring-ring/60,hover:bg-accent/30,hover:bg-muted/80,hover:bg-primary/10,hover:bg-primary/50,hover:border-primary/50,ring-border/60,ring-destructive/50The remaining 135 are plain Tailwind built-ins (palette, sizing, positioning) and are recoverable by an
@sourceovernode_modules/@object-ui/fields/dist.4. Corroboration: no in-repo host relies on a pre-built fields sheet
Every host that renders fields reaches into fields' source instead —
apps/console/src/index.css:17,examples/console-starter/src/index.css:9,examples/byo-backend-console/src/index.css:29, all@source '.../packages/fields/src/**/*.{ts,tsx}'. That is a workspace-relative path no external consumer can write. So the repo has never exercised the./style.cssexport, which is why the phantom survived — and it also means in-repo rendering proves nothing about consumer rendering.5. Why removal alone is no longer a no-op
The ruling's rationale was "an export that has never resolved cannot have a working consumer, so removing it breaks no one". That still holds for the export. But it now collides with a second measured fact: after PR #4060,
content/docs/guide/quick-start.md:60teachesThat sentence is true for components (#3884 measured exactly that) and false for fields: it generalizes a components-only reading across the package boundary. A consumer following the current quick-start today gets none of the 152. Removing the export makes that the permanent, documented state with no supported remedy — which is a product-shape call, not a cleanup.
Reporting
needs_decisionwith the A/B fork per the ruling's own escape clause. No files changed, no PR, worktree torn down.Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
Delegated ruling #2 (objectui seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3, 2026-08-10): the premise of ruling #1 is falsified by the measurement above — ruled route is now B, narrow variant. Authorization: maintainer's 2026-08-10 delegation (decisions may be taken by this seat from the long-term-stability standpoint). Veto window open.The dev's stop was correct and is the escape clause working as designed: 152 fields-only class shapes, 17 of them unrecoverable by any consumer-side
@source(their@themetokens are unpublished), falsify "removal breaks no one and costs nothing" — removal would ratify a permanently under-styled fields with no supported remedy.Ruling: B — give
@object-ui/fieldsa real CSS build, narrow variant (compile against@object-ui/components' theme, emit only fields' own utilities; do NOT re-emit the shared@theme— components' sheet owns it and consumers already import it first). Three axes:packages/components/scripts/build-css.mjspattern applied consistently, not a second mechanism; it is the only fork under which the published manifest tells the truth (same shape as the maintainer's fix(plugin-map): 顶层style是内联 CSS,不再被当作 MapLibre style 读 (#5017) #5175 ruling: when the capability and the declaration both exist, enforce — make the implementation catch up — rather than remove). A/A' both make "fields is styled" a property of consumer Tailwind configuration — the consumer-side-tolerance shape contract-first rejects.@importis correct by construction and the durable gate can land green asserting a true thing. A' fails as slightly-wrong colours even when transcribed perfectly — the least detectable failure mode available.Startup-focus counterweight acknowledged (zero external reports since publication = weak pull); the cost side is one mirrored build script, which is why it does not tip the ruling.
Implementation scope (same PR, per the dev's own note):
src/index.cssis expressed (build-time path is acceptable inside the monorepo — it mirrors how components builds itself);scripts/__tests__/package-files-exist.test.tswith the producer test +files-containment test described in the report) — never before it, it would be red on main;style.cssimport where docs(guide): teach the Tailwind 4 CSS-first setup on theming / troubleshooting / quick-start #4060 removed it, and correct the over-generalized sentence atquick-start.md:60— with B the measurement that justified the removal is superseded; docs must describe the package as it will ship from this commit;Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
ACCEPT (objectui seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4076, implementing Delegated Ruling #2 (route B, narrow variant).What shipped:
@object-ui/fieldsgains a real CSS build — a build-time-only Tailwind entry that@references components' theme for resolution while emitting none of it, plus a build script mirroring components' that subtracts every rule components' built sheet already ships. Output 21.57 kB / 157 classes (vs a ~180 kB naive near-duplicate);npm pack --dry-runconfirmsdist/index.cssis in the tarball — the"./style.css"export resolves for the first time in the package's life. Acceptance evidence per the ruling: all 152 measured fields-only classes covered, 0 uncovered, and all 17 theme-token utilities only this build can produce are present; the 157−152 delta is explained, not smoothed over. The durable gate (exports-reality: packability + CSS producibility) landed in the same PR inpackage-files-exist.test.ts, and the three guide pages were re-taught (fields import restored, the over-generalized quick-start:60 sentence repaired). Changeset minor, accepted by the Bump Policy gate.Review notes: two real would-have-shipped-wrong bugs were caught by the dev's own verification — Tailwind's cwd-dependent source detection poisoning the subtraction set (fixed by reading components' built artifact) and fields' own entry absorbing repo-wide utilities (fixed with
source(none), byte-identical from both cwds); and the gate's firstonDiskpredicate was falsified against the exact state it exists to reject and re-keyed on git's index. Reverse verification ran in both pre-fix build states, red in both with the defect named verbatim in the failure message. Coupling to components' unpublished source is two build-time monorepo-relative paths, unreachable from the tarball, ordered by turbo's^build. Region exclusivity vs #3569 held. All 20 checks completed, 0 failures (Lint / Type Check / 4 shards individually verified).Reminder recorded for the release: the export only works from the release that carries this change — versions ≤17.3.0 never shipped the file (stated in the changeset).
Landing next: flipping ready and driving to MERGED.
Generated by Claude Code
docs(guide): teach the Tailwind 4 CSS-first setup on theming / troubl…
feat(fields): build and publish the style.css the package has always …