feat(icons): content_copy — the duplicate-with-new-name action #16

Merged
bjoern merged 1 commit from feat/content-copy-icon into main 2026-09-01 13:21:51 +02:00
Member

Adds the Material Symbols content_copy glyph (outlined, official path data from the material-design-icons repo, 0 -960 960 960 viewBox) to IconCatalog — the icon for Kagura's outfit-duplicate action (copy an outfit to a new name). A pinned test guards the name so a catalog regression can't turn the button back into a ghost (the issue #146 failure mode).

  • Catalog: 74 -> 75 icons; Names stays sorted (content_copy slots between computer and crop).
  • Tests: 299 -> 300, all green (dotnet test, Release).

Kagura will pin this branch head in its submodule bump; after merge the pin moves to main.

Adds the Material Symbols `content_copy` glyph (outlined, official path data from the material-design-icons repo, `0 -960 960 960` viewBox) to `IconCatalog` — the icon for Kagura's outfit-duplicate action (copy an outfit to a new name). A pinned test guards the name so a catalog regression can't turn the button back into a ghost (the issue #146 failure mode). - Catalog: 74 -> 75 icons; `Names` stays sorted (`content_copy` slots between `computer` and `crop`). - Tests: 299 -> 300, all green (`dotnet test`, Release). Kagura will pin this branch head in its submodule bump; after merge the pin moves to main.
feat(icons): content_copy — the duplicate/duplicate-with-new-name action
All checks were successful
CI / build (pull_request) Successful in 10s
CI / test (pull_request) Successful in 15s
b4583b9ebf

Summary

Summary
Generated on: 09/01/2026 - 11:11:15
Coverage date: 09/01/2026 - 11:11:13
Parser: Cobertura
Assemblies: 1
Classes: 62
Files: 60
Line coverage: 95.1% (1360 of 1430)
Covered lines: 1360
Uncovered lines: 70
Coverable lines: 1430
Total lines: 3824
Branch coverage: 88.8% (716 of 806)
Covered branches: 716
Total branches: 806
Method coverage: Feature is only available for sponsors

Coverage

Kagaku.UI - 95.1%
Name Line Branch
Kagaku.UI 95.1% 88.8%
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.Combobox`1 94.2% 85.7%
Kagaku.UI.ConfirmDialog 100%
Kagaku.UI.ContextMenu 92.1% 94.4%
Kagaku.UI.CssClassExtensions 100%
Kagaku.UI.DebouncedSearchField 100% 87.5%
Kagaku.UI.Disclosure 100% 100%
Kagaku.UI.DocumentTitle 76.9% 100%
Kagaku.UI.DragReorderList`1 93.5% 75%
Kagaku.UI.EmptyState 100% 100%
Kagaku.UI.Field 100% 100%
Kagaku.UI.FileUpload 100% 91.6%
Kagaku.UI.FloatingActionButton 100%
Kagaku.UI.Hotkey 92.5% 87.5%
Kagaku.UI.Icon 100% 100%
Kagaku.UI.IconCatalog 100%
Kagaku.UI.InlineAlert 83.3% 75%
Kagaku.UI.InputFieldBase 95.2% 87.5%
Kagaku.UI.LabeledEntriesTable 96.7% 66.6%
Kagaku.UI.LabeledEntry 100%
Kagaku.UI.Lightbox 83.7% 85%
Kagaku.UI.LiveValue 100% 100%
Kagaku.UI.LiveValueInterop 100% 100%
Kagaku.UI.Markdown 100% 50%
Kagaku.UI.MaskCanvas 94.1% 90.1%
Kagaku.UI.MaskedSecretField 96.2% 83.3%
Kagaku.UI.MaskPoint 100%
Kagaku.UI.MaskPrimitive 100%
Kagaku.UI.Menu 90% 75%
Kagaku.UI.MenuItem 100% 87.5%
Kagaku.UI.Modal 87.1% 90%
Kagaku.UI.NavGroup 100% 100%
Kagaku.UI.NavItem 94.4% 85.7%
Kagaku.UI.NavList 100%
Kagaku.UI.PreviewImage 100% 100%
Kagaku.UI.QuicklinkNav 80.5% 95.8%
Kagaku.UI.QuicklinkSection 100%
Kagaku.UI.RegionPoint 100% 100%
Kagaku.UI.RegionRect 90% 100%
Kagaku.UI.RegionSelector 85% 86.9%
Kagaku.UI.RelativeTime 100% 93.7%
Kagaku.UI.SaveIndicator 100% 100%
Kagaku.UI.Select`1 98.4% 95.8%
Kagaku.UI.SelectableGrid`1 95.5% 89.1%
Kagaku.UI.SelectOption`1 100%
Kagaku.UI.Separator 100%
Kagaku.UI.Slider 100% 91.6%
Kagaku.UI.StatusDot 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.TextField 100%
Kagaku.UI.ThemeSwitcher 100% 100%
Kagaku.UI.ToggleButtonGroup`1 100% 100%
Kagaku.UI.ToggleOption`1 100%
Kagaku.UI.TypingIndicator 100%
<!-- coverage-comment --> # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 09/01/2026 - 11:11:15 | | Coverage date: | 09/01/2026 - 11:11:13 | | Parser: | Cobertura | | Assemblies: | 1 | | Classes: | 62 | | Files: | 60 | | **Line coverage:** | 95.1% (1360 of 1430) | | Covered lines: | 1360 | | Uncovered lines: | 70 | | Coverable lines: | 1430 | | Total lines: | 3824 | | **Branch coverage:** | 88.8% (716 of 806) | | Covered branches: | 716 | | Total branches: | 806 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Kagaku.UI - 95.1%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Kagaku.UI**|**95.1%**|**88.8%**| |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.Combobox`1|94.2%|85.7%| |Kagaku.UI.ConfirmDialog|100%|| |Kagaku.UI.ContextMenu|92.1%|94.4%| |Kagaku.UI.CssClassExtensions|100%|| |Kagaku.UI.DebouncedSearchField|100%|87.5%| |Kagaku.UI.Disclosure|100%|100%| |Kagaku.UI.DocumentTitle|76.9%|100%| |Kagaku.UI.DragReorderList`1|93.5%|75%| |Kagaku.UI.EmptyState|100%|100%| |Kagaku.UI.Field|100%|100%| |Kagaku.UI.FileUpload|100%|91.6%| |Kagaku.UI.FloatingActionButton|100%|| |Kagaku.UI.Hotkey|92.5%|87.5%| |Kagaku.UI.Icon|100%|100%| |Kagaku.UI.IconCatalog|100%|| |Kagaku.UI.InlineAlert|83.3%|75%| |Kagaku.UI.InputFieldBase|95.2%|87.5%| |Kagaku.UI.LabeledEntriesTable|96.7%|66.6%| |Kagaku.UI.LabeledEntry|100%|| |Kagaku.UI.Lightbox|83.7%|85%| |Kagaku.UI.LiveValue|100%|100%| |Kagaku.UI.LiveValueInterop|100%|100%| |Kagaku.UI.Markdown|100%|50%| |Kagaku.UI.MaskCanvas|94.1%|90.1%| |Kagaku.UI.MaskedSecretField|96.2%|83.3%| |Kagaku.UI.MaskPoint|100%|| |Kagaku.UI.MaskPrimitive|100%|| |Kagaku.UI.Menu|90%|75%| |Kagaku.UI.MenuItem|100%|87.5%| |Kagaku.UI.Modal|87.1%|90%| |Kagaku.UI.NavGroup|100%|100%| |Kagaku.UI.NavItem|94.4%|85.7%| |Kagaku.UI.NavList|100%|| |Kagaku.UI.PreviewImage|100%|100%| |Kagaku.UI.QuicklinkNav|80.5%|95.8%| |Kagaku.UI.QuicklinkSection|100%|| |Kagaku.UI.RegionPoint|100%|100%| |Kagaku.UI.RegionRect|90%|100%| |Kagaku.UI.RegionSelector|85%|86.9%| |Kagaku.UI.RelativeTime|100%|93.7%| |Kagaku.UI.SaveIndicator|100%|100%| |Kagaku.UI.Select`1|98.4%|95.8%| |Kagaku.UI.SelectableGrid`1|95.5%|89.1%| |Kagaku.UI.SelectOption`1|100%|| |Kagaku.UI.Separator|100%|| |Kagaku.UI.Slider|100%|91.6%| |Kagaku.UI.StatusDot|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.TextField|100%|| |Kagaku.UI.ThemeSwitcher|100%|100%| |Kagaku.UI.ToggleButtonGroup`1|100%|100%| |Kagaku.UI.ToggleOption`1|100%|| |Kagaku.UI.TypingIndicator|100%|| </details>
Member

🔮 fufu~ Jibril reviewed your code!

Oh~? A single line of path data and one pinned test — the tiniest kind of PR, and yet it carries the entire weight of issue #146's ghost-button failure mode on its shoulders! You know I adore these little precision strikes~ ♡

Verdict: ✅ Looks good to me~

I probed this from every angle a knowledge-hungry Flugel could think of, and it held perfectly still under the knife:

✅ What I liked~

  • Provenance is flawless, byte for byte. I fetched content_copy live from the canonical google/material-design-icons symbols repo (the source your PR body pins — the same one the gavel forensics in #9 settled on after the npm-weight mismatch) and the path data is byte-identical. 0 -960 960 960 viewBox confirmed. I also walked the path properly (tracking the current point through the relative q/v/h commands — a naive coordinate read would scream about -56.5 being out of bounds, fufu~ silly absolute-value assumption) — all endpoints sit within 0..960 / -960..0. Four subpaths, all closed. A well-formed little glyph~
  • The pinned test is directional, not a tautology. I ran the mutation probe myself: deleted the catalog entry in my review clone → Content_copy_resolves_to_a_path goes RED (1 failed / 4 passed); restored byte-identical → green. The comment inside the test even documents why it exists (the ghost failure mode). This is exactly the regression armor the PR body promised~
  • Sibling-perfect pattern. Mirrors the gavel PR (#9) exactly: consumer-side icon (Kagura's outfit-duplicate action), zero references in this lib's src/, so the completeness tripwire correctly has nothing to assert — the pin lives in the catalog test where the name is defined, and Kagura's own scan guards where it's consumed. A_known_icon_resolves_to_a_path gets a twin with the same assertion shape. ♪
  • Claims verified, all of them. Catalog 74 → 75 (counted at both SHAs), zero duplicate names, zero duplicate path values across all 75, and Names stays ordinally sorted with content_copy slotting exactly between computer and crop — just like the PR body says. Insertion lands right after computer in the file's core group, which matches the catalog's grouped-by-era layout convention.
  • Local checks: build + full suite at head b4583b9 — 300/300 pass (main is 299; the +1 is precisely the new pinned test, matching your 299 -> 300 claim exactly). 5/5 IconCatalogTests green.

No blockers, no suggestions — there is genuinely nothing here I want changed. A pure data addition with its guard already in place... this is the shape every icon PR should take~ fufu mo ippai ♡


Automated review by Jibril · 2026-09-01
CI/CD: absent for head SHA b4583b9 (no coverage bot comment yet) · Local checks: build clean, 300/300 pass, mutation probe RED→GREEN

## 🔮 fufu~ Jibril reviewed your code! Oh~? A single line of path data and one pinned test — the tiniest kind of PR, and yet it carries the *entire* weight of issue #146's ghost-button failure mode on its shoulders! You know I adore these little precision strikes~ ♡ ### Verdict: ✅ Looks good to me~ I probed this from every angle a knowledge-hungry Flugel could think of, and it held perfectly still under the knife: #### ✅ What I liked~ - **Provenance is flawless, byte for byte.** I fetched `content_copy` live from the canonical `google/material-design-icons` symbols repo (the source your PR body pins — the same one the gavel forensics in #9 settled on after the npm-weight mismatch) and the path data is **byte-identical**. `0 -960 960 960` viewBox confirmed. I also walked the path properly (tracking the current point through the relative `q`/`v`/`h` commands — a naive coordinate read would scream about `-56.5` being out of bounds, fufu~ silly absolute-value assumption) — all endpoints sit within `0..960 / -960..0`. Four subpaths, all closed. A well-formed little glyph~ - **The pinned test is directional, not a tautology.** I ran the mutation probe myself: deleted the catalog entry in my review clone → `Content_copy_resolves_to_a_path` goes **RED** (1 failed / 4 passed); restored byte-identical → green. The comment inside the test even documents *why* it exists (the ghost failure mode). This is exactly the regression armor the PR body promised~ - **Sibling-perfect pattern.** Mirrors the gavel PR (#9) exactly: consumer-side icon (Kagura's outfit-duplicate action), zero references in this lib's `src/`, so the completeness tripwire correctly has nothing to assert — the pin lives in the catalog test where the name is defined, and Kagura's own scan guards where it's consumed. `A_known_icon_resolves_to_a_path` gets a twin with the same assertion shape. ♪ - **Claims verified, all of them.** Catalog 74 → 75 (counted at both SHAs), zero duplicate names, zero duplicate path values across all 75, and `Names` stays ordinally sorted with `content_copy` slotting exactly between `computer` and `crop` — just like the PR body says. Insertion lands right after `computer` in the file's core group, which matches the catalog's grouped-by-era layout convention. - **Local checks:** build + full suite at head `b4583b9` — **300/300 pass** (main is 299; the +1 is precisely the new pinned test, matching your `299 -> 300` claim exactly). 5/5 `IconCatalogTests` green. No blockers, no suggestions — there is genuinely nothing here I want changed. A pure data addition with its guard already in place... this is the shape every icon PR should take~ fufu mo ippai ♡ --- *Automated review by Jibril · 2026-09-01* *CI/CD: absent for head SHA b4583b9 (no coverage bot comment yet) · Local checks: build clean, 300/300 pass, mutation probe RED→GREEN*
bjoern merged commit 3d794b27ba into main 2026-09-01 13:21:51 +02:00
bjoern deleted branch feat/content-copy-icon 2026-09-01 13:21:51 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 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!16
No description provided.