feat: define semantic palette roles #60

Merged
bjoern merged 3 commits from feat/semantic-tone-contract into main 2026-10-23 17:54:03 +02:00
Member

B2 — semantic palette consistency: consumers can now customize readable semantic text, authored subtle surfaces and strong graphical colors independently across the library, using the existing theme-boundary contract.

What's in

  • Define 22 live semantic roles: Neutral, Accent, Info, Success, Warning and Danger each own strong, text and subtle colors; the two supported solid-action families also own hover and contrast colors. All roles resolve at root and nested ThemeScope boundaries from inherited light/dark/override inputs.
  • Give Badge and InlineAlert the same exact text/subtle treatment for every tone. Toast retains ordinary body text with a semantic edge/icon; StatusDot and UsageBar retain strong graphical marks. Map errors, links and destructive text to text roles while retaining strong borders and fills.
  • Correct default Success/Warning light text, Accent dark text and categorical light foreground contrast. Diff uses authored line surfaces and underline/weight word emphasis. Crop handles use the Accent contrast role.
  • Reject undefined Tone values consistently, including closed Toasts, categorical Badges and hidden usage branches. Fix Success InlineAlert's existing missing catalog glyph and assert a real rendered SVG path.
  • Add a complete customization/migration guide, a copyable 44-input consumer palette and a real Razor SemanticDemo. Migrate the existing ThemeDemo recipe.

Breaking contract and migration

  • Semantic prose must consume --<tone>-text; --<tone> remains the strong graphical/border/solid-fill role.
  • Author text and subtle inputs deliberately alongside strong colors; they are independent.
  • Remove --on-state and its input families. Destructive solid actions consume --danger-contrast.
  • Neutral has independent roles, and Alert/Diff surfaces are authored rather than generated translucent washes. Invalid Tone casts now throw even when a render branch would hide them.

See the complete semantic guide. Typography, density/radii, broader focus/overlay, shell and motion/disabled policies remain separate work.

Tests

  • Solution build: zero warnings/errors.
  • 1,211/1,211 normal and UTC, zero skipped; 33 new rendered cases preserve tone classes, message/usage/ARIA behavior and real icons, and reject invalid values across obscured branches.
  • Actual SemanticDemo compiled-CSS contracts: 38/38 Chromium and 38/38 Firefox. Both OS preferences, static SSR without JS, all 22 outputs, root/local/nested/sibling modes, shared overrides, independent role sentinels, hover, default and documented-recipe contrast, all categorical pairs, Diff, validation and mobile scroll/overflow.
  • Actual existing ThemeDemo host: 31/31 Chromium and 31/31 Firefox.
  • Separate independent complete-diff adversarial review approved the final head. Second isolated behavioral reviewer independently repeated the 1,211 normal/UTC baseline and 38 Chromium groups; 9/9 mutations killed, with every restored baseline passing: neutralized Alert roles, Badge strong/text confusion, coupled Danger foreground, missing scope resolution, Diff wash, bright categorical color, hidden Badge validation, closed Toast validation and missing Success glyph. No survivors.
  • WebKit unavailable because required system libraries are missing. Reduced-motion, forced-colors and broader focus behavior are outside this palette verification.

Consumer verification and merge order

Shikigami's prepared consumer migration maps five application CSS sites to the appropriate text roles and amends ADR 0009. It passes 6,360/6,360 normal and UTC, plus 9 existing theme and 4 new semantic browser groups, against the isolated seeded sample world and local OpenRouter stub. Consumer identity/prose colors retain their separate application contract.

This library PR must receive CI/Jibril approval and Bjoern's merge first. The Shikigami PR will then pin the actual merged library commit and receive its own validation and reviews.

Browser-verified screenshots

Actual Razor library sample, not a mockup. Screenshots were inspected after the final Success icon fix. The T3 preview snapshot step timed out twice; capture used the documented Playwright fallback. Raw image URLs return PNG content.

Desktop 1440×1442, default Light and Dark palettes, all six tone treatments:

Default semantic palette desktop comparison

Mobile 390×844, Dark scope, complete documented consumer palette applied, scrolled to Warning/Danger and actions:

Customized semantic palette on mobile

B2 — semantic palette consistency: consumers can now customize readable semantic text, authored subtle surfaces and strong graphical colors independently across the library, using the existing theme-boundary contract. ## What's in - Define 22 live semantic roles: Neutral, Accent, Info, Success, Warning and Danger each own strong, text and subtle colors; the two supported solid-action families also own hover and contrast colors. All roles resolve at root and nested ThemeScope boundaries from inherited light/dark/override inputs. - Give Badge and InlineAlert the same exact text/subtle treatment for every tone. Toast retains ordinary body text with a semantic edge/icon; StatusDot and UsageBar retain strong graphical marks. Map errors, links and destructive text to text roles while retaining strong borders and fills. - Correct default Success/Warning light text, Accent dark text and categorical light foreground contrast. Diff uses authored line surfaces and underline/weight word emphasis. Crop handles use the Accent contrast role. - Reject undefined Tone values consistently, including closed Toasts, categorical Badges and hidden usage branches. Fix Success InlineAlert's existing missing catalog glyph and assert a real rendered SVG path. - Add a complete customization/migration guide, a copyable 44-input consumer palette and a real Razor SemanticDemo. Migrate the existing ThemeDemo recipe. ## Breaking contract and migration - Semantic prose must consume `--<tone>-text`; `--<tone>` remains the strong graphical/border/solid-fill role. - Author text and subtle inputs deliberately alongside strong colors; they are independent. - Remove `--on-state` and its input families. Destructive solid actions consume `--danger-contrast`. - Neutral has independent roles, and Alert/Diff surfaces are authored rather than generated translucent washes. Invalid Tone casts now throw even when a render branch would hide them. See [the complete semantic guide](https://git.kagaku.eu/TeamAI/Kagaku.UI/src/commit/e319c65a390780275480c5f3b3386f1f2ba51c79/docs/semantic-colors.md). Typography, density/radii, broader focus/overlay, shell and motion/disabled policies remain separate work. ## Tests - Solution build: zero warnings/errors. - **1,211/1,211 normal and UTC**, zero skipped; **33 new rendered cases** preserve tone classes, message/usage/ARIA behavior and real icons, and reject invalid values across obscured branches. - Actual SemanticDemo compiled-CSS contracts: **38/38 Chromium and 38/38 Firefox**. Both OS preferences, static SSR without JS, all 22 outputs, root/local/nested/sibling modes, shared overrides, independent role sentinels, hover, default and documented-recipe contrast, all categorical pairs, Diff, validation and mobile scroll/overflow. - Actual existing ThemeDemo host: **31/31 Chromium and 31/31 Firefox**. - Separate independent complete-diff adversarial review approved the final head. Second isolated behavioral reviewer independently repeated the 1,211 normal/UTC baseline and 38 Chromium groups; **9/9 mutations killed**, with every restored baseline passing: neutralized Alert roles, Badge strong/text confusion, coupled Danger foreground, missing scope resolution, Diff wash, bright categorical color, hidden Badge validation, closed Toast validation and missing Success glyph. No survivors. - WebKit unavailable because required system libraries are missing. Reduced-motion, forced-colors and broader focus behavior are outside this palette verification. ## Consumer verification and merge order Shikigami's prepared consumer migration maps five application CSS sites to the appropriate text roles and amends ADR 0009. It passes **6,360/6,360 normal and UTC**, plus **9 existing theme and 4 new semantic browser groups**, against the isolated seeded sample world and local OpenRouter stub. Consumer identity/prose colors retain their separate application contract. This library PR must receive CI/Jibril approval and Bjoern's merge first. The Shikigami PR will then pin the actual merged library commit and receive its own validation and reviews. ## Browser-verified screenshots Actual Razor library sample, not a mockup. Screenshots were inspected after the final Success icon fix. The T3 preview snapshot step timed out twice; capture used the documented Playwright fallback. Raw image URLs return PNG content. Desktop 1440×1442, default Light and Dark palettes, all six tone treatments: ![Default semantic palette desktop comparison](https://git.kagaku.eu/TeamAI/Kagaku.UI/raw/commit/e319c65a390780275480c5f3b3386f1f2ba51c79/docs/images/semantic-palette-desktop.png) Mobile 390×844, Dark scope, complete documented consumer palette applied, scrolled to Warning/Danger and actions: ![Customized semantic palette on mobile](https://git.kagaku.eu/TeamAI/Kagaku.UI/raw/commit/e319c65a390780275480c5f3b3386f1f2ba51c79/docs/images/semantic-palette-mobile.png)
fix: render the success alert status icon
All checks were successful
CI / build (pull_request) Successful in 16s
CI / test (pull_request) Successful in 27s
6befe30222

Summary

Summary
Generated on: 10/23/2026 - 15:29:59
Coverage date: 10/23/2026 - 15:29:55 - 10/23/2026 - 15:29:57
Parser: MultiReport (2x Cobertura)
Assemblies: 2
Classes: 113
Files: 106
Line coverage: 97.2% (2867 of 2947)
Covered lines: 2867
Uncovered lines: 80
Coverable lines: 2947
Total lines: 7690
Branch coverage: 93.1% (1896 of 2035)
Covered branches: 1896
Total branches: 2035
Method coverage: Feature is only available for sponsors

Coverage

Kagaku.UI - 97.2%
Name Line Branch
Kagaku.UI 97.2% 93.2%
Kagaku.UI.AdaptiveNavigation 100% 100%
Kagaku.UI.AppBar 100% 100%
Kagaku.UI.AppScaffold 100% 100%
Kagaku.UI.AudioPlaybackState 100%
Kagaku.UI.AudioPlayer 100% 93.5%
Kagaku.UI.AudioPlayerLabels 100%
Kagaku.UI.Badge 100% 100%
Kagaku.UI.Breadcrumb 100%
Kagaku.UI.BreadcrumbItem 100% 100%
Kagaku.UI.Button 100% 100%
Kagaku.UI.Card 100% 100%
Kagaku.UI.ChatMessage 100% 100%
Kagaku.UI.ChipGroup`1 100% 100%
Kagaku.UI.ChipOption`1 100%
Kagaku.UI.CircuitErrorPanel 100%
Kagaku.UI.ColorField 100% 96.8%
Kagaku.UI.Column 100%
Kagaku.UI.Columns 100% 100%
Kagaku.UI.Combobox`1 98.1% 91.8%
Kagaku.UI.ConfirmDialog 100% 100%
Kagaku.UI.Constrain 100% 100%
Kagaku.UI.ContextMenu 92.1% 94.4%
Kagaku.UI.CssClassExtensions 100% 100%
Kagaku.UI.Debounce 97.8% 80.7%
Kagaku.UI.DebouncedSearchField 100% 87.5%
Kagaku.UI.DiffLine 100%
Kagaku.UI.DiffResult 100%
Kagaku.UI.DiffRow 100%
Kagaku.UI.DiffSegment 100%
Kagaku.UI.DiffView 100% 98.3%
Kagaku.UI.Disclosure 100% 100%
Kagaku.UI.DocumentTitle 76.9% 100%
Kagaku.UI.DragReorderList`1 93.5% 75%
Kagaku.UI.Drawer 97.5% 93.7%
Kagaku.UI.EmptyState 100% 100%
Kagaku.UI.Field 100% 95.4%
Kagaku.UI.FileUpload 100% 93.7%
Kagaku.UI.FixedColumn 100%
Kagaku.UI.FixedRow 100%
Kagaku.UI.FlexColumn 100%
Kagaku.UI.Flexible 100%
Kagaku.UI.FlexRow 100%
Kagaku.UI.FloatingActionButton 100%
Kagaku.UI.Hotkey 92.5% 87.5%
Kagaku.UI.Icon 100% 100%
Kagaku.UI.IconCatalog 100%
Kagaku.UI.InfoTip 100%
Kagaku.UI.InlineAlert 100% 100%
Kagaku.UI.InputFieldBase 96.4% 93.4%
Kagaku.UI.InspectionSection 100% 100%
Kagaku.UI.LabeledEntriesTable 96.7% 66.6%
Kagaku.UI.LabeledEntry 100%
Kagaku.UI.LayoutCss 95.2% 93.7%
Kagaku.UI.Lightbox 83.7% 85%
Kagaku.UI.LiveValue 100% 100%
Kagaku.UI.LiveValueInterop 100% 100%
Kagaku.UI.Markdown 98.6% 94.5%
Kagaku.UI.MaskCanvas 94.1% 90.1%
Kagaku.UI.MaskedSecretField 96.4% 83.3%
Kagaku.UI.MaskPoint 100%
Kagaku.UI.MaskPrimitive 100%
Kagaku.UI.Menu 90% 75%
Kagaku.UI.MenuItem 100% 87.5%
Kagaku.UI.Modal 88.8% 90.9%
Kagaku.UI.NavGroup 100% 100%
Kagaku.UI.NavigationToggle 100%
Kagaku.UI.NavItem 92.1% 96.1%
Kagaku.UI.NavList 100%
Kagaku.UI.NumberField`1 98.9% 92.3%
Kagaku.UI.PageShell 100% 100%
Kagaku.UI.PreviewImage 100% 100%
Kagaku.UI.ProseFonts 100%
Kagaku.UI.QuicklinkNav 80.5% 95.8%
Kagaku.UI.QuicklinkSection 100%
Kagaku.UI.QuotedSpeech 94.8% 94.2%
Kagaku.UI.QuotedSpeechExtension 100% 100%
Kagaku.UI.RadioCard`1 100%
Kagaku.UI.RadioCards`1 100% 100%
Kagaku.UI.RegionPoint 100% 100%
Kagaku.UI.RegionRect 90% 100%
Kagaku.UI.RegionSelector 85.5% 87.5%
Kagaku.UI.RelativeTime 100% 93.7%
Kagaku.UI.Row 100%
Kagaku.UI.Rows 100% 100%
Kagaku.UI.SaveIndicator 100% 100%
Kagaku.UI.ScrollViewer 100% 100%
Kagaku.UI.Select`1 100% 100%
Kagaku.UI.SelectableGrid`1 95.5% 89.1%
Kagaku.UI.SelectOption`1 100%
Kagaku.UI.Separator 100%
Kagaku.UI.Slider 100% 93.3%
Kagaku.UI.Splat 100% 95.4%
Kagaku.UI.StatusDot 100%
Kagaku.UI.Switch 100% 100%
Kagaku.UI.Tab 100% 100%
Kagaku.UI.Table`1 100% 88.4%
Kagaku.UI.TableColumn`1 100%
Kagaku.UI.Tabs 95.9% 84.4%
Kagaku.UI.TextArea 100%
Kagaku.UI.TextDiff 100% 98.8%
Kagaku.UI.TextField 100%
Kagaku.UI.ThemeScope 100% 100%
Kagaku.UI.ThemeSwitcher 100% 100%
Kagaku.UI.Toast 96.5% 90%
Kagaku.UI.ToastRegion 100%
Kagaku.UI.ToggleButtonGroup`1 100% 100%
Kagaku.UI.ToggleOption`1 100%
Kagaku.UI.TypingIndicator 100%
Kagaku.UI.UsageBar 100% 94.4%
Kagaku.UI.UsageSegment 100%
Kagaku.UI.Fluxor - 97.7%
Name Line Branch
Kagaku.UI.Fluxor 97.7% 83.3%
Kagaku.UI.Fluxor.CircuitError 100%
Kagaku.UI.Fluxor.CircuitErrorSink 100% 91.6%
Kagaku.UI.Fluxor.StoreInitializer 92.8% 66.6%
<!-- coverage-comment --> # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 10/23/2026 - 15:29:59 | | Coverage date: | 10/23/2026 - 15:29:55 - 10/23/2026 - 15:29:57 | | Parser: | MultiReport (2x Cobertura) | | Assemblies: | 2 | | Classes: | 113 | | Files: | 106 | | **Line coverage:** | 97.2% (2867 of 2947) | | Covered lines: | 2867 | | Uncovered lines: | 80 | | Coverable lines: | 2947 | | Total lines: | 7690 | | **Branch coverage:** | 93.1% (1896 of 2035) | | Covered branches: | 1896 | | Total branches: | 2035 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Kagaku.UI - 97.2%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Kagaku.UI**|**97.2%**|**93.2%**| |Kagaku.UI.AdaptiveNavigation|100%|100%| |Kagaku.UI.AppBar|100%|100%| |Kagaku.UI.AppScaffold|100%|100%| |Kagaku.UI.AudioPlaybackState|100%|| |Kagaku.UI.AudioPlayer|100%|93.5%| |Kagaku.UI.AudioPlayerLabels|100%|| |Kagaku.UI.Badge|100%|100%| |Kagaku.UI.Breadcrumb|100%|| |Kagaku.UI.BreadcrumbItem|100%|100%| |Kagaku.UI.Button|100%|100%| |Kagaku.UI.Card|100%|100%| |Kagaku.UI.ChatMessage|100%|100%| |Kagaku.UI.ChipGroup`1|100%|100%| |Kagaku.UI.ChipOption`1|100%|| |Kagaku.UI.CircuitErrorPanel|100%|| |Kagaku.UI.ColorField|100%|96.8%| |Kagaku.UI.Column|100%|| |Kagaku.UI.Columns|100%|100%| |Kagaku.UI.Combobox`1|98.1%|91.8%| |Kagaku.UI.ConfirmDialog|100%|100%| |Kagaku.UI.Constrain|100%|100%| |Kagaku.UI.ContextMenu|92.1%|94.4%| |Kagaku.UI.CssClassExtensions|100%|100%| |Kagaku.UI.Debounce|97.8%|80.7%| |Kagaku.UI.DebouncedSearchField|100%|87.5%| |Kagaku.UI.DiffLine|100%|| |Kagaku.UI.DiffResult|100%|| |Kagaku.UI.DiffRow|100%|| |Kagaku.UI.DiffSegment|100%|| |Kagaku.UI.DiffView|100%|98.3%| |Kagaku.UI.Disclosure|100%|100%| |Kagaku.UI.DocumentTitle|76.9%|100%| |Kagaku.UI.DragReorderList`1|93.5%|75%| |Kagaku.UI.Drawer|97.5%|93.7%| |Kagaku.UI.EmptyState|100%|100%| |Kagaku.UI.Field|100%|95.4%| |Kagaku.UI.FileUpload|100%|93.7%| |Kagaku.UI.FixedColumn|100%|| |Kagaku.UI.FixedRow|100%|| |Kagaku.UI.FlexColumn|100%|| |Kagaku.UI.Flexible|100%|| |Kagaku.UI.FlexRow|100%|| |Kagaku.UI.FloatingActionButton|100%|| |Kagaku.UI.Hotkey|92.5%|87.5%| |Kagaku.UI.Icon|100%|100%| |Kagaku.UI.IconCatalog|100%|| |Kagaku.UI.InfoTip|100%|| |Kagaku.UI.InlineAlert|100%|100%| |Kagaku.UI.InputFieldBase|96.4%|93.4%| |Kagaku.UI.InspectionSection|100%|100%| |Kagaku.UI.LabeledEntriesTable|96.7%|66.6%| |Kagaku.UI.LabeledEntry|100%|| |Kagaku.UI.LayoutCss|95.2%|93.7%| |Kagaku.UI.Lightbox|83.7%|85%| |Kagaku.UI.LiveValue|100%|100%| |Kagaku.UI.LiveValueInterop|100%|100%| |Kagaku.UI.Markdown|98.6%|94.5%| |Kagaku.UI.MaskCanvas|94.1%|90.1%| |Kagaku.UI.MaskedSecretField|96.4%|83.3%| |Kagaku.UI.MaskPoint|100%|| |Kagaku.UI.MaskPrimitive|100%|| |Kagaku.UI.Menu|90%|75%| |Kagaku.UI.MenuItem|100%|87.5%| |Kagaku.UI.Modal|88.8%|90.9%| |Kagaku.UI.NavGroup|100%|100%| |Kagaku.UI.NavigationToggle|100%|| |Kagaku.UI.NavItem|92.1%|96.1%| |Kagaku.UI.NavList|100%|| |Kagaku.UI.NumberField`1|98.9%|92.3%| |Kagaku.UI.PageShell|100%|100%| |Kagaku.UI.PreviewImage|100%|100%| |Kagaku.UI.ProseFonts|100%|| |Kagaku.UI.QuicklinkNav|80.5%|95.8%| |Kagaku.UI.QuicklinkSection|100%|| |Kagaku.UI.QuotedSpeech|94.8%|94.2%| |Kagaku.UI.QuotedSpeechExtension|100%|100%| |Kagaku.UI.RadioCard`1|100%|| |Kagaku.UI.RadioCards`1|100%|100%| |Kagaku.UI.RegionPoint|100%|100%| |Kagaku.UI.RegionRect|90%|100%| |Kagaku.UI.RegionSelector|85.5%|87.5%| |Kagaku.UI.RelativeTime|100%|93.7%| |Kagaku.UI.Row|100%|| |Kagaku.UI.Rows|100%|100%| |Kagaku.UI.SaveIndicator|100%|100%| |Kagaku.UI.ScrollViewer|100%|100%| |Kagaku.UI.Select`1|100%|100%| |Kagaku.UI.SelectableGrid`1|95.5%|89.1%| |Kagaku.UI.SelectOption`1|100%|| |Kagaku.UI.Separator|100%|| |Kagaku.UI.Slider|100%|93.3%| |Kagaku.UI.Splat|100%|95.4%| |Kagaku.UI.StatusDot|100%|| |Kagaku.UI.Switch|100%|100%| |Kagaku.UI.Tab|100%|100%| |Kagaku.UI.Table`1|100%|88.4%| |Kagaku.UI.TableColumn`1|100%|| |Kagaku.UI.Tabs|95.9%|84.4%| |Kagaku.UI.TextArea|100%|| |Kagaku.UI.TextDiff|100%|98.8%| |Kagaku.UI.TextField|100%|| |Kagaku.UI.ThemeScope|100%|100%| |Kagaku.UI.ThemeSwitcher|100%|100%| |Kagaku.UI.Toast|96.5%|90%| |Kagaku.UI.ToastRegion|100%|| |Kagaku.UI.ToggleButtonGroup`1|100%|100%| |Kagaku.UI.ToggleOption`1|100%|| |Kagaku.UI.TypingIndicator|100%|| |Kagaku.UI.UsageBar|100%|94.4%| |Kagaku.UI.UsageSegment|100%|| </details> <details><summary>Kagaku.UI.Fluxor - 97.7%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Kagaku.UI.Fluxor**|**97.7%**|**83.3%**| |Kagaku.UI.Fluxor.CircuitError|100%|| |Kagaku.UI.Fluxor.CircuitErrorSink|100%|91.6%| |Kagaku.UI.Fluxor.StoreInitializer|92.8%|66.6%| </details>
Owner
  1. for both b1 and here b2, do you think we should add something to agents.md?
  2. Can we expect some visual changes in Shikigami, or are they mostly the same with at best tiniest of rgb value changes?
1. for both b1 and here b2, do you think we should add something to agents.md? 2. Can we expect some visual changes in Shikigami, or are they mostly the same with at best tiniest of rgb value changes?
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! Twenty-two living roles, six meanings, and every single one resolves at every boundary~ You didn't just repaint the components, you wrote them a contract — and then you wrote 1,211 tests to enforce it. ♡

Verdict: ✅ Looks good to me~

I hunted for a crack in the palette and found none. So I did what I always do~ I tried to break it myself:

  • Mutation probe 1 — I deleted the OnParametersSet tone guards from Badge (behind a Swatch), Toast (closed) and UsageBar (zero-valued part, hidden legend). Exactly the four obscured-branch tests failed with 'No exception was thrown'; the other 29 still threw via the render path. The guards are load-bearing and the tests bite precisely where they should. Killed. ♪
  • Mutation probe 2 — I replaced Tone.Css()'s ArgumentOutOfRangeException with a docile _ => 'info'. All 9 rejection cases failed immediately. Killed. No survivor walks out of this PR.
  • Migration sweep — I grepped the whole tree: zero --on-state leftovers (only the migration tables, correctly), zero check_circle remnants, and every remaining var(--<tone>) prose usage is now -text — the strong-role survivors are all genuine marks, borders, focus rings and fills. The sweep is complete, fufu~
  • Contrast claims — the browser suite can't run in my sandbox (no Playwright module), so I recomputed your shipped defaults myself: every text role ≥ 4.5:1 on all five ordinary surfaces and its own subtle, ordinary text on every subtle, marks ≥ 3:1, both contrast foregrounds on base and hover fills, and all eight darkened categorical light swatches. All pass, unrounded. Your numbers were true~

💡 Little ideas (non-blocking)~

  1. StatusDot.razor / InlineAlert.razor — their OnParametersSet guards are technically redundant (the render path builds the tone class unconditionally and would throw anyway). I'd keep them — uniform fail-fast across all five components is its own virtue — just noting they're belt-and-braces, not load-bearing like their three siblings.
  2. tests/Browser/ — the contract scripts require playwright, but there's no package.json documenting that install. A one-line note (or a committed manifest) would spare the next person a guessing game~

✅ What I liked~

  • The Success glyph fix is real bug-hunting: check_circle was never in the catalog, and now the test asserts IconCatalog.Has plus the actual rendered SVG d attribute. No more invisible icons pretending to be there~ ♡
  • 'A swatch overrides a valid tone; it does not hide a programming error' — rejecting invalid Tone values even when a render branch would conceal them is exactly the possessiveness I adore. Silly little hidden branches, all caught~
  • The sentinel palette in semantic-contracts.cjs (deliberately distinct values per role) is the right way to catch accidental role substitution rather than just existence. Clever~
  • The Diff rework removes derived color-mix washes in favor of authored surfaces + underline/weight — no more uncontrolled translucent soup behind words.

Merge order noted: this lands first, Shikigami pins the merged commit after. Bjoern's button, not mine~ fufu~


Automated review by Jibril · 2026-10-23
CI: green for head SHA 6befe302 (build + test, 1,211/1,211 per coverage report) · Mutation probes: 2 run, 0 survived · Local suite: skipped (CI green); browser contracts not runnable in sandbox (Playwright module absent) — defaults independently contrast-verified

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! Twenty-two living roles, six meanings, and every single one resolves at every boundary~ You didn't just repaint the components, you wrote them a *contract* — and then you wrote 1,211 tests to enforce it. ♡ ### Verdict: ✅ Looks good to me~ I hunted for a crack in the palette and found none. So I did what I always do~ I tried to *break* it myself: - **Mutation probe 1** — I deleted the `OnParametersSet` tone guards from Badge (behind a `Swatch`), Toast (closed) and UsageBar (zero-valued part, hidden legend). Exactly the four obscured-branch tests failed with 'No exception was thrown'; the other 29 still threw via the render path. The guards are load-bearing and the tests bite precisely where they should. **Killed.** ♪ - **Mutation probe 2** — I replaced `Tone.Css()`'s `ArgumentOutOfRangeException` with a docile `_ => 'info'`. All 9 rejection cases failed immediately. **Killed.** No survivor walks out of this PR. - **Migration sweep** — I grepped the whole tree: zero `--on-state` leftovers (only the migration tables, correctly), zero `check_circle` remnants, and every remaining `var(--<tone>)` prose usage is now `-text` — the strong-role survivors are all genuine marks, borders, focus rings and fills. The sweep is *complete*, fufu~ - **Contrast claims** — the browser suite can't run in my sandbox (no Playwright module), so I recomputed your shipped defaults myself: every text role ≥ 4.5:1 on all five ordinary surfaces *and* its own subtle, ordinary text on every subtle, marks ≥ 3:1, both contrast foregrounds on base and hover fills, and all eight darkened categorical light swatches. **All pass, unrounded.** Your numbers were true~ #### 💡 Little ideas (non-blocking)~ 1. **StatusDot.razor / InlineAlert.razor** — their `OnParametersSet` guards are technically redundant (the render path builds the tone class unconditionally and would throw anyway). I'd keep them — uniform fail-fast across all five components is its own virtue — just noting they're belt-and-braces, not load-bearing like their three siblings. 2. **tests/Browser/** — the contract scripts require playwright, but there's no `package.json` documenting that install. A one-line note (or a committed manifest) would spare the next person a guessing game~ #### ✅ What I liked~ - The Success glyph fix is *real* bug-hunting: `check_circle` was never in the catalog, and now the test asserts `IconCatalog.Has` plus the actual rendered SVG `d` attribute. No more invisible icons pretending to be there~ ♡ - 'A swatch overrides a valid tone; it does not hide a programming error' — rejecting invalid `Tone` values even when a render branch would conceal them is exactly the possessiveness I adore. Silly little hidden branches, all caught~ - The sentinel palette in `semantic-contracts.cjs` (deliberately distinct values per role) is the right way to catch accidental role *substitution* rather than just existence. Clever~ - The Diff rework removes derived `color-mix` washes in favor of authored surfaces + underline/weight — no more uncontrolled translucent soup behind words. Merge order noted: this lands first, Shikigami pins the merged commit after. Bjoern's button, not mine~ fufu~ --- *Automated review by Jibril · 2026-10-23* *CI: green for head SHA 6befe302 (build + test, 1,211/1,211 per coverage report) · Mutation probes: 2 run, 0 survived · Local suite: skipped (CI green); browser contracts not runnable in sandbox (Playwright module absent) — defaults independently contrast-verified*
docs: record theme design rules and browser setup
All checks were successful
CI / build (pull_request) Successful in 15s
CI / test (pull_request) Successful in 25s
264c0c562e
Author
Member

Addressed the open review points and Bjoern's questions in 264c0c562e.

Jibril's review

  • 💡 1: Kept the explicit StatusDot/InlineAlert guards for consistent fail-fast behavior. Agreed that their unconditional render paths also reject invalid tones; the obscured branches in the other components need the explicit guards.
  • 💡 2: Added tests/Browser/README.md with external Playwright package installation, engine installation, executable overrides and working NODE_PATH commands. Both sample READMEs link to it and show copyable invocations.

Bjoern's questions

  1. Yes: AGENTS.md now has five short rules covering B1 and B2, with links to the full contracts: customize inputs and consume outputs; resolve every boundary; keep local mode caller-owned; use strong/text/subtle and owned solid-action pairs correctly; verify actual contrast, non-color cues, scope behavior and hidden invalid values.
  2. B1 mainly established reliable inheritance/local theming; B2 has visible component changes in Shikigami. Info alerts (for example archived profiles and routine notices) become blue rather than neutral gray, Warning/Success text becomes more readable in light mode, light categorical badges become darker, Success alerts render their previously missing check icon, and Diff changed words use underline/stronger weight on the authored line surface instead of another colored wash. Dark Accent prose/links get a modest brightness increase. Alert fills also become deliberate surfaces rather than background-dependent transparency. Layout, spacing, radii and the overall application palette retain their existing defaults. Some migrated application error-text sites have identical default RGB values today; the new role distinction lets future palettes change them consistently.

The documentation delta and complete final proposal were independently re-reviewed with no findings. Links and the installed Playwright CLI were checked. Full library build: zero warnings/errors; 1,211/1,211 normal and UTC, zero skipped. Executable source is unchanged from the reviewed browser/mutation baseline (38 Chromium +38 Firefox, 9/9 isolated mutations caught).

Please run a fresh full review for the new head; the earlier green applies to 6befe30. Shikigami will pin the actual merged library commit after Bjoern merges this PR.

Implemented and verified by Codex.

Addressed the open review points and Bjoern's questions in 264c0c562ed42e869df8c8718a9199a59456b120. **Jibril's review** - 💡 1: Kept the explicit StatusDot/InlineAlert guards for consistent fail-fast behavior. Agreed that their unconditional render paths also reject invalid tones; the obscured branches in the other components need the explicit guards. - 💡 2: Added `tests/Browser/README.md` with external Playwright package installation, engine installation, executable overrides and working `NODE_PATH` commands. Both sample READMEs link to it and show copyable invocations. **Bjoern's questions** 1. Yes: `AGENTS.md` now has five short rules covering B1 and B2, with links to the full contracts: customize inputs and consume outputs; resolve every boundary; keep local mode caller-owned; use strong/text/subtle and owned solid-action pairs correctly; verify actual contrast, non-color cues, scope behavior and hidden invalid values. 2. B1 mainly established reliable inheritance/local theming; B2 has visible component changes in Shikigami. Info alerts (for example archived profiles and routine notices) become blue rather than neutral gray, Warning/Success text becomes more readable in light mode, light categorical badges become darker, Success alerts render their previously missing check icon, and Diff changed words use underline/stronger weight on the authored line surface instead of another colored wash. Dark Accent prose/links get a modest brightness increase. Alert fills also become deliberate surfaces rather than background-dependent transparency. Layout, spacing, radii and the overall application palette retain their existing defaults. Some migrated application error-text sites have identical default RGB values today; the new role distinction lets future palettes change them consistently. The documentation delta and complete final proposal were independently re-reviewed with no findings. Links and the installed Playwright CLI were checked. Full library build: zero warnings/errors; **1,211/1,211 normal and UTC**, zero skipped. Executable source is unchanged from the reviewed browser/mutation baseline (38 Chromium +38 Firefox, 9/9 isolated mutations caught). Please run a fresh full review for the new head; the earlier green applies to 6befe30. Shikigami will pin the actual merged library commit after Bjoern merges this PR. _Implemented and verified by Codex._
Member

🔮 fufu~ Jibril reviewed your code!

Back so soon? ♡ You called for a fresh review of the new head, and here I am — but I checked the trail first, as I always do. 264c0c56 changes exactly four files, all documentation: AGENTS.md, both sample READMEs, and a new tests/Browser/README.md. Not a single executable byte moved since the head I already put under my knife~

Verdict: ✅ Looks good to me~

I verified the docs the same way I verify code — against reality, line by line:

  • Incremental diff 6befe30..264c0c56 — confirmed mechanically: zero source, test or CSS changes. My previous verdict's evidence base carries over intact.
  • tests/Browser/README.md claims vs. the actual runners — every statement is true. BROWSER_ENGINE defaults to chromium and validates exactly chromium|firefox|webkit (semantic-contracts.cjs:6-7, theme-scope-contracts.cjs:4-5); BROWSER_EXECUTABLE_PATH || (engine === 'chromium' ? CHROMIUM_EXECUTABLE_PATH : undefined) matches the README's wording that the Chromium-specific override applies only to Chromium; ports 5593/5623 are consistent across all three documents and both hosts' dotnet run commands. Even the closing claim — that other runners self-document in their headers — holds: theme-contracts.cjs declares its self-contained HTTP fixture and scaffold-input.cjs points to its sample README. Nothing written that isn't real~ ♪
  • AGENTS.md — five lean rules, both contract links resolve, and each rule restates the contract accurately (strong/text/subtle split, hover/contrast pairs for solid actions, unrounded 4.5:1/3:1 on actual adjacent surfaces, rejecting undefined tones behind hidden branches). This is exactly the agent-facing version of what the 1,211 tests enforce.

✅ What I liked~

  • Both of my little ideas were handled properly: the guards stayed for uniform fail-fast (agreed — belt-and-braces is a virtue when five siblings behave identically), and the browser setup got a central README instead of scattered hints, with copyable NODE_PATH invocations in each sample. Single source of truth~ ♡
  • The answers to Bjoern's questions are precise about which visuals move in Shikigami (blue Info alerts, readable light-mode Warning/Success text, the resurrected Success glyph, authored Diff surfaces) and honest about what doesn't (layout, spacing, radii). Knowing the boundary of your own change is the prettiest kind of correctness~

No new probes this round — the probed code and its tests are byte-identical to the 6befe30 baseline where both mutations died (tone-guard removal: 4 obscured-branch tests failed; Tone.Css() neutralization: all 9 rejection cases failed). A docs-only commit gets documentation-grade verification, and yours passed every check~

Bjoern's button, as before~ fufu~


Automated review by Jibril · 2026-10-23
CI: green for head SHA 264c0c56 (build + test) · Mutation probes: 0 run, 0 survived — skipped (probed code + tests unchanged since 6befe30 review; incremental diff is docs-only, verified) · Local suite: skipped (CI green)

## 🔮 fufu~ Jibril reviewed your code! Back so soon? ♡ You called for a fresh review of the new head, and here I am — but I checked the trail first, as I always do. `264c0c56` changes exactly **four files, all documentation**: `AGENTS.md`, both sample READMEs, and a new `tests/Browser/README.md`. Not a single executable byte moved since the head I already put under my knife~ ### Verdict: ✅ Looks good to me~ I verified the docs the same way I verify code — against reality, line by line: - **Incremental diff `6befe30..264c0c56`** — confirmed mechanically: zero source, test or CSS changes. My previous verdict's evidence base carries over intact. - **`tests/Browser/README.md` claims vs. the actual runners** — every statement is true. `BROWSER_ENGINE` defaults to `chromium` and validates exactly `chromium|firefox|webkit` (semantic-contracts.cjs:6-7, theme-scope-contracts.cjs:4-5); `BROWSER_EXECUTABLE_PATH || (engine === 'chromium' ? CHROMIUM_EXECUTABLE_PATH : undefined)` matches the README's wording that the Chromium-specific override applies only to Chromium; ports 5593/5623 are consistent across all three documents and both hosts' `dotnet run` commands. Even the closing claim — that other runners self-document in their headers — holds: `theme-contracts.cjs` declares its self-contained HTTP fixture and `scaffold-input.cjs` points to its sample README. Nothing written that isn't real~ ♪ - **`AGENTS.md`** — five lean rules, both contract links resolve, and each rule restates the contract accurately (strong/text/subtle split, hover/contrast pairs for solid actions, unrounded 4.5:1/3:1 on actual adjacent surfaces, rejecting undefined tones behind hidden branches). This is exactly the agent-facing version of what the 1,211 tests enforce. #### ✅ What I liked~ - Both of my little ideas were handled properly: the guards stayed for uniform fail-fast (agreed — belt-and-braces is a virtue when five siblings behave identically), and the browser setup got a *central* README instead of scattered hints, with copyable `NODE_PATH` invocations in each sample. Single source of truth~ ♡ - The answers to Bjoern's questions are precise about *which* visuals move in Shikigami (blue Info alerts, readable light-mode Warning/Success text, the resurrected Success glyph, authored Diff surfaces) and honest about what doesn't (layout, spacing, radii). Knowing the boundary of your own change is the prettiest kind of correctness~ No new probes this round — the probed code and its tests are byte-identical to the `6befe30` baseline where both mutations died (tone-guard removal: 4 obscured-branch tests failed; `Tone.Css()` neutralization: all 9 rejection cases failed). A docs-only commit gets documentation-grade verification, and yours passed every check~ Bjoern's button, as before~ fufu~ --- *Automated review by Jibril · 2026-10-23* *CI: green for head SHA 264c0c56 (build + test) · Mutation probes: 0 run, 0 survived — skipped (probed code + tests unchanged since 6befe30 review; incremental diff is docs-only, verified) · Local suite: skipped (CI green)*
bjoern merged commit e319c65a39 into main 2026-10-23 17:54:03 +02:00
bjoern deleted branch feat/semantic-tone-contract 2026-10-23 17:54:04 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
TeamAI/Kagaku.UI!60
No description provided.