test(scripts): pin @object-ui/fields' published stylesheet as a third subject - #7043

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin
Aug 31, 2026
Merged

test(scripts): pin @object-ui/fields' published stylesheet as a third subject#7043
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Fixes#6438

scripts/__tests__/plugin-published-stylesheet.test.ts ran its per-package
assertions over exactly two subjects, plugin-grid and plugin-kanban.
@object-ui/fields was not one of them — and it is the package whose stylesheet
has actually been shipping to consumers since #4059, the very defect the test's
own header cites as the reason the shape exists. Its dist/index.css was
guarded by the four write-time assertions inside the shared builder, which run
only during a build; CI runs this suite on an unbuilt worktree, so nothing in
the test run inspected it.

This adds fields as a third subject. The suite goes from 14 tests to 20
(three subjects times six per-package assertions, plus two standalone).

Premise re-verified on the merged ref

Re-read on main = e33b44796, item for item, rather than inherited:
packages/fields/scripts/build-css.mjs (notbuild-stylesheet.mjs) imports
createPluginStylesheetBuilder at line 94 and exports PACKAGE_ROOT / PACKAGE_NAME
(96/97), MUST_SURVIVE / CLASS_CEILING (114/132), builder / buildOptions
(161/163) behind the isEntrypoint guard (171) — the same shape the two plugins
export. SUBJECTS was at test line 91.

How the CARD_THEMED entry was derived

Independently, from the sheet the build actually emits — not read back off
fields' own MUST_SURVIVE, which would have looked identical while pinning
nothing.

Method: build fields' sheet through the shared builder, then keep every
surviving class whose own declarations resolve a --color-* token declared in
packages/components/src/index.css's @theme block (35 tokens) — the file that
package does not publish, which is exactly what makes an in-monorepo build the
only possible producer of these utilities.

That yields 17 surviving themed classes out of 163 surviving total. Two
independent corroborations:

Only 3 of the 17 appear in MUST_SURVIVE, so the list is demonstrably not that
list read back.

Banner: taken from buildOptions, and why nothing changed

fields passes a per-package header (HEADER, line 147, into buildOptions at
line 168); plugin-grid's buildOptions has no header key and inherits the
shared defaultHeader. The emitted sheet is header plus the sheet, so any
assertion reading the banner from the shared default would judge fields wrongly.

Surveyed before writing: no assertion in the suite reads the emitted banner,
so the caveat is preventive here, not corrective. The one assertion that
inspects the whole css string — "carries utilities only" — was checked against
fields' actual HEADER bytes and none of its three patterns can match it. The
module header now records the rule for anything added later. A banner pin is
not added here, for a reason recorded as a follow-up below.

Proof the new assertions have teeth

"The suite is green after I added it" is not evidence — a green assertion that
inspects nothing is precisely the defect this card records. Two ablations, each
proving the mutation reached disk before measuring, and each proving the restore
by blob hash rather than by exit code:

1. A themed utility stops being produced.hover:bg-primary/10 is in the
derived list and deliberately not in MUST_SURVIVE, so the builder's
write-time throw does not fire and mask the result. Its single usage site in
RecordPickerDialog.tsx was retargeted to hover:bg-primary/15.

  • on disk: occurrences of the removed text 1 to 0, injected text 0 to 1; blob moved 1e9d341d to 3e0a4915
  • result: Tests 1 failed | 19 passed, the failure being
    fields > emits the themed utilities only this build can produce with
    AssertionError: expected [ 'hover:bg-primary/10' ] to deeply equal []
  • restore: blob back to 1e9d341d, git diff HEAD empty

2. The manifest declaration breaks. fields' exports['./style.css'] was
pointed at ./dist/nope.css, which also proves the subject name resolves to
packages/fields.

  • on disk: injected 1, original pair 0; blob moved 5e442f18 to 98eeea6f
  • result: Tests 1 failed | 19 passed, the failure being
    fields > declares the export AND the step that produces it
  • restore: blob back to 5e442f18, git diff HEAD empty

In both runs exactly one assertion went red and it was a fields one, with
plugin-grid and plugin-kanban still green — so the red is subject-specific,
not a global break.

The finding that justifies the per-package coverage

Under ablation 1 the union assertion, "gives every themed utility the card
measured a producer", stayed green. Measured cause: plugin-grid also emits
hover:bg-primary/10, so the union was satisfied by another subject while
fields' own sheet had genuinely regressed. Adding fields to SUBJECTS is what
buys the coverage; adding it only to CARD_THEMED would have reproduced the
defect this card records.

Verification

Union run on the final commit, git rev-parse --short HEAD = 1219b8d88, tree clean:

  • npx vitest run scripts/__tests__/plugin-published-stylesheet.test.ts --maxWorkers=2Tests 20 passed (20), exit 0
  • pnpm type-check:scripts — exit 0. Load-bearing: the shared builder's own comment records that this reads the options types through this test file, and fields is the first subject to pass header.
  • pnpm type-check:coverage45/46 via type-check, 41/41 packages compile their tests
  • pnpm check:control-bytesOK (scanned 5850 tracked text file(s))
  • pnpm changeset:check — no major, fixed group OK
  • node scripts/check-changeset-presence.mjs — "no changeset is owed"; the changeset is an explicit no-release declaration in the empty-frontmatter shape this repo uses for test-only changes
  • eslint on the changed file — 0 errors, 0 warnings

Lint was narrowed to the changed file rather than run farm-wide, and the
narrowing is measured, not assumed: the file count comes from eslint's own
--format json output (1 file), and type-aware linting is not enabled in
eslint.config.js (no projectService, project: or parserOptions;
control term rules hits 10 times in the same file, so the query was live), so
this diff cannot move the verdict on any untouched file. CI runs the full farm
regardless.

Follow-up, filed not ridden along

The emitted banner is pinned by nothing, and it cannot be pinned cleanly today:
the shared builder does not export its defaultHeader, so an assertion covering
all three subjects would need a tolerant fallback in the test for the two
packages that declare no header — the consumer-side leniency this repo's
contract-first rule says to fix at the producer instead. That is a
producer-side change with its own review, so it is recorded rather than ridden
along here.


Generated by Claude Code

… subject
`plugin-published-stylesheet.test.ts` ran its per-package assertions over
`plugin-grid` and `plugin-kanban` only. `@object-ui/fields` — the package whose
sheet has actually been shipping to consumers since objectui#4059, the very
defect the test's header cites as the reason the shape exists — was covered by
the builder's four write-time assertions and by nothing in the suite, since CI
runs the tests on an unbuilt worktree.
objectui#6405 re-pointed fields at the shared `createPluginStylesheetBuilder`,
so it now exports the same module shape the plugins do and the assertions apply
unchanged.
The `CARD_THEMED` entry is derived from the emitted sheet — surviving classes
whose declarations resolve a `--color-*` token from components' unpublished
`@theme` block — not read back off fields' own `MUST_SURVIVE`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgDDqh6YnkXqsnVTCa7wHk
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scripts/__tests__/plugin-published-stylesheet.test.ts pins the two plugin sheets but not @object-ui/fields, the one that is actually published

2 participants

@zhuangjianguo@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

test(scripts): pin @object-ui/fields' published stylesheet as a third subject - #7043

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin
Aug 31, 2026
Merged

test(scripts): pin @object-ui/fields' published stylesheet as a third subject#7043
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Fixes#6438

scripts/__tests__/plugin-published-stylesheet.test.ts ran its per-package
assertions over exactly two subjects, plugin-grid and plugin-kanban.
@object-ui/fields was not one of them — and it is the package whose stylesheet
has actually been shipping to consumers since #4059, the very defect the test's
own header cites as the reason the shape exists. Its dist/index.css was
guarded by the four write-time assertions inside the shared builder, which run
only during a build; CI runs this suite on an unbuilt worktree, so nothing in
the test run inspected it.

This adds fields as a third subject. The suite goes from 14 tests to 20
(three subjects times six per-package assertions, plus two standalone).

Premise re-verified on the merged ref

Re-read on main = e33b44796, item for item, rather than inherited:
packages/fields/scripts/build-css.mjs (notbuild-stylesheet.mjs) imports
createPluginStylesheetBuilder at line 94 and exports PACKAGE_ROOT / PACKAGE_NAME
(96/97), MUST_SURVIVE / CLASS_CEILING (114/132), builder / buildOptions
(161/163) behind the isEntrypoint guard (171) — the same shape the two plugins
export. SUBJECTS was at test line 91.

How the CARD_THEMED entry was derived

Independently, from the sheet the build actually emits — not read back off
fields' own MUST_SURVIVE, which would have looked identical while pinning
nothing.

Method: build fields' sheet through the shared builder, then keep every
surviving class whose own declarations resolve a --color-* token declared in
packages/components/src/index.css's @theme block (35 tokens) — the file that
package does not publish, which is exactly what makes an in-monorepo build the
only possible producer of these utilities.

That yields 17 surviving themed classes out of 163 surviving total. Two
independent corroborations:

Only 3 of the 17 appear in MUST_SURVIVE, so the list is demonstrably not that
list read back.

Banner: taken from buildOptions, and why nothing changed

fields passes a per-package header (HEADER, line 147, into buildOptions at
line 168); plugin-grid's buildOptions has no header key and inherits the
shared defaultHeader. The emitted sheet is header plus the sheet, so any
assertion reading the banner from the shared default would judge fields wrongly.

Surveyed before writing: no assertion in the suite reads the emitted banner,
so the caveat is preventive here, not corrective. The one assertion that
inspects the whole css string — "carries utilities only" — was checked against
fields' actual HEADER bytes and none of its three patterns can match it. The
module header now records the rule for anything added later. A banner pin is
not added here, for a reason recorded as a follow-up below.

Proof the new assertions have teeth

"The suite is green after I added it" is not evidence — a green assertion that
inspects nothing is precisely the defect this card records. Two ablations, each
proving the mutation reached disk before measuring, and each proving the restore
by blob hash rather than by exit code:

1. A themed utility stops being produced.hover:bg-primary/10 is in the
derived list and deliberately not in MUST_SURVIVE, so the builder's
write-time throw does not fire and mask the result. Its single usage site in
RecordPickerDialog.tsx was retargeted to hover:bg-primary/15.

  • on disk: occurrences of the removed text 1 to 0, injected text 0 to 1; blob moved 1e9d341d to 3e0a4915
  • result: Tests 1 failed | 19 passed, the failure being
    fields > emits the themed utilities only this build can produce with
    AssertionError: expected [ 'hover:bg-primary/10' ] to deeply equal []
  • restore: blob back to 1e9d341d, git diff HEAD empty

2. The manifest declaration breaks. fields' exports['./style.css'] was
pointed at ./dist/nope.css, which also proves the subject name resolves to
packages/fields.

  • on disk: injected 1, original pair 0; blob moved 5e442f18 to 98eeea6f
  • result: Tests 1 failed | 19 passed, the failure being
    fields > declares the export AND the step that produces it
  • restore: blob back to 5e442f18, git diff HEAD empty

In both runs exactly one assertion went red and it was a fields one, with
plugin-grid and plugin-kanban still green — so the red is subject-specific,
not a global break.

The finding that justifies the per-package coverage

Under ablation 1 the union assertion, "gives every themed utility the card
measured a producer", stayed green. Measured cause: plugin-grid also emits
hover:bg-primary/10, so the union was satisfied by another subject while
fields' own sheet had genuinely regressed. Adding fields to SUBJECTS is what
buys the coverage; adding it only to CARD_THEMED would have reproduced the
defect this card records.

Verification

Union run on the final commit, git rev-parse --short HEAD = 1219b8d88, tree clean:

  • npx vitest run scripts/__tests__/plugin-published-stylesheet.test.ts --maxWorkers=2Tests 20 passed (20), exit 0
  • pnpm type-check:scripts — exit 0. Load-bearing: the shared builder's own comment records that this reads the options types through this test file, and fields is the first subject to pass header.
  • pnpm type-check:coverage45/46 via type-check, 41/41 packages compile their tests
  • pnpm check:control-bytesOK (scanned 5850 tracked text file(s))
  • pnpm changeset:check — no major, fixed group OK
  • node scripts/check-changeset-presence.mjs — "no changeset is owed"; the changeset is an explicit no-release declaration in the empty-frontmatter shape this repo uses for test-only changes
  • eslint on the changed file — 0 errors, 0 warnings

Lint was narrowed to the changed file rather than run farm-wide, and the
narrowing is measured, not assumed: the file count comes from eslint's own
--format json output (1 file), and type-aware linting is not enabled in
eslint.config.js (no projectService, project: or parserOptions;
control term rules hits 10 times in the same file, so the query was live), so
this diff cannot move the verdict on any untouched file. CI runs the full farm
regardless.

Follow-up, filed not ridden along

The emitted banner is pinned by nothing, and it cannot be pinned cleanly today:
the shared builder does not export its defaultHeader, so an assertion covering
all three subjects would need a tolerant fallback in the test for the two
packages that declare no header — the consumer-side leniency this repo's
contract-first rule says to fix at the producer instead. That is a
producer-side change with its own review, so it is recorded rather than ridden
along here.


Generated by Claude Code

… subject
`plugin-published-stylesheet.test.ts` ran its per-package assertions over
`plugin-grid` and `plugin-kanban` only. `@object-ui/fields` — the package whose
sheet has actually been shipping to consumers since objectui#4059, the very
defect the test's header cites as the reason the shape exists — was covered by
the builder's four write-time assertions and by nothing in the suite, since CI
runs the tests on an unbuilt worktree.
objectui#6405 re-pointed fields at the shared `createPluginStylesheetBuilder`,
so it now exports the same module shape the plugins do and the assertions apply
unchanged.
The `CARD_THEMED` entry is derived from the emitted sheet — surviving classes
whose declarations resolve a `--color-*` token from components' unpublished
`@theme` block — not read back off fields' own `MUST_SURVIVE`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgDDqh6YnkXqsnVTCa7wHk
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scripts/__tests__/plugin-published-stylesheet.test.ts pins the two plugin sheets but not @object-ui/fields, the one that is actually published

2 participants

@zhuangjianguo@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(scripts): pin @object-ui/fields' published stylesheet as a third subject - #7043

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin
Aug 31, 2026
Merged

test(scripts): pin @object-ui/fields' published stylesheet as a third subject#7043
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Fixes#6438

scripts/__tests__/plugin-published-stylesheet.test.ts ran its per-package
assertions over exactly two subjects, plugin-grid and plugin-kanban.
@object-ui/fields was not one of them — and it is the package whose stylesheet
has actually been shipping to consumers since #4059, the very defect the test's
own header cites as the reason the shape exists. Its dist/index.css was
guarded by the four write-time assertions inside the shared builder, which run
only during a build; CI runs this suite on an unbuilt worktree, so nothing in
the test run inspected it.

This adds fields as a third subject. The suite goes from 14 tests to 20
(three subjects times six per-package assertions, plus two standalone).

Premise re-verified on the merged ref

Re-read on main = e33b44796, item for item, rather than inherited:
packages/fields/scripts/build-css.mjs (notbuild-stylesheet.mjs) imports
createPluginStylesheetBuilder at line 94 and exports PACKAGE_ROOT / PACKAGE_NAME
(96/97), MUST_SURVIVE / CLASS_CEILING (114/132), builder / buildOptions
(161/163) behind the isEntrypoint guard (171) — the same shape the two plugins
export. SUBJECTS was at test line 91.

How the CARD_THEMED entry was derived

Independently, from the sheet the build actually emits — not read back off
fields' own MUST_SURVIVE, which would have looked identical while pinning
nothing.

Method: build fields' sheet through the shared builder, then keep every
surviving class whose own declarations resolve a --color-* token declared in
packages/components/src/index.css's @theme block (35 tokens) — the file that
package does not publish, which is exactly what makes an in-monorepo build the
only possible producer of these utilities.

That yields 17 surviving themed classes out of 163 surviving total. Two
independent corroborations:

Only 3 of the 17 appear in MUST_SURVIVE, so the list is demonstrably not that
list read back.

Banner: taken from buildOptions, and why nothing changed

fields passes a per-package header (HEADER, line 147, into buildOptions at
line 168); plugin-grid's buildOptions has no header key and inherits the
shared defaultHeader. The emitted sheet is header plus the sheet, so any
assertion reading the banner from the shared default would judge fields wrongly.

Surveyed before writing: no assertion in the suite reads the emitted banner,
so the caveat is preventive here, not corrective. The one assertion that
inspects the whole css string — "carries utilities only" — was checked against
fields' actual HEADER bytes and none of its three patterns can match it. The
module header now records the rule for anything added later. A banner pin is
not added here, for a reason recorded as a follow-up below.

Proof the new assertions have teeth

"The suite is green after I added it" is not evidence — a green assertion that
inspects nothing is precisely the defect this card records. Two ablations, each
proving the mutation reached disk before measuring, and each proving the restore
by blob hash rather than by exit code:

1. A themed utility stops being produced.hover:bg-primary/10 is in the
derived list and deliberately not in MUST_SURVIVE, so the builder's
write-time throw does not fire and mask the result. Its single usage site in
RecordPickerDialog.tsx was retargeted to hover:bg-primary/15.

  • on disk: occurrences of the removed text 1 to 0, injected text 0 to 1; blob moved 1e9d341d to 3e0a4915
  • result: Tests 1 failed | 19 passed, the failure being
    fields > emits the themed utilities only this build can produce with
    AssertionError: expected [ 'hover:bg-primary/10' ] to deeply equal []
  • restore: blob back to 1e9d341d, git diff HEAD empty

2. The manifest declaration breaks. fields' exports['./style.css'] was
pointed at ./dist/nope.css, which also proves the subject name resolves to
packages/fields.

  • on disk: injected 1, original pair 0; blob moved 5e442f18 to 98eeea6f
  • result: Tests 1 failed | 19 passed, the failure being
    fields > declares the export AND the step that produces it
  • restore: blob back to 5e442f18, git diff HEAD empty

In both runs exactly one assertion went red and it was a fields one, with
plugin-grid and plugin-kanban still green — so the red is subject-specific,
not a global break.

The finding that justifies the per-package coverage

Under ablation 1 the union assertion, "gives every themed utility the card
measured a producer", stayed green. Measured cause: plugin-grid also emits
hover:bg-primary/10, so the union was satisfied by another subject while
fields' own sheet had genuinely regressed. Adding fields to SUBJECTS is what
buys the coverage; adding it only to CARD_THEMED would have reproduced the
defect this card records.

Verification

Union run on the final commit, git rev-parse --short HEAD = 1219b8d88, tree clean:

  • npx vitest run scripts/__tests__/plugin-published-stylesheet.test.ts --maxWorkers=2Tests 20 passed (20), exit 0
  • pnpm type-check:scripts — exit 0. Load-bearing: the shared builder's own comment records that this reads the options types through this test file, and fields is the first subject to pass header.
  • pnpm type-check:coverage45/46 via type-check, 41/41 packages compile their tests
  • pnpm check:control-bytesOK (scanned 5850 tracked text file(s))
  • pnpm changeset:check — no major, fixed group OK
  • node scripts/check-changeset-presence.mjs — "no changeset is owed"; the changeset is an explicit no-release declaration in the empty-frontmatter shape this repo uses for test-only changes
  • eslint on the changed file — 0 errors, 0 warnings

Lint was narrowed to the changed file rather than run farm-wide, and the
narrowing is measured, not assumed: the file count comes from eslint's own
--format json output (1 file), and type-aware linting is not enabled in
eslint.config.js (no projectService, project: or parserOptions;
control term rules hits 10 times in the same file, so the query was live), so
this diff cannot move the verdict on any untouched file. CI runs the full farm
regardless.

Follow-up, filed not ridden along

The emitted banner is pinned by nothing, and it cannot be pinned cleanly today:
the shared builder does not export its defaultHeader, so an assertion covering
all three subjects would need a tolerant fallback in the test for the two
packages that declare no header — the consumer-side leniency this repo's
contract-first rule says to fix at the producer instead. That is a
producer-side change with its own review, so it is recorded rather than ridden
along here.


Generated by Claude Code

… subject
`plugin-published-stylesheet.test.ts` ran its per-package assertions over
`plugin-grid` and `plugin-kanban` only. `@object-ui/fields` — the package whose
sheet has actually been shipping to consumers since objectui#4059, the very
defect the test's header cites as the reason the shape exists — was covered by
the builder's four write-time assertions and by nothing in the suite, since CI
runs the tests on an unbuilt worktree.
objectui#6405 re-pointed fields at the shared `createPluginStylesheetBuilder`,
so it now exports the same module shape the plugins do and the assertions apply
unchanged.
The `CARD_THEMED` entry is derived from the emitted sheet — surviving classes
whose declarations resolve a `--color-*` token from components' unpublished
`@theme` block — not read back off fields' own `MUST_SURVIVE`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgDDqh6YnkXqsnVTCa7wHk
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scripts/__tests__/plugin-published-stylesheet.test.ts pins the two plugin sheets but not @object-ui/fields, the one that is actually published

2 participants

@zhuangjianguo@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(scripts): pin @object-ui/fields' published stylesheet as a third subject - #7043

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin
Aug 31, 2026
Merged

test(scripts): pin @object-ui/fields' published stylesheet as a third subject#7043
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Fixes#6438

scripts/__tests__/plugin-published-stylesheet.test.ts ran its per-package
assertions over exactly two subjects, plugin-grid and plugin-kanban.
@object-ui/fields was not one of them — and it is the package whose stylesheet
has actually been shipping to consumers since #4059, the very defect the test's
own header cites as the reason the shape exists. Its dist/index.css was
guarded by the four write-time assertions inside the shared builder, which run
only during a build; CI runs this suite on an unbuilt worktree, so nothing in
the test run inspected it.

This adds fields as a third subject. The suite goes from 14 tests to 20
(three subjects times six per-package assertions, plus two standalone).

Premise re-verified on the merged ref

Re-read on main = e33b44796, item for item, rather than inherited:
packages/fields/scripts/build-css.mjs (notbuild-stylesheet.mjs) imports
createPluginStylesheetBuilder at line 94 and exports PACKAGE_ROOT / PACKAGE_NAME
(96/97), MUST_SURVIVE / CLASS_CEILING (114/132), builder / buildOptions
(161/163) behind the isEntrypoint guard (171) — the same shape the two plugins
export. SUBJECTS was at test line 91.

How the CARD_THEMED entry was derived

Independently, from the sheet the build actually emits — not read back off
fields' own MUST_SURVIVE, which would have looked identical while pinning
nothing.

Method: build fields' sheet through the shared builder, then keep every
surviving class whose own declarations resolve a --color-* token declared in
packages/components/src/index.css's @theme block (35 tokens) — the file that
package does not publish, which is exactly what makes an in-monorepo build the
only possible producer of these utilities.

That yields 17 surviving themed classes out of 163 surviving total. Two
independent corroborations:

Only 3 of the 17 appear in MUST_SURVIVE, so the list is demonstrably not that
list read back.

Banner: taken from buildOptions, and why nothing changed

fields passes a per-package header (HEADER, line 147, into buildOptions at
line 168); plugin-grid's buildOptions has no header key and inherits the
shared defaultHeader. The emitted sheet is header plus the sheet, so any
assertion reading the banner from the shared default would judge fields wrongly.

Surveyed before writing: no assertion in the suite reads the emitted banner,
so the caveat is preventive here, not corrective. The one assertion that
inspects the whole css string — "carries utilities only" — was checked against
fields' actual HEADER bytes and none of its three patterns can match it. The
module header now records the rule for anything added later. A banner pin is
not added here, for a reason recorded as a follow-up below.

Proof the new assertions have teeth

"The suite is green after I added it" is not evidence — a green assertion that
inspects nothing is precisely the defect this card records. Two ablations, each
proving the mutation reached disk before measuring, and each proving the restore
by blob hash rather than by exit code:

1. A themed utility stops being produced.hover:bg-primary/10 is in the
derived list and deliberately not in MUST_SURVIVE, so the builder's
write-time throw does not fire and mask the result. Its single usage site in
RecordPickerDialog.tsx was retargeted to hover:bg-primary/15.

  • on disk: occurrences of the removed text 1 to 0, injected text 0 to 1; blob moved 1e9d341d to 3e0a4915
  • result: Tests 1 failed | 19 passed, the failure being
    fields > emits the themed utilities only this build can produce with
    AssertionError: expected [ 'hover:bg-primary/10' ] to deeply equal []
  • restore: blob back to 1e9d341d, git diff HEAD empty

2. The manifest declaration breaks. fields' exports['./style.css'] was
pointed at ./dist/nope.css, which also proves the subject name resolves to
packages/fields.

  • on disk: injected 1, original pair 0; blob moved 5e442f18 to 98eeea6f
  • result: Tests 1 failed | 19 passed, the failure being
    fields > declares the export AND the step that produces it
  • restore: blob back to 5e442f18, git diff HEAD empty

In both runs exactly one assertion went red and it was a fields one, with
plugin-grid and plugin-kanban still green — so the red is subject-specific,
not a global break.

The finding that justifies the per-package coverage

Under ablation 1 the union assertion, "gives every themed utility the card
measured a producer", stayed green. Measured cause: plugin-grid also emits
hover:bg-primary/10, so the union was satisfied by another subject while
fields' own sheet had genuinely regressed. Adding fields to SUBJECTS is what
buys the coverage; adding it only to CARD_THEMED would have reproduced the
defect this card records.

Verification

Union run on the final commit, git rev-parse --short HEAD = 1219b8d88, tree clean:

  • npx vitest run scripts/__tests__/plugin-published-stylesheet.test.ts --maxWorkers=2Tests 20 passed (20), exit 0
  • pnpm type-check:scripts — exit 0. Load-bearing: the shared builder's own comment records that this reads the options types through this test file, and fields is the first subject to pass header.
  • pnpm type-check:coverage45/46 via type-check, 41/41 packages compile their tests
  • pnpm check:control-bytesOK (scanned 5850 tracked text file(s))
  • pnpm changeset:check — no major, fixed group OK
  • node scripts/check-changeset-presence.mjs — "no changeset is owed"; the changeset is an explicit no-release declaration in the empty-frontmatter shape this repo uses for test-only changes
  • eslint on the changed file — 0 errors, 0 warnings

Lint was narrowed to the changed file rather than run farm-wide, and the
narrowing is measured, not assumed: the file count comes from eslint's own
--format json output (1 file), and type-aware linting is not enabled in
eslint.config.js (no projectService, project: or parserOptions;
control term rules hits 10 times in the same file, so the query was live), so
this diff cannot move the verdict on any untouched file. CI runs the full farm
regardless.

Follow-up, filed not ridden along

The emitted banner is pinned by nothing, and it cannot be pinned cleanly today:
the shared builder does not export its defaultHeader, so an assertion covering
all three subjects would need a tolerant fallback in the test for the two
packages that declare no header — the consumer-side leniency this repo's
contract-first rule says to fix at the producer instead. That is a
producer-side change with its own review, so it is recorded rather than ridden
along here.


Generated by Claude Code

… subject
`plugin-published-stylesheet.test.ts` ran its per-package assertions over
`plugin-grid` and `plugin-kanban` only. `@object-ui/fields` — the package whose
sheet has actually been shipping to consumers since objectui#4059, the very
defect the test's header cites as the reason the shape exists — was covered by
the builder's four write-time assertions and by nothing in the suite, since CI
runs the tests on an unbuilt worktree.
objectui#6405 re-pointed fields at the shared `createPluginStylesheetBuilder`,
so it now exports the same module shape the plugins do and the assertions apply
unchanged.
The `CARD_THEMED` entry is derived from the emitted sheet — surviving classes
whose declarations resolve a `--color-*` token from components' unpublished
`@theme` block — not read back off fields' own `MUST_SURVIVE`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgDDqh6YnkXqsnVTCa7wHk
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scripts/__tests__/plugin-published-stylesheet.test.ts pins the two plugin sheets but not @object-ui/fields, the one that is actually published

2 participants

@zhuangjianguo@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

test(scripts): pin @object-ui/fields' published stylesheet as a third subject - #7043

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin
Aug 31, 2026
Merged

test(scripts): pin @object-ui/fields' published stylesheet as a third subject#7043
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Fixes#6438

scripts/__tests__/plugin-published-stylesheet.test.ts ran its per-package
assertions over exactly two subjects, plugin-grid and plugin-kanban.
@object-ui/fields was not one of them — and it is the package whose stylesheet
has actually been shipping to consumers since #4059, the very defect the test's
own header cites as the reason the shape exists. Its dist/index.css was
guarded by the four write-time assertions inside the shared builder, which run
only during a build; CI runs this suite on an unbuilt worktree, so nothing in
the test run inspected it.

This adds fields as a third subject. The suite goes from 14 tests to 20
(three subjects times six per-package assertions, plus two standalone).

Premise re-verified on the merged ref

Re-read on main = e33b44796, item for item, rather than inherited:
packages/fields/scripts/build-css.mjs (notbuild-stylesheet.mjs) imports
createPluginStylesheetBuilder at line 94 and exports PACKAGE_ROOT / PACKAGE_NAME
(96/97), MUST_SURVIVE / CLASS_CEILING (114/132), builder / buildOptions
(161/163) behind the isEntrypoint guard (171) — the same shape the two plugins
export. SUBJECTS was at test line 91.

How the CARD_THEMED entry was derived

Independently, from the sheet the build actually emits — not read back off
fields' own MUST_SURVIVE, which would have looked identical while pinning
nothing.

Method: build fields' sheet through the shared builder, then keep every
surviving class whose own declarations resolve a --color-* token declared in
packages/components/src/index.css's @theme block (35 tokens) — the file that
package does not publish, which is exactly what makes an in-monorepo build the
only possible producer of these utilities.

That yields 17 surviving themed classes out of 163 surviving total. Two
independent corroborations:

Only 3 of the 17 appear in MUST_SURVIVE, so the list is demonstrably not that
list read back.

Banner: taken from buildOptions, and why nothing changed

fields passes a per-package header (HEADER, line 147, into buildOptions at
line 168); plugin-grid's buildOptions has no header key and inherits the
shared defaultHeader. The emitted sheet is header plus the sheet, so any
assertion reading the banner from the shared default would judge fields wrongly.

Surveyed before writing: no assertion in the suite reads the emitted banner,
so the caveat is preventive here, not corrective. The one assertion that
inspects the whole css string — "carries utilities only" — was checked against
fields' actual HEADER bytes and none of its three patterns can match it. The
module header now records the rule for anything added later. A banner pin is
not added here, for a reason recorded as a follow-up below.

Proof the new assertions have teeth

"The suite is green after I added it" is not evidence — a green assertion that
inspects nothing is precisely the defect this card records. Two ablations, each
proving the mutation reached disk before measuring, and each proving the restore
by blob hash rather than by exit code:

1. A themed utility stops being produced.hover:bg-primary/10 is in the
derived list and deliberately not in MUST_SURVIVE, so the builder's
write-time throw does not fire and mask the result. Its single usage site in
RecordPickerDialog.tsx was retargeted to hover:bg-primary/15.

  • on disk: occurrences of the removed text 1 to 0, injected text 0 to 1; blob moved 1e9d341d to 3e0a4915
  • result: Tests 1 failed | 19 passed, the failure being
    fields > emits the themed utilities only this build can produce with
    AssertionError: expected [ 'hover:bg-primary/10' ] to deeply equal []
  • restore: blob back to 1e9d341d, git diff HEAD empty

2. The manifest declaration breaks. fields' exports['./style.css'] was
pointed at ./dist/nope.css, which also proves the subject name resolves to
packages/fields.

  • on disk: injected 1, original pair 0; blob moved 5e442f18 to 98eeea6f
  • result: Tests 1 failed | 19 passed, the failure being
    fields > declares the export AND the step that produces it
  • restore: blob back to 5e442f18, git diff HEAD empty

In both runs exactly one assertion went red and it was a fields one, with
plugin-grid and plugin-kanban still green — so the red is subject-specific,
not a global break.

The finding that justifies the per-package coverage

Under ablation 1 the union assertion, "gives every themed utility the card
measured a producer", stayed green. Measured cause: plugin-grid also emits
hover:bg-primary/10, so the union was satisfied by another subject while
fields' own sheet had genuinely regressed. Adding fields to SUBJECTS is what
buys the coverage; adding it only to CARD_THEMED would have reproduced the
defect this card records.

Verification

Union run on the final commit, git rev-parse --short HEAD = 1219b8d88, tree clean:

  • npx vitest run scripts/__tests__/plugin-published-stylesheet.test.ts --maxWorkers=2Tests 20 passed (20), exit 0
  • pnpm type-check:scripts — exit 0. Load-bearing: the shared builder's own comment records that this reads the options types through this test file, and fields is the first subject to pass header.
  • pnpm type-check:coverage45/46 via type-check, 41/41 packages compile their tests
  • pnpm check:control-bytesOK (scanned 5850 tracked text file(s))
  • pnpm changeset:check — no major, fixed group OK
  • node scripts/check-changeset-presence.mjs — "no changeset is owed"; the changeset is an explicit no-release declaration in the empty-frontmatter shape this repo uses for test-only changes
  • eslint on the changed file — 0 errors, 0 warnings

Lint was narrowed to the changed file rather than run farm-wide, and the
narrowing is measured, not assumed: the file count comes from eslint's own
--format json output (1 file), and type-aware linting is not enabled in
eslint.config.js (no projectService, project: or parserOptions;
control term rules hits 10 times in the same file, so the query was live), so
this diff cannot move the verdict on any untouched file. CI runs the full farm
regardless.

Follow-up, filed not ridden along

The emitted banner is pinned by nothing, and it cannot be pinned cleanly today:
the shared builder does not export its defaultHeader, so an assertion covering
all three subjects would need a tolerant fallback in the test for the two
packages that declare no header — the consumer-side leniency this repo's
contract-first rule says to fix at the producer instead. That is a
producer-side change with its own review, so it is recorded rather than ridden
along here.


Generated by Claude Code

… subject
`plugin-published-stylesheet.test.ts` ran its per-package assertions over
`plugin-grid` and `plugin-kanban` only. `@object-ui/fields` — the package whose
sheet has actually been shipping to consumers since objectui#4059, the very
defect the test's header cites as the reason the shape exists — was covered by
the builder's four write-time assertions and by nothing in the suite, since CI
runs the tests on an unbuilt worktree.
objectui#6405 re-pointed fields at the shared `createPluginStylesheetBuilder`,
so it now exports the same module shape the plugins do and the assertions apply
unchanged.
The `CARD_THEMED` entry is derived from the emitted sheet — surviving classes
whose declarations resolve a `--color-*` token from components' unpublished
`@theme` block — not read back off fields' own `MUST_SURVIVE`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgDDqh6YnkXqsnVTCa7wHk
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scripts/__tests__/plugin-published-stylesheet.test.ts pins the two plugin sheets but not @object-ui/fields, the one that is actually published

2 participants

@zhuangjianguo@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(scripts): pin @object-ui/fields' published stylesheet as a third subject - #7043

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin
Aug 31, 2026
Merged

test(scripts): pin @object-ui/fields' published stylesheet as a third subject#7043
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Fixes#6438

scripts/__tests__/plugin-published-stylesheet.test.ts ran its per-package
assertions over exactly two subjects, plugin-grid and plugin-kanban.
@object-ui/fields was not one of them — and it is the package whose stylesheet
has actually been shipping to consumers since #4059, the very defect the test's
own header cites as the reason the shape exists. Its dist/index.css was
guarded by the four write-time assertions inside the shared builder, which run
only during a build; CI runs this suite on an unbuilt worktree, so nothing in
the test run inspected it.

This adds fields as a third subject. The suite goes from 14 tests to 20
(three subjects times six per-package assertions, plus two standalone).

Premise re-verified on the merged ref

Re-read on main = e33b44796, item for item, rather than inherited:
packages/fields/scripts/build-css.mjs (notbuild-stylesheet.mjs) imports
createPluginStylesheetBuilder at line 94 and exports PACKAGE_ROOT / PACKAGE_NAME
(96/97), MUST_SURVIVE / CLASS_CEILING (114/132), builder / buildOptions
(161/163) behind the isEntrypoint guard (171) — the same shape the two plugins
export. SUBJECTS was at test line 91.

How the CARD_THEMED entry was derived

Independently, from the sheet the build actually emits — not read back off
fields' own MUST_SURVIVE, which would have looked identical while pinning
nothing.

Method: build fields' sheet through the shared builder, then keep every
surviving class whose own declarations resolve a --color-* token declared in
packages/components/src/index.css's @theme block (35 tokens) — the file that
package does not publish, which is exactly what makes an in-monorepo build the
only possible producer of these utilities.

That yields 17 surviving themed classes out of 163 surviving total. Two
independent corroborations:

Only 3 of the 17 appear in MUST_SURVIVE, so the list is demonstrably not that
list read back.

Banner: taken from buildOptions, and why nothing changed

fields passes a per-package header (HEADER, line 147, into buildOptions at
line 168); plugin-grid's buildOptions has no header key and inherits the
shared defaultHeader. The emitted sheet is header plus the sheet, so any
assertion reading the banner from the shared default would judge fields wrongly.

Surveyed before writing: no assertion in the suite reads the emitted banner,
so the caveat is preventive here, not corrective. The one assertion that
inspects the whole css string — "carries utilities only" — was checked against
fields' actual HEADER bytes and none of its three patterns can match it. The
module header now records the rule for anything added later. A banner pin is
not added here, for a reason recorded as a follow-up below.

Proof the new assertions have teeth

"The suite is green after I added it" is not evidence — a green assertion that
inspects nothing is precisely the defect this card records. Two ablations, each
proving the mutation reached disk before measuring, and each proving the restore
by blob hash rather than by exit code:

1. A themed utility stops being produced.hover:bg-primary/10 is in the
derived list and deliberately not in MUST_SURVIVE, so the builder's
write-time throw does not fire and mask the result. Its single usage site in
RecordPickerDialog.tsx was retargeted to hover:bg-primary/15.

  • on disk: occurrences of the removed text 1 to 0, injected text 0 to 1; blob moved 1e9d341d to 3e0a4915
  • result: Tests 1 failed | 19 passed, the failure being
    fields > emits the themed utilities only this build can produce with
    AssertionError: expected [ 'hover:bg-primary/10' ] to deeply equal []
  • restore: blob back to 1e9d341d, git diff HEAD empty

2. The manifest declaration breaks. fields' exports['./style.css'] was
pointed at ./dist/nope.css, which also proves the subject name resolves to
packages/fields.

  • on disk: injected 1, original pair 0; blob moved 5e442f18 to 98eeea6f
  • result: Tests 1 failed | 19 passed, the failure being
    fields > declares the export AND the step that produces it
  • restore: blob back to 5e442f18, git diff HEAD empty

In both runs exactly one assertion went red and it was a fields one, with
plugin-grid and plugin-kanban still green — so the red is subject-specific,
not a global break.

The finding that justifies the per-package coverage

Under ablation 1 the union assertion, "gives every themed utility the card
measured a producer", stayed green. Measured cause: plugin-grid also emits
hover:bg-primary/10, so the union was satisfied by another subject while
fields' own sheet had genuinely regressed. Adding fields to SUBJECTS is what
buys the coverage; adding it only to CARD_THEMED would have reproduced the
defect this card records.

Verification

Union run on the final commit, git rev-parse --short HEAD = 1219b8d88, tree clean:

  • npx vitest run scripts/__tests__/plugin-published-stylesheet.test.ts --maxWorkers=2Tests 20 passed (20), exit 0
  • pnpm type-check:scripts — exit 0. Load-bearing: the shared builder's own comment records that this reads the options types through this test file, and fields is the first subject to pass header.
  • pnpm type-check:coverage45/46 via type-check, 41/41 packages compile their tests
  • pnpm check:control-bytesOK (scanned 5850 tracked text file(s))
  • pnpm changeset:check — no major, fixed group OK
  • node scripts/check-changeset-presence.mjs — "no changeset is owed"; the changeset is an explicit no-release declaration in the empty-frontmatter shape this repo uses for test-only changes
  • eslint on the changed file — 0 errors, 0 warnings

Lint was narrowed to the changed file rather than run farm-wide, and the
narrowing is measured, not assumed: the file count comes from eslint's own
--format json output (1 file), and type-aware linting is not enabled in
eslint.config.js (no projectService, project: or parserOptions;
control term rules hits 10 times in the same file, so the query was live), so
this diff cannot move the verdict on any untouched file. CI runs the full farm
regardless.

Follow-up, filed not ridden along

The emitted banner is pinned by nothing, and it cannot be pinned cleanly today:
the shared builder does not export its defaultHeader, so an assertion covering
all three subjects would need a tolerant fallback in the test for the two
packages that declare no header — the consumer-side leniency this repo's
contract-first rule says to fix at the producer instead. That is a
producer-side change with its own review, so it is recorded rather than ridden
along here.


Generated by Claude Code

… subject
`plugin-published-stylesheet.test.ts` ran its per-package assertions over
`plugin-grid` and `plugin-kanban` only. `@object-ui/fields` — the package whose
sheet has actually been shipping to consumers since objectui#4059, the very
defect the test's header cites as the reason the shape exists — was covered by
the builder's four write-time assertions and by nothing in the suite, since CI
runs the tests on an unbuilt worktree.
objectui#6405 re-pointed fields at the shared `createPluginStylesheetBuilder`,
so it now exports the same module shape the plugins do and the assertions apply
unchanged.
The `CARD_THEMED` entry is derived from the emitted sheet — surviving classes
whose declarations resolve a `--color-*` token from components' unpublished
`@theme` block — not read back off fields' own `MUST_SURVIVE`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgDDqh6YnkXqsnVTCa7wHk
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scripts/__tests__/plugin-published-stylesheet.test.ts pins the two plugin sheets but not @object-ui/fields, the one that is actually published

2 participants

@zhuangjianguo@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

test(scripts): pin @object-ui/fields' published stylesheet as a third subject - #7043

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin
Aug 31, 2026
Merged

test(scripts): pin @object-ui/fields' published stylesheet as a third subject#7043
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Fixes#6438

scripts/__tests__/plugin-published-stylesheet.test.ts ran its per-package
assertions over exactly two subjects, plugin-grid and plugin-kanban.
@object-ui/fields was not one of them — and it is the package whose stylesheet
has actually been shipping to consumers since #4059, the very defect the test's
own header cites as the reason the shape exists. Its dist/index.css was
guarded by the four write-time assertions inside the shared builder, which run
only during a build; CI runs this suite on an unbuilt worktree, so nothing in
the test run inspected it.

This adds fields as a third subject. The suite goes from 14 tests to 20
(three subjects times six per-package assertions, plus two standalone).

Premise re-verified on the merged ref

Re-read on main = e33b44796, item for item, rather than inherited:
packages/fields/scripts/build-css.mjs (notbuild-stylesheet.mjs) imports
createPluginStylesheetBuilder at line 94 and exports PACKAGE_ROOT / PACKAGE_NAME
(96/97), MUST_SURVIVE / CLASS_CEILING (114/132), builder / buildOptions
(161/163) behind the isEntrypoint guard (171) — the same shape the two plugins
export. SUBJECTS was at test line 91.

How the CARD_THEMED entry was derived

Independently, from the sheet the build actually emits — not read back off
fields' own MUST_SURVIVE, which would have looked identical while pinning
nothing.

Method: build fields' sheet through the shared builder, then keep every
surviving class whose own declarations resolve a --color-* token declared in
packages/components/src/index.css's @theme block (35 tokens) — the file that
package does not publish, which is exactly what makes an in-monorepo build the
only possible producer of these utilities.

That yields 17 surviving themed classes out of 163 surviving total. Two
independent corroborations:

Only 3 of the 17 appear in MUST_SURVIVE, so the list is demonstrably not that
list read back.

Banner: taken from buildOptions, and why nothing changed

fields passes a per-package header (HEADER, line 147, into buildOptions at
line 168); plugin-grid's buildOptions has no header key and inherits the
shared defaultHeader. The emitted sheet is header plus the sheet, so any
assertion reading the banner from the shared default would judge fields wrongly.

Surveyed before writing: no assertion in the suite reads the emitted banner,
so the caveat is preventive here, not corrective. The one assertion that
inspects the whole css string — "carries utilities only" — was checked against
fields' actual HEADER bytes and none of its three patterns can match it. The
module header now records the rule for anything added later. A banner pin is
not added here, for a reason recorded as a follow-up below.

Proof the new assertions have teeth

"The suite is green after I added it" is not evidence — a green assertion that
inspects nothing is precisely the defect this card records. Two ablations, each
proving the mutation reached disk before measuring, and each proving the restore
by blob hash rather than by exit code:

1. A themed utility stops being produced.hover:bg-primary/10 is in the
derived list and deliberately not in MUST_SURVIVE, so the builder's
write-time throw does not fire and mask the result. Its single usage site in
RecordPickerDialog.tsx was retargeted to hover:bg-primary/15.

  • on disk: occurrences of the removed text 1 to 0, injected text 0 to 1; blob moved 1e9d341d to 3e0a4915
  • result: Tests 1 failed | 19 passed, the failure being
    fields > emits the themed utilities only this build can produce with
    AssertionError: expected [ 'hover:bg-primary/10' ] to deeply equal []
  • restore: blob back to 1e9d341d, git diff HEAD empty

2. The manifest declaration breaks. fields' exports['./style.css'] was
pointed at ./dist/nope.css, which also proves the subject name resolves to
packages/fields.

  • on disk: injected 1, original pair 0; blob moved 5e442f18 to 98eeea6f
  • result: Tests 1 failed | 19 passed, the failure being
    fields > declares the export AND the step that produces it
  • restore: blob back to 5e442f18, git diff HEAD empty

In both runs exactly one assertion went red and it was a fields one, with
plugin-grid and plugin-kanban still green — so the red is subject-specific,
not a global break.

The finding that justifies the per-package coverage

Under ablation 1 the union assertion, "gives every themed utility the card
measured a producer", stayed green. Measured cause: plugin-grid also emits
hover:bg-primary/10, so the union was satisfied by another subject while
fields' own sheet had genuinely regressed. Adding fields to SUBJECTS is what
buys the coverage; adding it only to CARD_THEMED would have reproduced the
defect this card records.

Verification

Union run on the final commit, git rev-parse --short HEAD = 1219b8d88, tree clean:

  • npx vitest run scripts/__tests__/plugin-published-stylesheet.test.ts --maxWorkers=2Tests 20 passed (20), exit 0
  • pnpm type-check:scripts — exit 0. Load-bearing: the shared builder's own comment records that this reads the options types through this test file, and fields is the first subject to pass header.
  • pnpm type-check:coverage45/46 via type-check, 41/41 packages compile their tests
  • pnpm check:control-bytesOK (scanned 5850 tracked text file(s))
  • pnpm changeset:check — no major, fixed group OK
  • node scripts/check-changeset-presence.mjs — "no changeset is owed"; the changeset is an explicit no-release declaration in the empty-frontmatter shape this repo uses for test-only changes
  • eslint on the changed file — 0 errors, 0 warnings

Lint was narrowed to the changed file rather than run farm-wide, and the
narrowing is measured, not assumed: the file count comes from eslint's own
--format json output (1 file), and type-aware linting is not enabled in
eslint.config.js (no projectService, project: or parserOptions;
control term rules hits 10 times in the same file, so the query was live), so
this diff cannot move the verdict on any untouched file. CI runs the full farm
regardless.

Follow-up, filed not ridden along

The emitted banner is pinned by nothing, and it cannot be pinned cleanly today:
the shared builder does not export its defaultHeader, so an assertion covering
all three subjects would need a tolerant fallback in the test for the two
packages that declare no header — the consumer-side leniency this repo's
contract-first rule says to fix at the producer instead. That is a
producer-side change with its own review, so it is recorded rather than ridden
along here.


Generated by Claude Code

… subject
`plugin-published-stylesheet.test.ts` ran its per-package assertions over
`plugin-grid` and `plugin-kanban` only. `@object-ui/fields` — the package whose
sheet has actually been shipping to consumers since objectui#4059, the very
defect the test's header cites as the reason the shape exists — was covered by
the builder's four write-time assertions and by nothing in the suite, since CI
runs the tests on an unbuilt worktree.
objectui#6405 re-pointed fields at the shared `createPluginStylesheetBuilder`,
so it now exports the same module shape the plugins do and the assertions apply
unchanged.
The `CARD_THEMED` entry is derived from the emitted sheet — surviving classes
whose declarations resolve a `--color-*` token from components' unpublished
`@theme` block — not read back off fields' own `MUST_SURVIVE`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgDDqh6YnkXqsnVTCa7wHk
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scripts/__tests__/plugin-published-stylesheet.test.ts pins the two plugin sheets but not @object-ui/fields, the one that is actually published

2 participants

@zhuangjianguo@claude
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

test(scripts): pin @object-ui/fields' published stylesheet as a third subject - #7043

Merged
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin
Aug 31, 2026
Merged

test(scripts): pin @object-ui/fields' published stylesheet as a third subject#7043
zhuangjianguo merged 1 commit into
mainfrom
claude/issue-6438-fields-stylesheet-pin

Conversation

@zhuangjianguo

Copy link
Copy Markdown
Collaborator

Fixes#6438

scripts/__tests__/plugin-published-stylesheet.test.ts ran its per-package
assertions over exactly two subjects, plugin-grid and plugin-kanban.
@object-ui/fields was not one of them — and it is the package whose stylesheet
has actually been shipping to consumers since #4059, the very defect the test's
own header cites as the reason the shape exists. Its dist/index.css was
guarded by the four write-time assertions inside the shared builder, which run
only during a build; CI runs this suite on an unbuilt worktree, so nothing in
the test run inspected it.

This adds fields as a third subject. The suite goes from 14 tests to 20
(three subjects times six per-package assertions, plus two standalone).

Premise re-verified on the merged ref

Re-read on main = e33b44796, item for item, rather than inherited:
packages/fields/scripts/build-css.mjs (notbuild-stylesheet.mjs) imports
createPluginStylesheetBuilder at line 94 and exports PACKAGE_ROOT / PACKAGE_NAME
(96/97), MUST_SURVIVE / CLASS_CEILING (114/132), builder / buildOptions
(161/163) behind the isEntrypoint guard (171) — the same shape the two plugins
export. SUBJECTS was at test line 91.

How the CARD_THEMED entry was derived

Independently, from the sheet the build actually emits — not read back off
fields' own MUST_SURVIVE, which would have looked identical while pinning
nothing.

Method: build fields' sheet through the shared builder, then keep every
surviving class whose own declarations resolve a --color-* token declared in
packages/components/src/index.css's @theme block (35 tokens) — the file that
package does not publish, which is exactly what makes an in-monorepo build the
only possible producer of these utilities.

That yields 17 surviving themed classes out of 163 surviving total. Two
independent corroborations:

Only 3 of the 17 appear in MUST_SURVIVE, so the list is demonstrably not that
list read back.

Banner: taken from buildOptions, and why nothing changed

fields passes a per-package header (HEADER, line 147, into buildOptions at
line 168); plugin-grid's buildOptions has no header key and inherits the
shared defaultHeader. The emitted sheet is header plus the sheet, so any
assertion reading the banner from the shared default would judge fields wrongly.

Surveyed before writing: no assertion in the suite reads the emitted banner,
so the caveat is preventive here, not corrective. The one assertion that
inspects the whole css string — "carries utilities only" — was checked against
fields' actual HEADER bytes and none of its three patterns can match it. The
module header now records the rule for anything added later. A banner pin is
not added here, for a reason recorded as a follow-up below.

Proof the new assertions have teeth

"The suite is green after I added it" is not evidence — a green assertion that
inspects nothing is precisely the defect this card records. Two ablations, each
proving the mutation reached disk before measuring, and each proving the restore
by blob hash rather than by exit code:

1. A themed utility stops being produced.hover:bg-primary/10 is in the
derived list and deliberately not in MUST_SURVIVE, so the builder's
write-time throw does not fire and mask the result. Its single usage site in
RecordPickerDialog.tsx was retargeted to hover:bg-primary/15.

  • on disk: occurrences of the removed text 1 to 0, injected text 0 to 1; blob moved 1e9d341d to 3e0a4915
  • result: Tests 1 failed | 19 passed, the failure being
    fields > emits the themed utilities only this build can produce with
    AssertionError: expected [ 'hover:bg-primary/10' ] to deeply equal []
  • restore: blob back to 1e9d341d, git diff HEAD empty

2. The manifest declaration breaks. fields' exports['./style.css'] was
pointed at ./dist/nope.css, which also proves the subject name resolves to
packages/fields.

  • on disk: injected 1, original pair 0; blob moved 5e442f18 to 98eeea6f
  • result: Tests 1 failed | 19 passed, the failure being
    fields > declares the export AND the step that produces it
  • restore: blob back to 5e442f18, git diff HEAD empty

In both runs exactly one assertion went red and it was a fields one, with
plugin-grid and plugin-kanban still green — so the red is subject-specific,
not a global break.

The finding that justifies the per-package coverage

Under ablation 1 the union assertion, "gives every themed utility the card
measured a producer", stayed green. Measured cause: plugin-grid also emits
hover:bg-primary/10, so the union was satisfied by another subject while
fields' own sheet had genuinely regressed. Adding fields to SUBJECTS is what
buys the coverage; adding it only to CARD_THEMED would have reproduced the
defect this card records.

Verification

Union run on the final commit, git rev-parse --short HEAD = 1219b8d88, tree clean:

  • npx vitest run scripts/__tests__/plugin-published-stylesheet.test.ts --maxWorkers=2Tests 20 passed (20), exit 0
  • pnpm type-check:scripts — exit 0. Load-bearing: the shared builder's own comment records that this reads the options types through this test file, and fields is the first subject to pass header.
  • pnpm type-check:coverage45/46 via type-check, 41/41 packages compile their tests
  • pnpm check:control-bytesOK (scanned 5850 tracked text file(s))
  • pnpm changeset:check — no major, fixed group OK
  • node scripts/check-changeset-presence.mjs — "no changeset is owed"; the changeset is an explicit no-release declaration in the empty-frontmatter shape this repo uses for test-only changes
  • eslint on the changed file — 0 errors, 0 warnings

Lint was narrowed to the changed file rather than run farm-wide, and the
narrowing is measured, not assumed: the file count comes from eslint's own
--format json output (1 file), and type-aware linting is not enabled in
eslint.config.js (no projectService, project: or parserOptions;
control term rules hits 10 times in the same file, so the query was live), so
this diff cannot move the verdict on any untouched file. CI runs the full farm
regardless.

Follow-up, filed not ridden along

The emitted banner is pinned by nothing, and it cannot be pinned cleanly today:
the shared builder does not export its defaultHeader, so an assertion covering
all three subjects would need a tolerant fallback in the test for the two
packages that declare no header — the consumer-side leniency this repo's
contract-first rule says to fix at the producer instead. That is a
producer-side change with its own review, so it is recorded rather than ridden
along here.


Generated by Claude Code

… subject
`plugin-published-stylesheet.test.ts` ran its per-package assertions over
`plugin-grid` and `plugin-kanban` only. `@object-ui/fields` — the package whose
sheet has actually been shipping to consumers since objectui#4059, the very
defect the test's header cites as the reason the shape exists — was covered by
the builder's four write-time assertions and by nothing in the suite, since CI
runs the tests on an unbuilt worktree.
objectui#6405 re-pointed fields at the shared `createPluginStylesheetBuilder`,
so it now exports the same module shape the plugins do and the assertions apply
unchanged.
The `CARD_THEMED` entry is derived from the emitted sheet — surviving classes
whose declarations resolve a `--color-*` token from components' unpublished
`@theme` block — not read back off fields' own `MUST_SURVIVE`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GgDDqh6YnkXqsnVTCa7wHk
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scripts/__tests__/plugin-published-stylesheet.test.ts pins the two plugin sheets but not @object-ui/fields, the one that is actually published

2 participants

@zhuangjianguo@claude