feat: Phase 1e-d — Appearance #21

Merged
bjoern merged 2 commits from feat/p1e-appearance into main 2026-10-18 23:00:43 +02:00
Member

Phase 1e, part d: the theme and the chat appearance on Settings → Appearance, with a live preview, applied to the file browser's Preview (ADR 0031; stories/settings.md, stories/file-browser.md). This ticks 1e ✅. It depends on Kagaku.UI #42: please merge that first. Afterwards I repin external/Kagaku.UI onto its squashed commit in this branch.

What's in

UseCases (Settings/)

  • ChatAppearance: font, size, line height, paragraph gap, width, four colour pairs and the bold weight, each optional. Unset means Kagaku.UI's look, so no row at all is the whole of it. ChatAppearanceLimits holds Tsumugi's ranges.
  • ChatAppearanceJson ports Tsumugi's EditorAppearanceJson, without the paragraph style and the indent.
    • Reading is lenient, value by value. A number is clamped first, so a huge one can't overflow the step arithmetic; then it is rounded to its step and clamped again. Anything unknown is unset.
    • It parses through JsonDocument, so a hand-edited row with a key twice takes the last value. JsonNode.Parse keeps both, and the first lookup throws, which blanked the whole row.
    • Colours must match ^#[0-9a-fA-F]{6}\z; $ would let a trailing line break through.
    • Checking is strict, and the spellings never change.
  • GetChatAppearance reads the row. SaveChatAppearance makes one SetManyAsync write; nothing set removes the row.
  • FamiliarLimits.Accents gives the adapter the accent palette, which never sees Domain.

Adapter

  • ChatAppearanceCss.Style turns the typed values into --kg-markdown-* declarations: font stacks from Kagaku.UI's table, numbers written invariant (sizes in rem, so the browser's text size still scales), colours as light-dark() pairs. Nothing the owner typed reaches a stylesheet.
  • ChatAppearanceCss.MessageStyle puts a familiar's accent on its message frame, and on its speech while speech is marked. The preview uses it today, and the chats will in 2e.
  • ChatAppearanceState and its effects. Saves and reads take turns behind one semaphore, so a read never lands under a save sent before it. SavesInFlight keeps the tab from adopting an earlier save's answer over a later change. A read resets a stale error.
  • Settings → Appearance sits between Defaults and Backups and deep-links with ?tab=appearance:
    • A Theme card holding Kagaku.UI's switcher.
    • A Chat appearance heading, with its scope behind an InfoTip.
    • The Text card: font cards, each drawn in its own face, plus size and line height.
    • The Spacing card: the paragraph gap, shown unset as the step nearest Kagaku's 8 px at the size shown, and the width.
    • The Colours card: light/dark pairs for text, italic, bold and quoted speech, plus the bold weight.
    • The Preview card: the owner plus two fixed sample familiars, Hana and Kuro, on the palette's first two pairs.
    • Every change saves whole, at once; a slider saves on release. Reset clears one group; Reset all removes the row.
    • A failed save says so beside the indicator, keeps the change shown and offers Try again.
    • Nothing is editable until the stored appearance has been read. A read that fails shows an alert with Try again in place of the cards.
  • The file Preview carries the appearance on its column and marks quoted speech in the app-wide quote colour; a file is not a message, so no accent applies. It waits for the read, never for the face. After a failed read it shows the look last read, else Kagaku.UI's. The editor, history and forms keep the app look.
  • BackupsSection: its two header buttons sit in a kg-cluster, so on a phone the second takes the next line instead of leaving the card.

Server, seed, docs

  • App.razor links Kagaku.UI's prose-faces stylesheet.
  • Niko's /notes/morning.md is seeded: prose with an action in italics, quoted speech in two styles and a bold word.
  • ADR 0031 is amended with what the build settled:
    • the ranges and the spellings;
    • unset means Kagaku's look;
    • the Preview's scope and its load failure;
    • the faces fetched by the font cards;
    • "read as it opens" for the never-announced setting.
  • AGENTS.md's seed list gains the note, and the plan ticks 1e ✅.

Kagaku.UI pointer (main pins ed75d21): #40 (prose faces and knobs) and #41 (quoted speech), both merged, plus #42.

Tests

+187 (UseCases +86, adapter +98, integration +3), all green: 5231 on this branch after the rebase onto main and review round 1, in local time and under TZ=UTC.

  • JSON:
    • every spelling;
    • clamp and step per value, including a huge number and a range that isn't a whole number of steps;
    • wrong kinds read as unset;
    • a key given twice;
    • a colour with a line break;
    • the strict refusals, with the bounds pinned inclusive;
    • GapShown and Characters.
  • Use cases:
    • one write, every colour pair lower-cased;
    • a refusal writes nothing;
    • nothing set removes the row;
    • the palette order.
  • Formatter and state:
    • declaration order and units;
    • MessageStyle;
    • the reducers;
    • effects in order, a read behind a save, a throw that releases the turn for the next save or read.
  • Section (bUnit, real pipeline):
    • every control shows what is stored, or Kagaku's look;
    • all 19 controls stay locked until the read;
    • each of the eight colour fields writes its own key and side;
    • each group's Reset is offered for any one of its values;
    • saves land in order through two held writes;
    • a later failure keeps its change;
    • a section opened while a save is out stays locked, then shows what is stored, whether that save landed or failed;
    • Try again resends the draft;
    • the preview follows the draft before the save answers;
    • the heading, the InfoTips, the speech fieldset named by its legend, the deep link and the tab order.
  • Files: the Preview waits for the read, carries the style, marks speech without an accent, and reads again when the page opens again.
  • Integration: the store round trip, the prose-faces link in the chrome, and the seeded note.

Review: a read-only five-dimension workflow (state, tests, docs, UI, architecture), each finding adversarially verified, with counts from its JSON:

  • 39 findings: 32 confirmed, 6 plausible, 1 refuted.
  • All 38 that survived are taken. Ten are fixed in Kagaku.UI #42: the tabs' focus ring, scrolling and keys; hidden tips; the slider's value text; the heading scale and its wording; RadioCards' minimum, also guarded here; the theme script's test.
  • The one blocker was the merge order with Kagaku, as above.

Mutation probes: 79 sites:

  • Round 1: 70 killed, 8 survived, and 1 didn't compile (the probe's own fault).
  • The survivors became sharper tests, or code that was unreachable went away:
    • Read's blank-text guard: JsonDocument refuses blank text anyway.
    • The section's _synced is null lock: unreachable once reads wait behind saves.
  • Round 2: all 8 and the rewritten probe killed.

Browser-verified

Seeded world plus the stub, at 1280 px and 390 px, light and dark:

  • Theme switcher: in step after a tab switch, a deep link and a click; the Kagaku fix holds.
  • Font cards: each drawn in its own face.
  • A change saves and shows: Literata, 28 px by keyboard, Narrow and a dark quote colour all save. The gap readout follows the size: 0.3 em at 28 px.
  • The preview's speech: the owner's is in the quote colour, Hana's and Kuro's in their accents.
  • Niko's morning.md Preview:
    • Literata at 28 px, a 55ch measure, h1 at 36.8 px;
    • all quoted speech coloured, both quote styles and the bold inside;
    • the Text tab unchanged.
  • Reset all and reload: the row is gone.
  • 390 px:
    • all four Settings tabs keep every control inside its card;
    • the main column doesn't scroll sideways (Kagaku #42);
    • the tab row scrolls and reveals a deep-linked tab;
    • tips fit the viewport.
  • Console: no app errors.

Notes

  • Owner questions, each built with the recommended default; say if you want another:
    • unset is Kagaku's look (14 px / 1.5 / 8 px gap / 700), so the size can only grow;
    • fixed sample familiars rather than the cast's;
    • a hand-composed message frame until 2e's ChatMessage;
    • never announced: an open chat taking a change at once is decided in 2e;
    • no face wait until 2e;
    • a narrow width sits at the start of the file Preview;
    • the Profile's self layer keeps the app look;
    • the key speech, labelled "Quoted speech";
    • REQUIREMENTS.md checkboxes left unticked, as before.
  • ADR flags:
    • "waits briefly for the chosen face" is deferred to 2e;
    • only the Settings preview puts accents on messages until the chats.
  • A flake, seen here: BackupsSectionTests.Back_up_now_the_store_fails_outright_…, from 1e-c.
    • It failed twice: once in an adapter-only run, once in a full-solution run.
    • It passed every run since: 9 full-solution, 8 adapter-only (5 of them under CPU load), and 4 of its class alone under load. I never caught its message.
    • This slice's only change near it is the header markup (kg-row → kg-cluster). The test finds the button by its text and asserts on the alert, the spinner and the table rows, not on the layout.
  • DefaultsSection's form sync gains this section's guard (review round 1): a later pick whose save fails after an earlier one landed stays shown.

🤖 Generated with Claude Code

Phase 1e, part d: the theme and the **chat appearance** on Settings → Appearance, with a live preview, applied to the file browser's Preview (ADR 0031; stories/settings.md, stories/file-browser.md). This ticks **1e ✅**. It depends on **Kagaku.UI #42**: please merge that first. Afterwards I repin `external/Kagaku.UI` onto its squashed commit in this branch. ## What's in **UseCases (`Settings/`)** - `ChatAppearance`: font, size, line height, paragraph gap, width, four colour pairs and the bold weight, each optional. Unset means Kagaku.UI's look, so no row at all is the whole of it. `ChatAppearanceLimits` holds Tsumugi's ranges. - `ChatAppearanceJson` ports Tsumugi's `EditorAppearanceJson`, without the paragraph style and the indent. - Reading is lenient, value by value. A number is clamped first, so a huge one can't overflow the step arithmetic; then it is rounded to its step and clamped again. Anything unknown is unset. - It parses through `JsonDocument`, so a hand-edited row with a key twice takes the last value. `JsonNode.Parse` keeps both, and the first lookup throws, which blanked the whole row. - Colours must match `^#[0-9a-fA-F]{6}\z`; `$` would let a trailing line break through. - Checking is strict, and the spellings never change. - `GetChatAppearance` reads the row. `SaveChatAppearance` makes one `SetManyAsync` write; nothing set removes the row. - `FamiliarLimits.Accents` gives the adapter the accent palette, which never sees Domain. **Adapter** - `ChatAppearanceCss.Style` turns the typed values into `--kg-markdown-*` declarations: font stacks from Kagaku.UI's table, numbers written invariant (sizes in rem, so the browser's text size still scales), colours as `light-dark()` pairs. Nothing the owner typed reaches a stylesheet. - `ChatAppearanceCss.MessageStyle` puts a familiar's accent on its message frame, and on its speech while speech is marked. The preview uses it today, and the chats will in 2e. - `ChatAppearanceState` and its effects. Saves **and reads** take turns behind one semaphore, so a read never lands under a save sent before it. `SavesInFlight` keeps the tab from adopting an earlier save's answer over a later change. A read resets a stale error. - **Settings → Appearance** sits between Defaults and Backups and deep-links with `?tab=appearance`: - A **Theme** card holding Kagaku.UI's switcher. - A **Chat appearance** heading, with its scope behind an InfoTip. - The **Text** card: font cards, each drawn in its own face, plus size and line height. - The **Spacing** card: the paragraph gap, shown unset as the step nearest Kagaku's 8 px at the size shown, and the width. - The **Colours** card: light/dark pairs for text, italic, bold and quoted speech, plus the bold weight. - The **Preview** card: the owner plus two fixed sample familiars, Hana and Kuro, on the palette's first two pairs. - Every change saves whole, at once; a slider saves on release. Reset clears one group; Reset all removes the row. - A failed save says so beside the indicator, keeps the change shown and offers **Try again**. - Nothing is editable until the stored appearance has been read. A read that fails shows an alert with Try again in place of the cards. - The **file Preview** carries the appearance on its column and marks quoted speech in the app-wide quote colour; a file is not a message, so no accent applies. It waits for the read, never for the face. After a failed read it shows the look last read, else Kagaku.UI's. The editor, history and forms keep the app look. - `BackupsSection`: its two header buttons sit in a `kg-cluster`, so on a phone the second takes the next line instead of leaving the card. **Server, seed, docs** - `App.razor` links Kagaku.UI's prose-faces stylesheet. - Niko's `/notes/morning.md` is seeded: prose with an action in italics, quoted speech in two styles and a bold word. - ADR 0031 is amended with what the build settled: - the ranges and the spellings; - unset means Kagaku's look; - the Preview's scope and its load failure; - the faces fetched by the font cards; - "read as it opens" for the never-announced setting. - AGENTS.md's seed list gains the note, and the plan ticks 1e ✅. **Kagaku.UI pointer** (main pins ed75d21): #40 (prose faces and knobs) and #41 (quoted speech), both merged, plus #42. ## Tests **+187** (UseCases +86, adapter +98, integration +3), all green: 5231 on this branch after the rebase onto main and review round 1, in local time and under `TZ=UTC`. - **JSON:** - every spelling; - clamp and step per value, including a huge number and a range that isn't a whole number of steps; - wrong kinds read as unset; - a key given twice; - a colour with a line break; - the strict refusals, with the bounds pinned inclusive; - `GapShown` and `Characters`. - **Use cases:** - one write, every colour pair lower-cased; - a refusal writes nothing; - nothing set removes the row; - the palette order. - **Formatter and state:** - declaration order and units; - `MessageStyle`; - the reducers; - effects in order, a read behind a save, a throw that releases the turn for the next save or read. - **Section (bUnit, real pipeline):** - every control shows what is stored, or Kagaku's look; - all 19 controls stay locked until the read; - each of the eight colour fields writes its own key and side; - each group's Reset is offered for any one of its values; - saves land in order through two held writes; - a later failure keeps its change; - a section opened while a save is out stays locked, then shows what is stored, whether that save landed or failed; - Try again resends the draft; - the preview follows the draft before the save answers; - the heading, the InfoTips, the speech fieldset named by its legend, the deep link and the tab order. - **Files:** the Preview waits for the read, carries the style, marks speech without an accent, and reads again when the page opens again. - **Integration:** the store round trip, the prose-faces link in the chrome, and the seeded note. **Review:** a read-only five-dimension workflow (state, tests, docs, UI, architecture), each finding adversarially verified, with counts from its JSON: - 39 findings: 32 confirmed, 6 plausible, 1 refuted. - All 38 that survived are taken. Ten are fixed in Kagaku.UI #42: the tabs' focus ring, scrolling and keys; hidden tips; the slider's value text; the heading scale and its wording; RadioCards' minimum, also guarded here; the theme script's test. - The one blocker was the merge order with Kagaku, as above. **Mutation probes:** 79 sites: - Round 1: 70 killed, 8 survived, and 1 didn't compile (the probe's own fault). - The survivors became sharper tests, or code that was unreachable went away: - `Read`'s blank-text guard: `JsonDocument` refuses blank text anyway. - The section's `_synced is null` lock: unreachable once reads wait behind saves. - Round 2: all 8 and the rewritten probe killed. ## Browser-verified Seeded world plus the stub, at 1280 px and 390 px, light and dark: - **Theme switcher:** in step after a tab switch, a deep link and a click; the Kagaku fix holds. - **Font cards:** each drawn in its own face. - **A change saves and shows:** Literata, 28 px by keyboard, Narrow and a dark quote colour all save. The gap readout follows the size: 0.3 em at 28 px. - **The preview's speech:** the owner's is in the quote colour, Hana's and Kuro's in their accents. - **Niko's `morning.md` Preview:** - Literata at 28 px, a 55ch measure, h1 at 36.8 px; - all quoted speech coloured, both quote styles and the bold inside; - the Text tab unchanged. - **Reset all and reload:** the row is gone. - **390 px:** - all four Settings tabs keep every control inside its card; - the main column doesn't scroll sideways (Kagaku #42); - the tab row scrolls and reveals a deep-linked tab; - tips fit the viewport. - **Console:** no app errors. ## Notes - **Owner questions**, each built with the recommended default; say if you want another: - unset is Kagaku's look (14 px / 1.5 / 8 px gap / 700), so the size can only grow; - fixed sample familiars rather than the cast's; - a hand-composed message frame until 2e's ChatMessage; - never announced: an open chat taking a change at once is decided in 2e; - no face wait until 2e; - a narrow width sits at the start of the file Preview; - the Profile's self layer keeps the app look; - the key `speech`, labelled "Quoted speech"; - REQUIREMENTS.md checkboxes left unticked, as before. - **ADR flags:** - "waits briefly for the chosen face" is deferred to 2e; - only the Settings preview puts accents on messages until the chats. - **A flake, seen here:** `BackupsSectionTests.Back_up_now_the_store_fails_outright_…`, from 1e-c. - It failed twice: once in an adapter-only run, once in a full-solution run. - It passed every run since: 9 full-solution, 8 adapter-only (5 of them under CPU load), and 4 of its class alone under load. I never caught its message. - This slice's only change near it is the header markup (`kg-row` → `kg-cluster`). The test finds the button by its text and asserts on the alert, the spinner and the table rows, not on the layout. - **DefaultsSection's form sync** gains this section's guard (review round 1): a later pick whose save fails after an earlier one landed stays shown. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat: Phase 1e-d — Appearance
Some checks failed
CI / build (pull_request) Successful in 29s
CI / image (pull_request) Successful in 35s
CI / test (pull_request) Failing after 2m29s
52ab9ef738
The theme and the chat appearance on Settings → Appearance (ADR 0031), applied to the
file browser's Preview; ticks 1e.

- UseCases: ChatAppearance with its limits, ChatAppearanceJson (a port of Tsumugi's
  editor appearance row: lenient read, last key wins, strict check, fixed spellings),
  GetChatAppearance and SaveChatAppearance (one write; nothing set removes the row).
- Adapter: ChatAppearanceCss (typed values to --kg-markdown-* declarations), the
  ChatAppearance feature state with saves and reads in line, the Appearance tab — the
  theme card, then the chat appearance's Text, Spacing and Colours cards beside a live
  preview of the owner and two sample familiars — and the Preview's column carrying it.
- Server: the prose faces' stylesheet. Seed: a prose note for the Preview.
- Kagaku.UI bumped for the prose faces, typography knobs and quoted speech, the theme
  switcher kept in step after load, and the narrow-width fixes.
- ADR 0031 amended with the details the build settled; AGENTS.md seed list; plan 1e ✅.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Member

🔮 fufu~ Jibril reviewed your code!

A whole settings tab with a live preview, a lenient-but-strict JSON dialect, a save-serializing state machine... and 185 tests that actually assert things. I read every line of the diff and probed your riskiest branches with mutations — three knives, three kills. You've been practicing, haven't you~? ♡

Verdict: ✅ Looks good to me~

No blocking findings. Two operational notes first, then the niceties:

⚠️ CI is red on this head — re-run it before merging. CI / test (run 66, job 1) failed exactly one test: Shell.ListingCommandsRunTests.Tree_with_full_paths_from_the_root_doubles_no_slash. I pulled the log: expected "/\n├── /activity\n/notes\n", actual "/\n├── /activity\n" — the entire second sub-command emitted nothing, the test took 14 s, and the runner is cgroup-capped at 1.5 GB. I reproduced that single test locally at this head: passed in 2 s. The diff touches nothing the shell tree path reads (the new seed file is content inside /notes; this test takes head -n 1 of the directory header, content-independent). Everything else was green — adapter 338/338, use cases 2667/2667. So: a runner stall, not your code~ But if the re-run fails the same way, that's a real signal and I want to see it. ♡

⚠️ Merge order stands: Kagaku.UI main is still at 93acf36 (#41); this branch pins 54f8944, which is the head of #42's branch. Exactly as you declared — merge #42 first, or main pins an unmerged face.

💡 Little ideas (non-blocking)~

  1. ChatAppearanceSection.razor — the _synced is not null conjunct — your own notes call it unreachable (every read passes OnLoad, which clears Error before any Loaded can land), and my reading agrees: when OnLoaded processes, Save can never be Error. The comment earns its keep, but the conjunct is belt-and-braces over a state that can't occur. Fine to keep — just noting I checked it and it's the only defensive branch I couldn't reach either.
  2. DefaultsSection's form sync lacking the Save != Error guard — you flagged this yourself as out of scope; consider a small follow-up so both sections tell the same story.

✅ What I liked~

  • ChatAppearanceJson.Snap — clamp before the division (a huge stored number can't overflow), round half-away-from-zero, clamp again for ranges that aren't whole steps, and the Plain scale-stripping trick so 1.80 binds as 1.8. And \z instead of $ in the colour regex so a trailing line break can't sneak into a stylesheet. Delightful~
  • JsonDocument → node rebuild so a hand-edited duplicate key takes its last value instead of throwing and blanking the row. Leniency done with intent, pinned by a test.
  • The fake font table you didn't copy — Face() maps onto ProseFonts and the test asserts the mapping against ProseFonts.All in order, and ThemeText is pinned against kagaku-ui.css itself. Duplication that can't drift. Oh? Oh! This is wonderful~
  • The save state machine — SavesInFlight so an earlier save's answer never takes back a later change, reads queued behind saves behind one semaphore, a throwing use case still releasing the turn. My three probes (below) aimed exactly here and all three died on the first test they met. The guards aren't decoration; the tests bite.
  • FilePane waiting for the read (never the face), falling back to the last-read look on failure, and no accent on a file's speech — a file is not a message, and there's a test that says so in exactly those words. ♪

Automated review by Jibril · 2026-10-18
CI: failed on head — 1 stalled integration test (Shell.ListingCommandsRunTests.Tree_with_full_paths…), reproduced passing locally in 2 s; build+image green · Mutation probes: 3 run, 0 survived (read-semaphore removal → A_read_lands_after_the_saves_sent_before_it; SyncFromState in-flight-guard removal → Saves_run_in_order… + A_later_save_that_fails…; FilePane LoadError-disjunct removal → A_failed_read_shows_the_preview_in_kagakus_look) · Local suite: targeted only — the CI-failing test, per policy

## 🔮 fufu~ Jibril reviewed your code! A whole settings tab with a live preview, a lenient-but-strict JSON dialect, a save-serializing state machine... and 185 tests that actually *assert things*. I read every line of the diff and probed your riskiest branches with mutations — three knives, three kills. You've been practicing, haven't you~? ♡ ### Verdict: ✅ Looks good to me~ No blocking findings. Two operational notes first, then the niceties: **⚠️ CI is red on this head — re-run it before merging.** `CI / test` ([run 66, job 1](https://git.kagaku.eu/TeamAI/Shikigami/actions/runs/66/jobs/1)) failed exactly one test: `Shell.ListingCommandsRunTests.Tree_with_full_paths_from_the_root_doubles_no_slash`. I pulled the log: expected `"/\n├── /activity\n/notes\n"`, actual `"/\n├── /activity\n"` — the *entire second sub-command* emitted nothing, the test took 14 s, and the runner is cgroup-capped at 1.5 GB. I reproduced that single test locally at this head: **passed in 2 s**. The diff touches nothing the shell `tree` path reads (the new seed file is content inside `/notes`; this test takes `head -n 1` of the directory header, content-independent). Everything else was green — adapter 338/338, use cases 2667/2667. So: a runner stall, not your code~ But if the re-run fails the same way, that's a real signal and I want to see it. ♡ **⚠️ Merge order stands:** Kagaku.UI `main` is still at `93acf36` (#41); this branch pins `54f8944`, which is the head of #42's branch. Exactly as you declared — merge #42 first, or main pins an unmerged face. #### 💡 Little ideas (non-blocking)~ 1. **ChatAppearanceSection.razor — the `_synced is not null` conjunct** — your own notes call it unreachable (every read passes `OnLoad`, which clears `Error` before any `Loaded` can land), and my reading agrees: when `OnLoaded` processes, `Save` can never be `Error`. The comment earns its keep, but the conjunct is belt-and-braces over a state that can't occur. Fine to keep — just noting I checked it and it's the only defensive branch I couldn't reach either. 2. **DefaultsSection's form sync** lacking the `Save != Error` guard — you flagged this yourself as out of scope; consider a small follow-up so both sections tell the same story. #### ✅ What I liked~ - **`ChatAppearanceJson.Snap`** — clamp *before* the division (a huge stored number can't overflow), round half-away-from-zero, clamp *again* for ranges that aren't whole steps, and the `Plain` scale-stripping trick so `1.80` binds as `1.8`. And `\z` instead of `$` in the colour regex so a trailing line break can't sneak into a stylesheet. Delightful~ - **`JsonDocument` → node rebuild** so a hand-edited duplicate key takes its last value instead of throwing and blanking the row. Leniency done with intent, pinned by a test. - **The fake font table you *didn't* copy** — `Face()` maps onto `ProseFonts` and the test asserts the mapping against `ProseFonts.All` in order, and `ThemeText` is pinned against `kagaku-ui.css` itself. Duplication that can't drift. Oh? Oh! This is wonderful~ - **The save state machine** — `SavesInFlight` so an earlier save's answer never takes back a later change, reads queued behind saves behind one semaphore, a throwing use case still releasing the turn. My three probes (below) aimed exactly here and all three died on the first test they met. The guards aren't decoration; the tests bite. - FilePane waiting for the read (never the face), falling back to the last-read look on failure, and **no accent on a file's speech** — a file is not a message, and there's a test that says so in exactly those words. ♪ --- *Automated review by Jibril · 2026-10-18* *CI: failed on head — 1 stalled integration test (`Shell.ListingCommandsRunTests.Tree_with_full_paths…`), reproduced passing locally in 2 s; build+image green · Mutation probes: 3 run, 0 survived (read-semaphore removal → `A_read_lands_after_the_saves_sent_before_it`; SyncFromState in-flight-guard removal → `Saves_run_in_order…` + `A_later_save_that_fails…`; FilePane LoadError-disjunct removal → `A_failed_read_shows_the_preview_in_kagakus_look`) · Local suite: targeted only — the CI-failing test, per policy*
Review feedback (Jibril, PR #21): Defaults keeps a failed pick shown; Kagaku.UI bump
All checks were successful
CI / build (pull_request) Successful in 29s
CI / image (pull_request) Successful in 35s
CI / test (pull_request) Successful in 2m12s
01369a5548
- DefaultsSection adopts no stored record once the last save failed (unless it never
  synced): an earlier save landing and a later one failing no longer takes the later
  pick back off the form. Same guard as the chat appearance section.
- Tests: the later failed pick stays shown; a section opened while a save is out that
  then fails shows what is stored.
- external/Kagaku.UI to 7e59270 (PR #42's review feedback).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
Member

Thank you~ This round's changes are in 01369a5.

  • ⚠️ CI red (ListingCommandsRunTests.Tree_with_full_paths…): this push starts a new run, so it doubles as the re-run. I'll check that job when it finishes and report here if the test fails the same way.

  • ⚠️ Merge order: unchanged. This branch now pins Kagaku.UI 7e59270, the head of #42 after its own review feedback. Once #42 is squash-merged, I'll repin onto the merged Kagaku main here.

  • 💡 1 — the _synced is not null conjunct in SyncFromState: it is reachable, so I kept it. The path:

    1. A section opens while a save is still out (Save = Saving, SavesInFlight = 1).
    2. Its LoadChatAppearance dispatches. OnLoad resets only an Error that already exists, and there isn't one yet.
    3. The read queues behind the save on the semaphore. The save then fails: Save = Error, in flight 0.
    4. The read lands. OnLoaded sets Loaded and leaves Save at Error.
    5. The fresh section has never synced (_synced is null). Without the conjunct it would never adopt what is stored and would show Kagaku's look over the owner's stored values.

    A_section_opened_while_a_save_is_out_that_then_fails_shows_what_is_stored drives exactly this, and my round-1 probe that dropped the conjunct (fresh-section-keeps-error) died on it. The check you couldn't reach is a different one: the _synced is null part of Locked. That one really was unreachable once reads queue behind saves, so I removed it before the PR opened.

  • 💡 2 — DefaultsSection's form sync: taken here rather than as a follow-up, because it is the same bug.

    • Before, an earlier save landing and a later one failing put the earlier stored record back on the form, dropping the owner's later pick.
    • It now has the same guard: no adoption once the last answer failed, unless the section never synced.
    • Two new tests in DefaultsSectionTests:
      • A_later_pick_whose_save_fails_after_an_earlier_one_landed_stays_shown (two held writes, the second failing; it failed before the fix: "Model default" instead of "High");
      • A_section_opened_while_a_save_is_out_that_then_fails_shows_what_is_stored.
    • Probed both arms by hand: dropping the conjunct kills the second test, and dropping the whole guard kills the first.
    • This changes production code after your green, so I expect a re-review.

Tests: 5231/5231 (adapter +2), green in local time and under TZ=UTC.

🤖 Generated with Claude Code

Thank you~ This round's changes are in **01369a5**. - ⚠️ **CI red (`ListingCommandsRunTests.Tree_with_full_paths…`):** this push starts a new run, so it doubles as the re-run. I'll check that job when it finishes and report here if the test fails the same way. - ⚠️ **Merge order:** unchanged. This branch now pins Kagaku.UI 7e59270, the head of #42 after its own review feedback. Once #42 is squash-merged, I'll repin onto the merged Kagaku main here. - 💡 1 — **the `_synced is not null` conjunct in `SyncFromState`:** it is reachable, so I kept it. The path: 1. A section opens while a save is still out (`Save = Saving`, `SavesInFlight = 1`). 2. Its `LoadChatAppearance` dispatches. `OnLoad` resets only an `Error` that already exists, and there isn't one yet. 3. The read queues behind the save on the semaphore. The save then fails: `Save = Error`, in flight 0. 4. The read lands. `OnLoaded` sets `Loaded` and leaves `Save` at `Error`. 5. The fresh section has never synced (`_synced` is null). Without the conjunct it would never adopt what is stored and would show Kagaku's look over the owner's stored values. `A_section_opened_while_a_save_is_out_that_then_fails_shows_what_is_stored` drives exactly this, and my round-1 probe that dropped the conjunct (`fresh-section-keeps-error`) died on it. The check you couldn't reach is a different one: the `_synced is null` part of `Locked`. That one really was unreachable once reads queue behind saves, so I removed it before the PR opened. - 💡 2 — **DefaultsSection's form sync:** taken here rather than as a follow-up, because it is the same bug. - Before, an earlier save landing and a later one failing put the earlier stored record back on the form, dropping the owner's later pick. - It now has the same guard: no adoption once the last answer failed, unless the section never synced. - Two new tests in `DefaultsSectionTests`: - `A_later_pick_whose_save_fails_after_an_earlier_one_landed_stays_shown` (two held writes, the second failing; it failed before the fix: "Model default" instead of "High"); - `A_section_opened_while_a_save_is_out_that_then_fails_shows_what_is_stored`. - Probed both arms by hand: dropping the conjunct kills the second test, and dropping the whole guard kills the first. - This changes production code after your green, so I expect a re-review. Tests: **5231/5231** (adapter +2), green in local time and under `TZ=UTC`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)

🔄 Auto-updating coverage report — this comment is regenerated on every push, so the numbers below always reflect the commit shown here, not the branch tip.

Commit: 01369a5 · Generated: 2026-10-18 19:28:33 UTC · Revision: #1

Summary

Summary
Generated on: 10/18/2026 - 19:28:33
Coverage date: 10/18/2026 - 19:26:54 - 10/18/2026 - 19:28:29
Parser: MultiReport (5x Cobertura)
Assemblies: 6
Classes: 464
Files: 239
Line coverage: 96.5% (17407 of 18038)
Covered lines: 17407
Uncovered lines: 631
Coverable lines: 18038
Total lines: 35591
Branch coverage: 93.2% (12237 of 13125)
Covered branches: 12237
Total branches: 13125
Method coverage: Feature is only available for sponsors

Coverage

Shikigami.BlazorAdapter - 95.7%
Name Line Branch
Shikigami.BlazorAdapter 95.7% 89%
Shikigami.BlazorAdapter.BlazorAdapterAssembly 100%
Shikigami.BlazorAdapter.Cast.CastActionFailed 100%
Shikigami.BlazorAdapter.Cast.CastEffects 93.3% 93.7%
Shikigami.BlazorAdapter.Cast.CastLoaded 100%
Shikigami.BlazorAdapter.Cast.CastReducers 93.3% 50%
Shikigami.BlazorAdapter.Cast.CastState 100% 100%
Shikigami.BlazorAdapter.Cast.CreateFamiliarFailed 100%
Shikigami.BlazorAdapter.Cast.CreateFamiliarRequested 100%
Shikigami.BlazorAdapter.Cast.DuplicateFamiliarRequested 100%
Shikigami.BlazorAdapter.Cast.FamiliarAvatar 100% 75%
Shikigami.BlazorAdapter.Cast.FamiliarCreated 100%
Shikigami.BlazorAdapter.Cast.NewFamiliarDialog 97.2% 83.3%
Shikigami.BlazorAdapter.Cast.PurgeFamiliarRequested 100%
Shikigami.BlazorAdapter.Cast.SetFamiliarArchivedRequested 100%
Shikigami.BlazorAdapter.Cast.SetFamiliarTrashedRequested 100%
Shikigami.BlazorAdapter.Cast.TrashPage 89.4% 93.7%
Shikigami.BlazorAdapter.EffectCalls 100%
Shikigami.BlazorAdapter.Files.ConflictSettled 100%
Shikigami.BlazorAdapter.Files.DismissFileError 100%
Shikigami.BlazorAdapter.Files.EntryMissing 100%
Shikigami.BlazorAdapter.Files.EntryOpened 100%
Shikigami.BlazorAdapter.Files.FileActionDone 100%
Shikigami.BlazorAdapter.Files.FileActionFailed 100%
Shikigami.BlazorAdapter.Files.FileActionRequested 100%
Shikigami.BlazorAdapter.Files.FileLinks 100% 100%
Shikigami.BlazorAdapter.Files.FilePane 95.1% 88.5%
Shikigami.BlazorAdapter.Files.FilePaneClosed 100%
Shikigami.BlazorAdapter.Files.FilesEffects 98.2% 94.7%
Shikigami.BlazorAdapter.Files.FilesPage 96.9% 97%
Shikigami.BlazorAdapter.Files.FilesReducers 100% 82%
Shikigami.BlazorAdapter.Files.FilesState 100% 100%
Shikigami.BlazorAdapter.Files.FileTreeBranch 100% 100%
Shikigami.BlazorAdapter.Files.FolderPane 90.7% 83.9%
Shikigami.BlazorAdapter.Files.LoadFiles 100%
Shikigami.BlazorAdapter.Files.MemoryForm 100% 94.4%
Shikigami.BlazorAdapter.Files.OpenEntry 100%
Shikigami.BlazorAdapter.Files.SaveLanded 100%
Shikigami.BlazorAdapter.Files.SaveRefused 100%
Shikigami.BlazorAdapter.Files.SaveText 100%
Shikigami.BlazorAdapter.Files.SkillForm 100% 100%
Shikigami.BlazorAdapter.Files.TreeFailed 100%
Shikigami.BlazorAdapter.Files.TreeLoaded 100%
Shikigami.BlazorAdapter.Home.HomePage 88.2% 93.7%
Shikigami.BlazorAdapter.Notifications.CoalescingBridge`1 94.4% 80%
Shikigami.BlazorAdapter.Notifications.DomainChangedBridge 100%
Shikigami.BlazorAdapter.Notifications.DomainChangesReceived 100% 100%
Shikigami.BlazorAdapter.Notifications.FamiliarEventsBridge 100%
Shikigami.BlazorAdapter.Notifications.FamiliarEventsReceived 100%
Shikigami.BlazorAdapter.Profile.AvatarChosen 100%
Shikigami.BlazorAdapter.Profile.AvatarClearRequested 0%
Shikigami.BlazorAdapter.Profile.AvatarFailed 100%
Shikigami.BlazorAdapter.Profile.AvatarSaved 100%
Shikigami.BlazorAdapter.Profile.CreatedWithoutAvatar 100%
Shikigami.BlazorAdapter.Profile.ExpressionsEditor 86.6% 88.8%
Shikigami.BlazorAdapter.Profile.LoadProfile 100%
Shikigami.BlazorAdapter.Profile.PersonaEditor 100% 97.2%
Shikigami.BlazorAdapter.Profile.PersonaReloaded 100%
Shikigami.BlazorAdapter.Profile.PersonaSave 100%
Shikigami.BlazorAdapter.Profile.PersonaSaved 100%
Shikigami.BlazorAdapter.Profile.PersonaSaveFailed 100%
Shikigami.BlazorAdapter.Profile.ProfileEffects 89.4% 85%
Shikigami.BlazorAdapter.Profile.ProfileLoaded 100%
Shikigami.BlazorAdapter.Profile.ProfileMissing 100%
Shikigami.BlazorAdapter.Profile.ProfilePage 89.6% 87.3%
Shikigami.BlazorAdapter.Profile.ProfileReducers 94.7% 51.3%
Shikigami.BlazorAdapter.Profile.ProfileRefreshed 100%
Shikigami.BlazorAdapter.Profile.ProfileState 100% 100%
Shikigami.BlazorAdapter.Profile.ReloadPersona 100%
Shikigami.BlazorAdapter.Profile.RevertSelfRequested 100%
Shikigami.BlazorAdapter.Profile.SavePersonaRequested 100%
Shikigami.BlazorAdapter.Profile.SaveSettingsRequested 100%
Shikigami.BlazorAdapter.Profile.SelfLayer 92.3% 87.5%
Shikigami.BlazorAdapter.Profile.SettingsSaved 100%
Shikigami.BlazorAdapter.Profile.SettingsSaveFailed 100%
Shikigami.BlazorAdapter.Settings.BackupFailed 100%
Shikigami.BlazorAdapter.Settings.BackupSettingsLoaded 100%
Shikigami.BlazorAdapter.Settings.BackupSettingsLoadFailed 100%
Shikigami.BlazorAdapter.Settings.BackupsSection 100% 100%
Shikigami.BlazorAdapter.Settings.BackupsSettingsEffects 100%
Shikigami.BlazorAdapter.Settings.BackupsSettingsReducers 100%
Shikigami.BlazorAdapter.Settings.BackupsSettingsState 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceCss 100% 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceEffects 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceLoaded 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceLoadFailed 100%
Shikigami.BlazorAdapter.Settings.ChatAppearancePreview 100% 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceReducers 100% 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceSaved 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceSaveFailed 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceSection 100% 100%
Shikigami.BlazorAdapter.Settings.ChatAppearanceState 100%
Shikigami.BlazorAdapter.Settings.DefaultsSection 94.5% 85.7%
Shikigami.BlazorAdapter.Settings.DefaultsSettingsEffects 100%
Shikigami.BlazorAdapter.Settings.DefaultsSettingsReducers 100% 100%
Shikigami.BlazorAdapter.Settings.DefaultsSettingsState 100%
Shikigami.BlazorAdapter.Settings.LoadProviderSettings 100%
Shikigami.BlazorAdapter.Settings.ModelCatalogLoaded 100%
Shikigami.BlazorAdapter.Settings.ModelCatalogLoadFailed 100%
Shikigami.BlazorAdapter.Settings.ModelDefaultsLoaded 100%
Shikigami.BlazorAdapter.Settings.ModelDefaultsLoadFailed 100%
Shikigami.BlazorAdapter.Settings.ModelDefaultsSaved 100%
Shikigami.BlazorAdapter.Settings.ModelDefaultsSaveFailed 100%
Shikigami.BlazorAdapter.Settings.ModelHints 100% 100%
Shikigami.BlazorAdapter.Settings.ModelPicker 100% 98.2%
Shikigami.BlazorAdapter.Settings.Money 100%
Shikigami.BlazorAdapter.Settings.OpenRouterKeySaved 100%
Shikigami.BlazorAdapter.Settings.OpenRouterKeySaveFailed 100%
Shikigami.BlazorAdapter.Settings.ProviderKeyChecked 100%
Shikigami.BlazorAdapter.Settings.ProviderSection 100% 100%
Shikigami.BlazorAdapter.Settings.ProviderSettingsEffects 100% 100%
Shikigami.BlazorAdapter.Settings.ProviderSettingsLoaded 100%
Shikigami.BlazorAdapter.Settings.ProviderSettingsReducers 100% 100%
Shikigami.BlazorAdapter.Settings.ProviderSettingsState 100% 100%
Shikigami.BlazorAdapter.Settings.SaveChatAppearanceRequested 100%
Shikigami.BlazorAdapter.Settings.SaveModelDefaultsRequested 100%
Shikigami.BlazorAdapter.Settings.SaveOpenRouterKeyRequested 100%
Shikigami.BlazorAdapter.Shell.CastRail 100% 100%
Shikigami.Domain - 98.6%
Name Line Branch
Shikigami.Domain 98.6% 92.6%
Shikigami.Domain.Familiars.AccentPalette 100%
Shikigami.Domain.Familiars.ColourPair 100% 100%
Shikigami.Domain.Familiars.Expression 100% 100%
Shikigami.Domain.Familiars.ExpressionSet 100% 100%
Shikigami.Domain.Familiars.Familiar 100% 87.8%
Shikigami.Domain.Familiars.LearningSettings 100%
Shikigami.Domain.Familiars.MemoryBudgets 100% 100%
Shikigami.Domain.Familiars.ModelChoice 100% 100%
Shikigami.Domain.Familiars.OutreachSettings 100% 100%
Shikigami.Domain.Familiars.QuietHours 100% 87.5%
Shikigami.Domain.Familiars.ToolGroupIds 100%
Shikigami.Domain.Files.BlobContent 100% 75%
Shikigami.Domain.Files.BlobSha 87.5% 100%
Shikigami.Domain.Files.DefaultLayout 100%
Shikigami.Domain.Files.FileActor 100%
Shikigami.Domain.Files.FileAuthor 100% 100%
Shikigami.Domain.Files.FileContent 100% 100%
Shikigami.Domain.Files.FileNode 100% 90%
Shikigami.Domain.Files.FilePath 100% 97.8%
Shikigami.Domain.Files.FileRevision 100% 87.5%
Shikigami.Domain.Files.LocalDates 100%
Shikigami.Domain.Files.MediaTypes 100% 100%
Shikigami.Domain.Files.Permissions 100% 100%
Shikigami.Domain.Files.RunActor 100% 100%
Shikigami.Domain.Files.Slug 100% 100%
Shikigami.Domain.Files.TextContent 100% 100%
Shikigami.Domain.Files.TrashPath 100% 100%
Shikigami.Domain.Settings.AppSetting 100%
Shikigami.Domain.Text 100% 100%
System.Text.RegularExpressions.Generated 96.2% 85.2%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_0
94.8% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_2
96.8% 93.7%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__MediaTypeShape_3
95.9% 92.1%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7
916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__NamePattern_1
97.2% 94.4%
Shikigami.Infrastructure - 97.2%
Name Line Branch
Shikigami.Infrastructure 97.2% 86.7%
Shikigami.Infrastructure.Backups.BackupArtifactName 100% 100%
Shikigami.Infrastructure.Backups.BackupOptions 100%
Shikigami.Infrastructure.Backups.BackupSchedule 100% 83.3%
Shikigami.Infrastructure.Backups.BackupScheduler 96.6% 87.5%
Shikigami.Infrastructure.Backups.BackupWriter 98.5% 92.8%
Shikigami.Infrastructure.Backups.DatabaseFingerprint 91.9% 97%
Shikigami.Infrastructure.Backups.FileSystemBackupStore 100% 100%
Shikigami.Infrastructure.Backups.OwnerOnlyFile 100% 100%
Shikigami.Infrastructure.Backups.PreMigrationBackup 90% 100%
Shikigami.Infrastructure.Backups.SqliteSnapshot 88.2% 75%
Shikigami.Infrastructure.Blobs.BlobSweep 100% 100%
Shikigami.Infrastructure.Blobs.BlobSweepOptions 100% 100%
Shikigami.Infrastructure.Blobs.BlobSweepResult 100%
Shikigami.Infrastructure.Blobs.FileSystemBlobStore 95.9% 97%
Shikigami.Infrastructure.DailyMaintenanceService 97.8% 91.6%
Shikigami.Infrastructure.DependencyInjection 100% 100%
Shikigami.Infrastructure.Notifications.InProcessBus`1 100% 100%
Shikigami.Infrastructure.Persistence.Configurations.AppSettingConfiguration 100%
Shikigami.Infrastructure.Persistence.Configurations.FamiliarConfiguration 100%
Shikigami.Infrastructure.Persistence.Configurations.FileNodeConfiguration 100%
Shikigami.Infrastructure.Persistence.Configurations.FileRevisionConfigurati
on
100%
Shikigami.Infrastructure.Persistence.Configurations.UnreferencedBlobConfigu
ration
100%
Shikigami.Infrastructure.Persistence.Converters.BlobShaConverter 100%
Shikigami.Infrastructure.Persistence.Converters.ExpressionSetConverter 100% 100%
Shikigami.Infrastructure.Persistence.Converters.FilePathConverter 100%
Shikigami.Infrastructure.Persistence.Converters.Json 100% 100%
Shikigami.Infrastructure.Persistence.Converters.OutreachSettingsConverter 100% 100%
Shikigami.Infrastructure.Persistence.Converters.UtcTicksConverter 100%
Shikigami.Infrastructure.Persistence.DatabaseMigrator 100%
Shikigami.Infrastructure.Persistence.Migrations.AppSettings 100%
Shikigami.Infrastructure.Persistence.Migrations.FileCreatedBy 98%
Shikigami.Infrastructure.Persistence.Migrations.Initial 97.9%
Shikigami.Infrastructure.Persistence.Migrations.Profile 96.2%
Shikigami.Infrastructure.Persistence.Migrations.ShikigamiDbContextModelSnap
shot
100%
Shikigami.Infrastructure.Persistence.ShikigamiDbContext 98.6% 100%
Shikigami.Infrastructure.Persistence.ShikigamiDbContextFactory 0%
Shikigami.Infrastructure.Persistence.SqlitePragmaInterceptor 100% 100%
Shikigami.Infrastructure.Persistence.Stores.EfFamiliarStore 100%
Shikigami.Infrastructure.Persistence.Stores.EfFileStore 100% 100%
Shikigami.Infrastructure.Persistence.UnreferencedBlob 100%
Shikigami.Infrastructure.Provider.OpenRouterKeySource 100% 100%
Shikigami.Infrastructure.Provider.OpenRouterModelProvider 100% 93.4%
Shikigami.Infrastructure.Provider.OpenRouterOptions 100% 50%
Shikigami.Infrastructure.Provider.ResolvedKey 100% 50%
Shikigami.Infrastructure.Settings.EfAppSettingsStore 100% 100%
System.Text.RegularExpressions.Generated 81.4% 64.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F3A4F28468B24E9C
234D40E1D5003482F41439E482AB211B6EAD2E13F0A9D40B0__Pattern_0
84% 65.7%
Shikigami.Kernel - 90.9%
Name Line Branch
Shikigami.Kernel 90.9% 75%
Shikigami.Kernel.Err`1 100%
Shikigami.Kernel.Ok`1 100%
Shikigami.Kernel.Result`1 88.8% 75%
Shikigami.Server - 100%
Name Line Branch
Shikigami.Server 100% 95.3%
Program 100% 100%
Shikigami.Server.Backups.BackupConfiguration 100% 100%
Shikigami.Server.Components.App 100%
Shikigami.Server.Components.Layout.AppHeader 100% 78.5%
Shikigami.Server.Components.Layout.MainLayout 100%
Shikigami.Server.Components.Pages.Gate 100% 100%
Shikigami.Server.Diagnostics.SeedOnStart 100% 100%
Shikigami.Server.Provider.OpenRouterConfiguration 100% 100%
Shikigami.Server.Security.AccessGate 100% 87.5%
Shikigami.Server.Security.AccessSecret 100% 100%
Shikigami.Server.Security.GateThrottle 100% 100%
Shikigami.Server.Security.ProxyNetwork 100% 100%
Shikigami.Server.VolumeStartupValidator 100% 100%
Shikigami.UseCases - 96.1%
Name Line Branch
Shikigami.UseCases 96.1% 94%
Shikigami.UseCases.Backups.BackupArtifact 100%
Shikigami.UseCases.Backups.BackupFailure 100%
Shikigami.UseCases.Backups.BackupJobState 100%
Shikigami.UseCases.Backups.BackupPolicy 100%
Shikigami.UseCases.Backups.BackupStatusView 100% 100%
Shikigami.UseCases.Backups.DatabaseSnapshot 100%
Shikigami.UseCases.Backups.DownloadDatabaseSnapshot 100%
Shikigami.UseCases.Backups.GetBackupStatus 100%
Shikigami.UseCases.Backups.IBackupStore 0%
Shikigami.UseCases.Backups.RunBackupNow 100%
Shikigami.UseCases.DependencyInjection 100%
Shikigami.UseCases.Diagnostics.SeedDevData 86.3% 33.3%
Shikigami.UseCases.Familiars.AvatarImage 100%
Shikigami.UseCases.Familiars.ClearFamiliarAvatar 100%
Shikigami.UseCases.Familiars.CreateFamiliar 97.2% 70%
Shikigami.UseCases.Familiars.DuplicateFamiliar 96.7% 91.6%
Shikigami.UseCases.Familiars.ExpressionView 100%
Shikigami.UseCases.Familiars.FamiliarDetail 100%
Shikigami.UseCases.Familiars.FamiliarEvent 100%
Shikigami.UseCases.Familiars.FamiliarFiles 100% 100%
Shikigami.UseCases.Familiars.FamiliarLimits 71.4%
Shikigami.UseCases.Familiars.FamiliarPersona 96.8% 90%
Shikigami.UseCases.Familiars.FamiliarSettings 100% 100%
Shikigami.UseCases.Familiars.FamiliarSummary 100% 100%
Shikigami.UseCases.Familiars.FamiliarTemplates 100% 100%
Shikigami.UseCases.Familiars.FamiliarViews 100% 94.4%
Shikigami.UseCases.Familiars.GetFamiliar 100% 100%
Shikigami.UseCases.Familiars.ListFamiliars 100%
Shikigami.UseCases.Familiars.PersonaFile 100%
Shikigami.UseCases.Familiars.PurgeFamiliar 100%
Shikigami.UseCases.Familiars.ReadFamiliarAvatar 100% 87.5%
Shikigami.UseCases.Familiars.SaveFamiliarSettings 94.1% 87.5%
Shikigami.UseCases.Familiars.SelfRevision 100%
Shikigami.UseCases.Familiars.SetFamiliarArchived 100% 100%
Shikigami.UseCases.Familiars.SetFamiliarAvatar 100% 100%
Shikigami.UseCases.Familiars.SetFamiliarTrashed 100% 100%
Shikigami.UseCases.Familiars.ToolGroupCatalog 100%
Shikigami.UseCases.Familiars.ToolGroupInfo 100%
Shikigami.UseCases.Files.Browser.FileBrowser 92.7% 85.3%
Shikigami.UseCases.Files.Browser.FileBytes 100%
Shikigami.UseCases.Files.Browser.FileItem 100%
Shikigami.UseCases.Files.Browser.FileOk`1 100%
Shikigami.UseCases.Files.Browser.FileRefusal 100%
Shikigami.UseCases.Files.Browser.FileRefused`1 100%
Shikigami.UseCases.Files.Browser.FileRevisionView 100%
Shikigami.UseCases.Files.Browser.FileView 100%
Shikigami.UseCases.Files.Browser.MemoryBudget 100%
Shikigami.UseCases.Files.Browser.MemoryBudgetUse 100%
Shikigami.UseCases.Files.Browser.MemoryDraft 100%
Shikigami.UseCases.Files.Browser.SkillView 100%
Shikigami.UseCases.Files.Browser.SpecialForms 98.3% 90.2%
Shikigami.UseCases.Files.FamiliarWriteLocks 100% 100%
Shikigami.UseCases.Files.FileAuthors 100% 100%
Shikigami.UseCases.Files.FileMaintenance 100% 90%
Shikigami.UseCases.Files.FileMaintenanceResult 100%
Shikigami.UseCases.Files.FileSystem 99% 96%
Shikigami.UseCases.Files.FileWriteRefused 100%
Shikigami.UseCases.Files.FileWritten 100%
Shikigami.UseCases.Files.FsError 100% 50%
Shikigami.UseCases.Files.FsResult`1 100% 50%
Shikigami.UseCases.Files.Mounts.FileEntry 100%
Shikigami.UseCases.Files.Mounts.FileRead 100%
Shikigami.UseCases.Files.Mounts.GeneratedMount 100% 100%
Shikigami.UseCases.Files.Mounts.Mount 100%
Shikigami.UseCases.Files.Mounts.MountTable 100% 100%
Shikigami.UseCases.Files.Mounts.StoredMount 100% 100%
Shikigami.UseCases.Files.SeedDefaultLayout 100% 100%
Shikigami.UseCases.Files.Special.Budgets 100% 96.6%
Shikigami.UseCases.Files.Special.FrontMatter 100% 78.5%
Shikigami.UseCases.Files.Special.HeaderReader 98.2% 84.8%
Shikigami.UseCases.Files.Special.HeaderValue 100% 100%
Shikigami.UseCases.Files.Special.HeaderWriter 95.3% 90.7%
Shikigami.UseCases.Files.Special.MemoryFile 100% 87.5%
Shikigami.UseCases.Files.Special.MemoryUse 100%
Shikigami.UseCases.Files.Special.Numbers 100%
Shikigami.UseCases.Files.Special.RoutineFile 100% 99%
Shikigami.UseCases.Files.Special.SkillFile 100% 94.7%
Shikigami.UseCases.Files.Special.SpecialFolders 100% 100%
Shikigami.UseCases.Files.Special.ValidationProblem 100%
Shikigami.UseCases.Files.StoredBlob 100%
Shikigami.UseCases.Files.Utf8Order 100%
Shikigami.UseCases.Notifications.DomainChanged 100%
Shikigami.UseCases.Settings.AppearanceColour 100% 100%
Shikigami.UseCases.Settings.CatalogModel 100% 100%
Shikigami.UseCases.Settings.ChatAppearance 100%
Shikigami.UseCases.Settings.ChatAppearanceJson 100% 100%
Shikigami.UseCases.Settings.ChatAppearanceLimits 100% 100%
Shikigami.UseCases.Settings.CheckOpenRouterKey 100%
Shikigami.UseCases.Settings.GetChatAppearance 100%
Shikigami.UseCases.Settings.GetModelCatalog 100% 100%
Shikigami.UseCases.Settings.GetModelDefaults 100% 83.3%
Shikigami.UseCases.Settings.GetProviderSettings 100%
Shikigami.UseCases.Settings.ModelCatalog 100%
Shikigami.UseCases.Settings.ModelDefaults 100% 100%
Shikigami.UseCases.Settings.ProviderKeyInfo 100%
Shikigami.UseCases.Settings.ProviderKeyState 100%
Shikigami.UseCases.Settings.ProviderSettingsView 100% 100%
Shikigami.UseCases.Settings.RemoveOpenRouterKey 100%
Shikigami.UseCases.Settings.SaveChatAppearance 100% 100%
Shikigami.UseCases.Settings.SaveModelDefaults 100% 100%
Shikigami.UseCases.Settings.SaveOpenRouterKey 100% 100%
Shikigami.UseCases.Shell.AllowEveryCommand 100%
Shikigami.UseCases.Shell.Commands.Basename 100% 100%
Shikigami.UseCases.Shell.Commands.Builtin 100% 100%
Shikigami.UseCases.Shell.Commands.Cat 100% 100%
Shikigami.UseCases.Shell.Commands.Cd 97.5% 100%
Shikigami.UseCases.Shell.Commands.CFormat 100% 100%
Shikigami.UseCases.Shell.Commands.CNumbers 100% 100%
Shikigami.UseCases.Shell.Commands.CommandContext 97% 92.8%
Shikigami.UseCases.Shell.Commands.CommandRegistry 100% 100%
Shikigami.UseCases.Shell.Commands.Cut 100% 100%
Shikigami.UseCases.Shell.Commands.CutPlan 100% 100%
Shikigami.UseCases.Shell.Commands.Date 100% 98%
Shikigami.UseCases.Shell.Commands.Diff 100% 100%
Shikigami.UseCases.Shell.Commands.Dirname 100% 100%
Shikigami.UseCases.Shell.Commands.Echo 90.7% 92.3%
Shikigami.UseCases.Shell.Commands.Escapes 100% 97.4%
Shikigami.UseCases.Shell.Commands.False 88.8%
Shikigami.UseCases.Shell.Commands.FileCommand 100% 100%
Shikigami.UseCases.Shell.Commands.FileNames 100% 100%
Shikigami.UseCases.Shell.Commands.Filters 100% 90%
Shikigami.UseCases.Shell.Commands.Find 100% 97.7%
Shikigami.UseCases.Shell.Commands.FindExpression 100% 98.7%
Shikigami.UseCases.Shell.Commands.FindItem 100% 100%
Shikigami.UseCases.Shell.Commands.FindLine 100% 100%
Shikigami.UseCases.Shell.Commands.FindNode 100% 100%
Shikigami.UseCases.Shell.Commands.FindReference 100%
Shikigami.UseCases.Shell.Commands.GetOpt 100% 98.2%
Shikigami.UseCases.Shell.Commands.Grep 99.2% 98.9%
Shikigami.UseCases.Shell.Commands.Head 100% 100%
Shikigami.UseCases.Shell.Commands.HelpCommand 94.4% 100%
Shikigami.UseCases.Shell.Commands.History 97.5% 94%
Shikigami.UseCases.Shell.Commands.Invocation 100% 50%
Shikigami.UseCases.Shell.Commands.LinesCommand 97.2% 96.1%
Shikigami.UseCases.Shell.Commands.LineSearch 100% 100%
Shikigami.UseCases.Shell.Commands.Ls 97.2% 95.6%
Shikigami.UseCases.Shell.Commands.Magic 100% 95.9%
Shikigami.UseCases.Shell.Commands.Nl 100% 99.1%
Shikigami.UseCases.Shell.Commands.Numbers 100% 100%
Shikigami.UseCases.Shell.Commands.Operand 100%
Shikigami.UseCases.Shell.Commands.OptionSpec 100%
Shikigami.UseCases.Shell.Commands.ParsedOptions 100%
Shikigami.UseCases.Shell.Commands.Printf 100% 99.5%
Shikigami.UseCases.Shell.Commands.Pwd 100% 100%
Shikigami.UseCases.Shell.Commands.Ranges 100% 100%
Shikigami.UseCases.Shell.Commands.Rg 97.7% 94.7%
Shikigami.UseCases.Shell.Commands.SearchFiles 90% 83.3%
Shikigami.UseCases.Shell.Commands.SearchPatterns 100% 100%
Shikigami.UseCases.Shell.Commands.SearchSettings 100%
Shikigami.UseCases.Shell.Commands.Sed 100% 100%
Shikigami.UseCases.Shell.Commands.SedAddress 100%
Shikigami.UseCases.Shell.Commands.SedCommand 100%
Shikigami.UseCases.Shell.Commands.SedException 100%
Shikigami.UseCases.Shell.Commands.SedInput 100%
Shikigami.UseCases.Shell.Commands.SedParser 100% 99.8%
Shikigami.UseCases.Shell.Commands.SedPart 100%
Shikigami.UseCases.Shell.Commands.SedProgram 100%
Shikigami.UseCases.Shell.Commands.SedRegex 100%
Shikigami.UseCases.Shell.Commands.SedRun 100% 100%
Shikigami.UseCases.Shell.Commands.SedSubstitution 100%
Shikigami.UseCases.Shell.Commands.ShellCommand 100% 100%
Shikigami.UseCases.Shell.Commands.ShellQuote 100% 100%
Shikigami.UseCases.Shell.Commands.Sizes 100% 100%
Shikigami.UseCases.Shell.Commands.Sort 100% 94.1%
Shikigami.UseCases.Shell.Commands.SortKey 100% 100%
Shikigami.UseCases.Shell.Commands.SortOrder 99.5% 99.5%
Shikigami.UseCases.Shell.Commands.Stat 100% 90.9%
Shikigami.UseCases.Shell.Commands.StatFacts 100% 100%
Shikigami.UseCases.Shell.Commands.StatFormat 100% 99.5%
Shikigami.UseCases.Shell.Commands.Tail 100% 100%
Shikigami.UseCases.Shell.Commands.TextFile 100%
Shikigami.UseCases.Shell.Commands.Tr 100% 100%
Shikigami.UseCases.Shell.Commands.TreeCommand 100% 99.2%
Shikigami.UseCases.Shell.Commands.TrPlan 100% 100%
Shikigami.UseCases.Shell.Commands.TrSequence 93.9% 80%
Shikigami.UseCases.Shell.Commands.TrSet 100% 97.2%
Shikigami.UseCases.Shell.Commands.True 88.8%
Shikigami.UseCases.Shell.Commands.Uniq 100% 100%
Shikigami.UseCases.Shell.Commands.VersionOrder 100% 96.6%
Shikigami.UseCases.Shell.Commands.Wc 100% 97.3%
Shikigami.UseCases.Shell.Execution.CaptureSink 100% 100%
Shikigami.UseCases.Shell.Execution.ClosedSink 100%
Shikigami.UseCases.Shell.Execution.ClosedStreamException 100%
Shikigami.UseCases.Shell.Execution.CodePointOrder 100% 100%
Shikigami.UseCases.Shell.Execution.DateInput 96.8% 94.3%
Shikigami.UseCases.Shell.Execution.Errno 100% 100%
Shikigami.UseCases.Shell.Execution.Executor 98.1% 95.7%
Shikigami.UseCases.Shell.Execution.Expander 97.3% 95.1%
Shikigami.UseCases.Shell.Execution.Glob 94.6% 95.9%
Shikigami.UseCases.Shell.Execution.GnuQuote 91.2% 92.8%
Shikigami.UseCases.Shell.Execution.InputSource 100%
Shikigami.UseCases.Shell.Execution.LineChange 100%
Shikigami.UseCases.Shell.Execution.LineDiff 98.8% 98.1%
Shikigami.UseCases.Shell.Execution.LongDouble 100% 98.7%
Shikigami.UseCases.Shell.Execution.NullSink 100%
Shikigami.UseCases.Shell.Execution.OutputLimit 95.8% 94.7%
Shikigami.UseCases.Shell.Execution.PathResolver 100% 97%
Shikigami.UseCases.Shell.Execution.PipeSink 100% 100%
Shikigami.UseCases.Shell.Execution.PosixRegex 89.2% 90.7%
Shikigami.UseCases.Shell.Execution.PosixRegexException 100%
Shikigami.UseCases.Shell.Execution.ResolvedPath 100%
Shikigami.UseCases.Shell.Execution.ShellLimitException 100%
Shikigami.UseCases.Shell.Execution.ShellScope 94.7% 83.3%
Shikigami.UseCases.Shell.Execution.ShellTree 97.5% 91.3%
Shikigami.UseCases.Shell.Execution.Strftime 95.6% 92.3%
Shikigami.UseCases.Shell.Execution.Terminal 100% 100%
Shikigami.UseCases.Shell.Execution.TextLine 50% 0%
Shikigami.UseCases.Shell.Execution.TextLines 100% 100%
Shikigami.UseCases.Shell.Execution.TreeWalker 100% 100%
Shikigami.UseCases.Shell.Execution.Walked 100%
Shikigami.UseCases.Shell.Help.CommandHints 100% 100%
Shikigami.UseCases.Shell.Help.MountGuide 100%
Shikigami.UseCases.Shell.Help.ShellHelp 100% 100%
Shikigami.UseCases.Shell.ShellCommandPlan 100%
Shikigami.UseCases.Shell.ShellCommandRecord 100%
Shikigami.UseCases.Shell.ShellEffects 100%
Shikigami.UseCases.Shell.ShellInterpreter 100% 100%
Shikigami.UseCases.Shell.ShellLimits 100%
Shikigami.UseCases.Shell.ShellRead 100%
Shikigami.UseCases.Shell.ShellResult 75%
Shikigami.UseCases.Shell.ShellSession 100% 100%
Shikigami.UseCases.Shell.Syntax.AndOrList 100%
Shikigami.UseCases.Shell.Syntax.Assignment 100%
Shikigami.UseCases.Shell.Syntax.ByteText 100% 88.8%
Shikigami.UseCases.Shell.Syntax.HereDocBody 100%
Shikigami.UseCases.Shell.Syntax.Lexer 93.5% 89.8%
Shikigami.UseCases.Shell.Syntax.LiteralPart 100%
Shikigami.UseCases.Shell.Syntax.ParameterPart 100%
Shikigami.UseCases.Shell.Syntax.Parser 96.9% 90.1%
Shikigami.UseCases.Shell.Syntax.Pipeline 100%
Shikigami.UseCases.Shell.Syntax.Redirection 100%
Shikigami.UseCases.Shell.Syntax.Script 100%
Shikigami.UseCases.Shell.Syntax.ShellSyntaxException 100%
Shikigami.UseCases.Shell.Syntax.SimpleCommand 100%
Shikigami.UseCases.Shell.Syntax.TildePart 100% 100%
Shikigami.UseCases.Shell.Syntax.Token 77.7% 66.6%
Shikigami.UseCases.Shell.Syntax.Word 100% 83.3%
Shikigami.UseCases.Shell.Syntax.WordBuilder 100% 100%
System.Text.RegularExpressions.Generated 81.1% 72%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__AssignmentHead_10
95.8% 95.4%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__BraceExpansion_9
93.4% 85.4%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__HexColour_4
97.4% 96.4%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Interval_1
83.6% 75%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__IntervalBody_8
91.6% 86.1%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NameRule_3
92.1% 84.3%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NewerXY_6
88.5% 62.5%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Number_5
67.3% 62.7%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__OldCount_7
94.8% 83.3%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__TimeOfDay_0
70.9% 58.3%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048
F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Window_2
62.8% 48.3%
<!-- coverage-comment --> > 🔄 **Auto-updating coverage report** — this comment is regenerated on every push, so the numbers below always reflect the commit shown here, not the branch tip. > > **Commit:** `01369a5` · **Generated:** 2026-10-18 19:28:33 UTC · **Revision:** #1 # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 10/18/2026 - 19:28:33 | | Coverage date: | 10/18/2026 - 19:26:54 - 10/18/2026 - 19:28:29 | | Parser: | MultiReport (5x Cobertura) | | Assemblies: | 6 | | Classes: | 464 | | Files: | 239 | | **Line coverage:** | 96.5% (17407 of 18038) | | Covered lines: | 17407 | | Uncovered lines: | 631 | | Coverable lines: | 18038 | | Total lines: | 35591 | | **Branch coverage:** | 93.2% (12237 of 13125) | | Covered branches: | 12237 | | Total branches: | 13125 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Shikigami.BlazorAdapter - 95.7%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.BlazorAdapter**|**95.7%**|**89%**| |Shikigami.BlazorAdapter.BlazorAdapterAssembly|100%|| |Shikigami.BlazorAdapter.Cast.CastActionFailed|100%|| |Shikigami.BlazorAdapter.Cast.CastEffects|93.3%|93.7%| |Shikigami.BlazorAdapter.Cast.CastLoaded|100%|| |Shikigami.BlazorAdapter.Cast.CastReducers|93.3%|50%| |Shikigami.BlazorAdapter.Cast.CastState|100%|100%| |Shikigami.BlazorAdapter.Cast.CreateFamiliarFailed|100%|| |Shikigami.BlazorAdapter.Cast.CreateFamiliarRequested|100%|| |Shikigami.BlazorAdapter.Cast.DuplicateFamiliarRequested|100%|| |Shikigami.BlazorAdapter.Cast.FamiliarAvatar|100%|75%| |Shikigami.BlazorAdapter.Cast.FamiliarCreated|100%|| |Shikigami.BlazorAdapter.Cast.NewFamiliarDialog|97.2%|83.3%| |Shikigami.BlazorAdapter.Cast.PurgeFamiliarRequested|100%|| |Shikigami.BlazorAdapter.Cast.SetFamiliarArchivedRequested|100%|| |Shikigami.BlazorAdapter.Cast.SetFamiliarTrashedRequested|100%|| |Shikigami.BlazorAdapter.Cast.TrashPage|89.4%|93.7%| |Shikigami.BlazorAdapter.EffectCalls|100%|| |Shikigami.BlazorAdapter.Files.ConflictSettled|100%|| |Shikigami.BlazorAdapter.Files.DismissFileError|100%|| |Shikigami.BlazorAdapter.Files.EntryMissing|100%|| |Shikigami.BlazorAdapter.Files.EntryOpened|100%|| |Shikigami.BlazorAdapter.Files.FileActionDone|100%|| |Shikigami.BlazorAdapter.Files.FileActionFailed|100%|| |Shikigami.BlazorAdapter.Files.FileActionRequested|100%|| |Shikigami.BlazorAdapter.Files.FileLinks|100%|100%| |Shikigami.BlazorAdapter.Files.FilePane|95.1%|88.5%| |Shikigami.BlazorAdapter.Files.FilePaneClosed|100%|| |Shikigami.BlazorAdapter.Files.FilesEffects|98.2%|94.7%| |Shikigami.BlazorAdapter.Files.FilesPage|96.9%|97%| |Shikigami.BlazorAdapter.Files.FilesReducers|100%|82%| |Shikigami.BlazorAdapter.Files.FilesState|100%|100%| |Shikigami.BlazorAdapter.Files.FileTreeBranch|100%|100%| |Shikigami.BlazorAdapter.Files.FolderPane|90.7%|83.9%| |Shikigami.BlazorAdapter.Files.LoadFiles|100%|| |Shikigami.BlazorAdapter.Files.MemoryForm|100%|94.4%| |Shikigami.BlazorAdapter.Files.OpenEntry|100%|| |Shikigami.BlazorAdapter.Files.SaveLanded|100%|| |Shikigami.BlazorAdapter.Files.SaveRefused|100%|| |Shikigami.BlazorAdapter.Files.SaveText|100%|| |Shikigami.BlazorAdapter.Files.SkillForm|100%|100%| |Shikigami.BlazorAdapter.Files.TreeFailed|100%|| |Shikigami.BlazorAdapter.Files.TreeLoaded|100%|| |Shikigami.BlazorAdapter.Home.HomePage|88.2%|93.7%| |Shikigami.BlazorAdapter.Notifications.CoalescingBridge`1|94.4%|80%| |Shikigami.BlazorAdapter.Notifications.DomainChangedBridge|100%|| |Shikigami.BlazorAdapter.Notifications.DomainChangesReceived|100%|100%| |Shikigami.BlazorAdapter.Notifications.FamiliarEventsBridge|100%|| |Shikigami.BlazorAdapter.Notifications.FamiliarEventsReceived|100%|| |Shikigami.BlazorAdapter.Profile.AvatarChosen|100%|| |Shikigami.BlazorAdapter.Profile.AvatarClearRequested|0%|| |Shikigami.BlazorAdapter.Profile.AvatarFailed|100%|| |Shikigami.BlazorAdapter.Profile.AvatarSaved|100%|| |Shikigami.BlazorAdapter.Profile.CreatedWithoutAvatar|100%|| |Shikigami.BlazorAdapter.Profile.ExpressionsEditor|86.6%|88.8%| |Shikigami.BlazorAdapter.Profile.LoadProfile|100%|| |Shikigami.BlazorAdapter.Profile.PersonaEditor|100%|97.2%| |Shikigami.BlazorAdapter.Profile.PersonaReloaded|100%|| |Shikigami.BlazorAdapter.Profile.PersonaSave|100%|| |Shikigami.BlazorAdapter.Profile.PersonaSaved|100%|| |Shikigami.BlazorAdapter.Profile.PersonaSaveFailed|100%|| |Shikigami.BlazorAdapter.Profile.ProfileEffects|89.4%|85%| |Shikigami.BlazorAdapter.Profile.ProfileLoaded|100%|| |Shikigami.BlazorAdapter.Profile.ProfileMissing|100%|| |Shikigami.BlazorAdapter.Profile.ProfilePage|89.6%|87.3%| |Shikigami.BlazorAdapter.Profile.ProfileReducers|94.7%|51.3%| |Shikigami.BlazorAdapter.Profile.ProfileRefreshed|100%|| |Shikigami.BlazorAdapter.Profile.ProfileState|100%|100%| |Shikigami.BlazorAdapter.Profile.ReloadPersona|100%|| |Shikigami.BlazorAdapter.Profile.RevertSelfRequested|100%|| |Shikigami.BlazorAdapter.Profile.SavePersonaRequested|100%|| |Shikigami.BlazorAdapter.Profile.SaveSettingsRequested|100%|| |Shikigami.BlazorAdapter.Profile.SelfLayer|92.3%|87.5%| |Shikigami.BlazorAdapter.Profile.SettingsSaved|100%|| |Shikigami.BlazorAdapter.Profile.SettingsSaveFailed|100%|| |Shikigami.BlazorAdapter.Settings.BackupFailed|100%|| |Shikigami.BlazorAdapter.Settings.BackupSettingsLoaded|100%|| |Shikigami.BlazorAdapter.Settings.BackupSettingsLoadFailed|100%|| |Shikigami.BlazorAdapter.Settings.BackupsSection|100%|100%| |Shikigami.BlazorAdapter.Settings.BackupsSettingsEffects|100%|| |Shikigami.BlazorAdapter.Settings.BackupsSettingsReducers|100%|| |Shikigami.BlazorAdapter.Settings.BackupsSettingsState|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearanceCss|100%|100%| |Shikigami.BlazorAdapter.Settings.ChatAppearanceEffects|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearanceLoaded|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearanceLoadFailed|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearancePreview|100%|100%| |Shikigami.BlazorAdapter.Settings.ChatAppearanceReducers|100%|100%| |Shikigami.BlazorAdapter.Settings.ChatAppearanceSaved|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearanceSaveFailed|100%|| |Shikigami.BlazorAdapter.Settings.ChatAppearanceSection|100%|100%| |Shikigami.BlazorAdapter.Settings.ChatAppearanceState|100%|| |Shikigami.BlazorAdapter.Settings.DefaultsSection|94.5%|85.7%| |Shikigami.BlazorAdapter.Settings.DefaultsSettingsEffects|100%|| |Shikigami.BlazorAdapter.Settings.DefaultsSettingsReducers|100%|100%| |Shikigami.BlazorAdapter.Settings.DefaultsSettingsState|100%|| |Shikigami.BlazorAdapter.Settings.LoadProviderSettings|100%|| |Shikigami.BlazorAdapter.Settings.ModelCatalogLoaded|100%|| |Shikigami.BlazorAdapter.Settings.ModelCatalogLoadFailed|100%|| |Shikigami.BlazorAdapter.Settings.ModelDefaultsLoaded|100%|| |Shikigami.BlazorAdapter.Settings.ModelDefaultsLoadFailed|100%|| |Shikigami.BlazorAdapter.Settings.ModelDefaultsSaved|100%|| |Shikigami.BlazorAdapter.Settings.ModelDefaultsSaveFailed|100%|| |Shikigami.BlazorAdapter.Settings.ModelHints|100%|100%| |Shikigami.BlazorAdapter.Settings.ModelPicker|100%|98.2%| |Shikigami.BlazorAdapter.Settings.Money|100%|| |Shikigami.BlazorAdapter.Settings.OpenRouterKeySaved|100%|| |Shikigami.BlazorAdapter.Settings.OpenRouterKeySaveFailed|100%|| |Shikigami.BlazorAdapter.Settings.ProviderKeyChecked|100%|| |Shikigami.BlazorAdapter.Settings.ProviderSection|100%|100%| |Shikigami.BlazorAdapter.Settings.ProviderSettingsEffects|100%|100%| |Shikigami.BlazorAdapter.Settings.ProviderSettingsLoaded|100%|| |Shikigami.BlazorAdapter.Settings.ProviderSettingsReducers|100%|100%| |Shikigami.BlazorAdapter.Settings.ProviderSettingsState|100%|100%| |Shikigami.BlazorAdapter.Settings.SaveChatAppearanceRequested|100%|| |Shikigami.BlazorAdapter.Settings.SaveModelDefaultsRequested|100%|| |Shikigami.BlazorAdapter.Settings.SaveOpenRouterKeyRequested|100%|| |Shikigami.BlazorAdapter.Shell.CastRail|100%|100%| </details> <details><summary>Shikigami.Domain - 98.6%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.Domain**|**98.6%**|**92.6%**| |Shikigami.Domain.Familiars.AccentPalette|100%|| |Shikigami.Domain.Familiars.ColourPair|100%|100%| |Shikigami.Domain.Familiars.Expression|100%|100%| |Shikigami.Domain.Familiars.ExpressionSet|100%|100%| |Shikigami.Domain.Familiars.Familiar|100%|87.8%| |Shikigami.Domain.Familiars.LearningSettings|100%|| |Shikigami.Domain.Familiars.MemoryBudgets|100%|100%| |Shikigami.Domain.Familiars.ModelChoice|100%|100%| |Shikigami.Domain.Familiars.OutreachSettings|100%|100%| |Shikigami.Domain.Familiars.QuietHours|100%|87.5%| |Shikigami.Domain.Familiars.ToolGroupIds|100%|| |Shikigami.Domain.Files.BlobContent|100%|75%| |Shikigami.Domain.Files.BlobSha|87.5%|100%| |Shikigami.Domain.Files.DefaultLayout|100%|| |Shikigami.Domain.Files.FileActor|100%|| |Shikigami.Domain.Files.FileAuthor|100%|100%| |Shikigami.Domain.Files.FileContent|100%|100%| |Shikigami.Domain.Files.FileNode|100%|90%| |Shikigami.Domain.Files.FilePath|100%|97.8%| |Shikigami.Domain.Files.FileRevision|100%|87.5%| |Shikigami.Domain.Files.LocalDates|100%|| |Shikigami.Domain.Files.MediaTypes|100%|100%| |Shikigami.Domain.Files.Permissions|100%|100%| |Shikigami.Domain.Files.RunActor|100%|100%| |Shikigami.Domain.Files.Slug|100%|100%| |Shikigami.Domain.Files.TextContent|100%|100%| |Shikigami.Domain.Files.TrashPath|100%|100%| |Shikigami.Domain.Settings.AppSetting|100%|| |Shikigami.Domain.Text|100%|100%| |System.Text.RegularExpressions.Generated|96.2%|85.2%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7<br/>916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_0|94.8%|67.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7<br/>916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__Hex_2|96.8%|93.7%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7<br/>916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__MediaTypeShape_3|95.9%|92.1%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FDFEB299C15773C7<br/>916AED265A903CAC15169BB5EE676ADBEFE655D493DD7AC75__NamePattern_1|97.2%|94.4%| </details> <details><summary>Shikigami.Infrastructure - 97.2%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.Infrastructure**|**97.2%**|**86.7%**| |Shikigami.Infrastructure.Backups.BackupArtifactName|100%|100%| |Shikigami.Infrastructure.Backups.BackupOptions|100%|| |Shikigami.Infrastructure.Backups.BackupSchedule|100%|83.3%| |Shikigami.Infrastructure.Backups.BackupScheduler|96.6%|87.5%| |Shikigami.Infrastructure.Backups.BackupWriter|98.5%|92.8%| |Shikigami.Infrastructure.Backups.DatabaseFingerprint|91.9%|97%| |Shikigami.Infrastructure.Backups.FileSystemBackupStore|100%|100%| |Shikigami.Infrastructure.Backups.OwnerOnlyFile|100%|100%| |Shikigami.Infrastructure.Backups.PreMigrationBackup|90%|100%| |Shikigami.Infrastructure.Backups.SqliteSnapshot|88.2%|75%| |Shikigami.Infrastructure.Blobs.BlobSweep|100%|100%| |Shikigami.Infrastructure.Blobs.BlobSweepOptions|100%|100%| |Shikigami.Infrastructure.Blobs.BlobSweepResult|100%|| |Shikigami.Infrastructure.Blobs.FileSystemBlobStore|95.9%|97%| |Shikigami.Infrastructure.DailyMaintenanceService|97.8%|91.6%| |Shikigami.Infrastructure.DependencyInjection|100%|100%| |Shikigami.Infrastructure.Notifications.InProcessBus`1|100%|100%| |Shikigami.Infrastructure.Persistence.Configurations.AppSettingConfiguration|100%|| |Shikigami.Infrastructure.Persistence.Configurations.FamiliarConfiguration|100%|| |Shikigami.Infrastructure.Persistence.Configurations.FileNodeConfiguration|100%|| |Shikigami.Infrastructure.Persistence.Configurations.FileRevisionConfigurati<br/>on|100%|| |Shikigami.Infrastructure.Persistence.Configurations.UnreferencedBlobConfigu<br/>ration|100%|| |Shikigami.Infrastructure.Persistence.Converters.BlobShaConverter|100%|| |Shikigami.Infrastructure.Persistence.Converters.ExpressionSetConverter|100%|100%| |Shikigami.Infrastructure.Persistence.Converters.FilePathConverter|100%|| |Shikigami.Infrastructure.Persistence.Converters.Json|100%|100%| |Shikigami.Infrastructure.Persistence.Converters.OutreachSettingsConverter|100%|100%| |Shikigami.Infrastructure.Persistence.Converters.UtcTicksConverter|100%|| |Shikigami.Infrastructure.Persistence.DatabaseMigrator|100%|| |Shikigami.Infrastructure.Persistence.Migrations.AppSettings|100%|| |Shikigami.Infrastructure.Persistence.Migrations.FileCreatedBy|98%|| |Shikigami.Infrastructure.Persistence.Migrations.Initial|97.9%|| |Shikigami.Infrastructure.Persistence.Migrations.Profile|96.2%|| |Shikigami.Infrastructure.Persistence.Migrations.ShikigamiDbContextModelSnap<br/>shot|100%|| |Shikigami.Infrastructure.Persistence.ShikigamiDbContext|98.6%|100%| |Shikigami.Infrastructure.Persistence.ShikigamiDbContextFactory|0%|| |Shikigami.Infrastructure.Persistence.SqlitePragmaInterceptor|100%|100%| |Shikigami.Infrastructure.Persistence.Stores.EfFamiliarStore|100%|| |Shikigami.Infrastructure.Persistence.Stores.EfFileStore|100%|100%| |Shikigami.Infrastructure.Persistence.UnreferencedBlob|100%|| |Shikigami.Infrastructure.Provider.OpenRouterKeySource|100%|100%| |Shikigami.Infrastructure.Provider.OpenRouterModelProvider|100%|93.4%| |Shikigami.Infrastructure.Provider.OpenRouterOptions|100%|50%| |Shikigami.Infrastructure.Provider.ResolvedKey|100%|50%| |Shikigami.Infrastructure.Settings.EfAppSettingsStore|100%|100%| |System.Text.RegularExpressions.Generated|81.4%|64.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F3A4F28468B24E9C<br/>234D40E1D5003482F41439E482AB211B6EAD2E13F0A9D40B0__Pattern_0|84%|65.7%| </details> <details><summary>Shikigami.Kernel - 90.9%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.Kernel**|**90.9%**|**75%**| |Shikigami.Kernel.Err`1|100%|| |Shikigami.Kernel.Ok`1|100%|| |Shikigami.Kernel.Result`1|88.8%|75%| </details> <details><summary>Shikigami.Server - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.Server**|**100%**|**95.3%**| |Program|100%|100%| |Shikigami.Server.Backups.BackupConfiguration|100%|100%| |Shikigami.Server.Components.App|100%|| |Shikigami.Server.Components.Layout.AppHeader|100%|78.5%| |Shikigami.Server.Components.Layout.MainLayout|100%|| |Shikigami.Server.Components.Pages.Gate|100%|100%| |Shikigami.Server.Diagnostics.SeedOnStart|100%|100%| |Shikigami.Server.Provider.OpenRouterConfiguration|100%|100%| |Shikigami.Server.Security.AccessGate|100%|87.5%| |Shikigami.Server.Security.AccessSecret|100%|100%| |Shikigami.Server.Security.GateThrottle|100%|100%| |Shikigami.Server.Security.ProxyNetwork|100%|100%| |Shikigami.Server.VolumeStartupValidator|100%|100%| </details> <details><summary>Shikigami.UseCases - 96.1%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Shikigami.UseCases**|**96.1%**|**94%**| |Shikigami.UseCases.Backups.BackupArtifact|100%|| |Shikigami.UseCases.Backups.BackupFailure|100%|| |Shikigami.UseCases.Backups.BackupJobState|100%|| |Shikigami.UseCases.Backups.BackupPolicy|100%|| |Shikigami.UseCases.Backups.BackupStatusView|100%|100%| |Shikigami.UseCases.Backups.DatabaseSnapshot|100%|| |Shikigami.UseCases.Backups.DownloadDatabaseSnapshot|100%|| |Shikigami.UseCases.Backups.GetBackupStatus|100%|| |Shikigami.UseCases.Backups.IBackupStore|0%|| |Shikigami.UseCases.Backups.RunBackupNow|100%|| |Shikigami.UseCases.DependencyInjection|100%|| |Shikigami.UseCases.Diagnostics.SeedDevData|86.3%|33.3%| |Shikigami.UseCases.Familiars.AvatarImage|100%|| |Shikigami.UseCases.Familiars.ClearFamiliarAvatar|100%|| |Shikigami.UseCases.Familiars.CreateFamiliar|97.2%|70%| |Shikigami.UseCases.Familiars.DuplicateFamiliar|96.7%|91.6%| |Shikigami.UseCases.Familiars.ExpressionView|100%|| |Shikigami.UseCases.Familiars.FamiliarDetail|100%|| |Shikigami.UseCases.Familiars.FamiliarEvent|100%|| |Shikigami.UseCases.Familiars.FamiliarFiles|100%|100%| |Shikigami.UseCases.Familiars.FamiliarLimits|71.4%|| |Shikigami.UseCases.Familiars.FamiliarPersona|96.8%|90%| |Shikigami.UseCases.Familiars.FamiliarSettings|100%|100%| |Shikigami.UseCases.Familiars.FamiliarSummary|100%|100%| |Shikigami.UseCases.Familiars.FamiliarTemplates|100%|100%| |Shikigami.UseCases.Familiars.FamiliarViews|100%|94.4%| |Shikigami.UseCases.Familiars.GetFamiliar|100%|100%| |Shikigami.UseCases.Familiars.ListFamiliars|100%|| |Shikigami.UseCases.Familiars.PersonaFile|100%|| |Shikigami.UseCases.Familiars.PurgeFamiliar|100%|| |Shikigami.UseCases.Familiars.ReadFamiliarAvatar|100%|87.5%| |Shikigami.UseCases.Familiars.SaveFamiliarSettings|94.1%|87.5%| |Shikigami.UseCases.Familiars.SelfRevision|100%|| |Shikigami.UseCases.Familiars.SetFamiliarArchived|100%|100%| |Shikigami.UseCases.Familiars.SetFamiliarAvatar|100%|100%| |Shikigami.UseCases.Familiars.SetFamiliarTrashed|100%|100%| |Shikigami.UseCases.Familiars.ToolGroupCatalog|100%|| |Shikigami.UseCases.Familiars.ToolGroupInfo|100%|| |Shikigami.UseCases.Files.Browser.FileBrowser|92.7%|85.3%| |Shikigami.UseCases.Files.Browser.FileBytes|100%|| |Shikigami.UseCases.Files.Browser.FileItem|100%|| |Shikigami.UseCases.Files.Browser.FileOk`1|100%|| |Shikigami.UseCases.Files.Browser.FileRefusal|100%|| |Shikigami.UseCases.Files.Browser.FileRefused`1|100%|| |Shikigami.UseCases.Files.Browser.FileRevisionView|100%|| |Shikigami.UseCases.Files.Browser.FileView|100%|| |Shikigami.UseCases.Files.Browser.MemoryBudget|100%|| |Shikigami.UseCases.Files.Browser.MemoryBudgetUse|100%|| |Shikigami.UseCases.Files.Browser.MemoryDraft|100%|| |Shikigami.UseCases.Files.Browser.SkillView|100%|| |Shikigami.UseCases.Files.Browser.SpecialForms|98.3%|90.2%| |Shikigami.UseCases.Files.FamiliarWriteLocks|100%|100%| |Shikigami.UseCases.Files.FileAuthors|100%|100%| |Shikigami.UseCases.Files.FileMaintenance|100%|90%| |Shikigami.UseCases.Files.FileMaintenanceResult|100%|| |Shikigami.UseCases.Files.FileSystem|99%|96%| |Shikigami.UseCases.Files.FileWriteRefused|100%|| |Shikigami.UseCases.Files.FileWritten|100%|| |Shikigami.UseCases.Files.FsError|100%|50%| |Shikigami.UseCases.Files.FsResult`1|100%|50%| |Shikigami.UseCases.Files.Mounts.FileEntry|100%|| |Shikigami.UseCases.Files.Mounts.FileRead|100%|| |Shikigami.UseCases.Files.Mounts.GeneratedMount|100%|100%| |Shikigami.UseCases.Files.Mounts.Mount|100%|| |Shikigami.UseCases.Files.Mounts.MountTable|100%|100%| |Shikigami.UseCases.Files.Mounts.StoredMount|100%|100%| |Shikigami.UseCases.Files.SeedDefaultLayout|100%|100%| |Shikigami.UseCases.Files.Special.Budgets|100%|96.6%| |Shikigami.UseCases.Files.Special.FrontMatter|100%|78.5%| |Shikigami.UseCases.Files.Special.HeaderReader|98.2%|84.8%| |Shikigami.UseCases.Files.Special.HeaderValue|100%|100%| |Shikigami.UseCases.Files.Special.HeaderWriter|95.3%|90.7%| |Shikigami.UseCases.Files.Special.MemoryFile|100%|87.5%| |Shikigami.UseCases.Files.Special.MemoryUse|100%|| |Shikigami.UseCases.Files.Special.Numbers|100%|| |Shikigami.UseCases.Files.Special.RoutineFile|100%|99%| |Shikigami.UseCases.Files.Special.SkillFile|100%|94.7%| |Shikigami.UseCases.Files.Special.SpecialFolders|100%|100%| |Shikigami.UseCases.Files.Special.ValidationProblem|100%|| |Shikigami.UseCases.Files.StoredBlob|100%|| |Shikigami.UseCases.Files.Utf8Order|100%|| |Shikigami.UseCases.Notifications.DomainChanged|100%|| |Shikigami.UseCases.Settings.AppearanceColour|100%|100%| |Shikigami.UseCases.Settings.CatalogModel|100%|100%| |Shikigami.UseCases.Settings.ChatAppearance|100%|| |Shikigami.UseCases.Settings.ChatAppearanceJson|100%|100%| |Shikigami.UseCases.Settings.ChatAppearanceLimits|100%|100%| |Shikigami.UseCases.Settings.CheckOpenRouterKey|100%|| |Shikigami.UseCases.Settings.GetChatAppearance|100%|| |Shikigami.UseCases.Settings.GetModelCatalog|100%|100%| |Shikigami.UseCases.Settings.GetModelDefaults|100%|83.3%| |Shikigami.UseCases.Settings.GetProviderSettings|100%|| |Shikigami.UseCases.Settings.ModelCatalog|100%|| |Shikigami.UseCases.Settings.ModelDefaults|100%|100%| |Shikigami.UseCases.Settings.ProviderKeyInfo|100%|| |Shikigami.UseCases.Settings.ProviderKeyState|100%|| |Shikigami.UseCases.Settings.ProviderSettingsView|100%|100%| |Shikigami.UseCases.Settings.RemoveOpenRouterKey|100%|| |Shikigami.UseCases.Settings.SaveChatAppearance|100%|100%| |Shikigami.UseCases.Settings.SaveModelDefaults|100%|100%| |Shikigami.UseCases.Settings.SaveOpenRouterKey|100%|100%| |Shikigami.UseCases.Shell.AllowEveryCommand|100%|| |Shikigami.UseCases.Shell.Commands.Basename|100%|100%| |Shikigami.UseCases.Shell.Commands.Builtin|100%|100%| |Shikigami.UseCases.Shell.Commands.Cat|100%|100%| |Shikigami.UseCases.Shell.Commands.Cd|97.5%|100%| |Shikigami.UseCases.Shell.Commands.CFormat|100%|100%| |Shikigami.UseCases.Shell.Commands.CNumbers|100%|100%| |Shikigami.UseCases.Shell.Commands.CommandContext|97%|92.8%| |Shikigami.UseCases.Shell.Commands.CommandRegistry|100%|100%| |Shikigami.UseCases.Shell.Commands.Cut|100%|100%| |Shikigami.UseCases.Shell.Commands.CutPlan|100%|100%| |Shikigami.UseCases.Shell.Commands.Date|100%|98%| |Shikigami.UseCases.Shell.Commands.Diff|100%|100%| |Shikigami.UseCases.Shell.Commands.Dirname|100%|100%| |Shikigami.UseCases.Shell.Commands.Echo|90.7%|92.3%| |Shikigami.UseCases.Shell.Commands.Escapes|100%|97.4%| |Shikigami.UseCases.Shell.Commands.False|88.8%|| |Shikigami.UseCases.Shell.Commands.FileCommand|100%|100%| |Shikigami.UseCases.Shell.Commands.FileNames|100%|100%| |Shikigami.UseCases.Shell.Commands.Filters|100%|90%| |Shikigami.UseCases.Shell.Commands.Find|100%|97.7%| |Shikigami.UseCases.Shell.Commands.FindExpression|100%|98.7%| |Shikigami.UseCases.Shell.Commands.FindItem|100%|100%| |Shikigami.UseCases.Shell.Commands.FindLine|100%|100%| |Shikigami.UseCases.Shell.Commands.FindNode|100%|100%| |Shikigami.UseCases.Shell.Commands.FindReference|100%|| |Shikigami.UseCases.Shell.Commands.GetOpt|100%|98.2%| |Shikigami.UseCases.Shell.Commands.Grep|99.2%|98.9%| |Shikigami.UseCases.Shell.Commands.Head|100%|100%| |Shikigami.UseCases.Shell.Commands.HelpCommand|94.4%|100%| |Shikigami.UseCases.Shell.Commands.History|97.5%|94%| |Shikigami.UseCases.Shell.Commands.Invocation|100%|50%| |Shikigami.UseCases.Shell.Commands.LinesCommand|97.2%|96.1%| |Shikigami.UseCases.Shell.Commands.LineSearch|100%|100%| |Shikigami.UseCases.Shell.Commands.Ls|97.2%|95.6%| |Shikigami.UseCases.Shell.Commands.Magic|100%|95.9%| |Shikigami.UseCases.Shell.Commands.Nl|100%|99.1%| |Shikigami.UseCases.Shell.Commands.Numbers|100%|100%| |Shikigami.UseCases.Shell.Commands.Operand|100%|| |Shikigami.UseCases.Shell.Commands.OptionSpec|100%|| |Shikigami.UseCases.Shell.Commands.ParsedOptions|100%|| |Shikigami.UseCases.Shell.Commands.Printf|100%|99.5%| |Shikigami.UseCases.Shell.Commands.Pwd|100%|100%| |Shikigami.UseCases.Shell.Commands.Ranges|100%|100%| |Shikigami.UseCases.Shell.Commands.Rg|97.7%|94.7%| |Shikigami.UseCases.Shell.Commands.SearchFiles|90%|83.3%| |Shikigami.UseCases.Shell.Commands.SearchPatterns|100%|100%| |Shikigami.UseCases.Shell.Commands.SearchSettings|100%|| |Shikigami.UseCases.Shell.Commands.Sed|100%|100%| |Shikigami.UseCases.Shell.Commands.SedAddress|100%|| |Shikigami.UseCases.Shell.Commands.SedCommand|100%|| |Shikigami.UseCases.Shell.Commands.SedException|100%|| |Shikigami.UseCases.Shell.Commands.SedInput|100%|| |Shikigami.UseCases.Shell.Commands.SedParser|100%|99.8%| |Shikigami.UseCases.Shell.Commands.SedPart|100%|| |Shikigami.UseCases.Shell.Commands.SedProgram|100%|| |Shikigami.UseCases.Shell.Commands.SedRegex|100%|| |Shikigami.UseCases.Shell.Commands.SedRun|100%|100%| |Shikigami.UseCases.Shell.Commands.SedSubstitution|100%|| |Shikigami.UseCases.Shell.Commands.ShellCommand|100%|100%| |Shikigami.UseCases.Shell.Commands.ShellQuote|100%|100%| |Shikigami.UseCases.Shell.Commands.Sizes|100%|100%| |Shikigami.UseCases.Shell.Commands.Sort|100%|94.1%| |Shikigami.UseCases.Shell.Commands.SortKey|100%|100%| |Shikigami.UseCases.Shell.Commands.SortOrder|99.5%|99.5%| |Shikigami.UseCases.Shell.Commands.Stat|100%|90.9%| |Shikigami.UseCases.Shell.Commands.StatFacts|100%|100%| |Shikigami.UseCases.Shell.Commands.StatFormat|100%|99.5%| |Shikigami.UseCases.Shell.Commands.Tail|100%|100%| |Shikigami.UseCases.Shell.Commands.TextFile|100%|| |Shikigami.UseCases.Shell.Commands.Tr|100%|100%| |Shikigami.UseCases.Shell.Commands.TreeCommand|100%|99.2%| |Shikigami.UseCases.Shell.Commands.TrPlan|100%|100%| |Shikigami.UseCases.Shell.Commands.TrSequence|93.9%|80%| |Shikigami.UseCases.Shell.Commands.TrSet|100%|97.2%| |Shikigami.UseCases.Shell.Commands.True|88.8%|| |Shikigami.UseCases.Shell.Commands.Uniq|100%|100%| |Shikigami.UseCases.Shell.Commands.VersionOrder|100%|96.6%| |Shikigami.UseCases.Shell.Commands.Wc|100%|97.3%| |Shikigami.UseCases.Shell.Execution.CaptureSink|100%|100%| |Shikigami.UseCases.Shell.Execution.ClosedSink|100%|| |Shikigami.UseCases.Shell.Execution.ClosedStreamException|100%|| |Shikigami.UseCases.Shell.Execution.CodePointOrder|100%|100%| |Shikigami.UseCases.Shell.Execution.DateInput|96.8%|94.3%| |Shikigami.UseCases.Shell.Execution.Errno|100%|100%| |Shikigami.UseCases.Shell.Execution.Executor|98.1%|95.7%| |Shikigami.UseCases.Shell.Execution.Expander|97.3%|95.1%| |Shikigami.UseCases.Shell.Execution.Glob|94.6%|95.9%| |Shikigami.UseCases.Shell.Execution.GnuQuote|91.2%|92.8%| |Shikigami.UseCases.Shell.Execution.InputSource|100%|| |Shikigami.UseCases.Shell.Execution.LineChange|100%|| |Shikigami.UseCases.Shell.Execution.LineDiff|98.8%|98.1%| |Shikigami.UseCases.Shell.Execution.LongDouble|100%|98.7%| |Shikigami.UseCases.Shell.Execution.NullSink|100%|| |Shikigami.UseCases.Shell.Execution.OutputLimit|95.8%|94.7%| |Shikigami.UseCases.Shell.Execution.PathResolver|100%|97%| |Shikigami.UseCases.Shell.Execution.PipeSink|100%|100%| |Shikigami.UseCases.Shell.Execution.PosixRegex|89.2%|90.7%| |Shikigami.UseCases.Shell.Execution.PosixRegexException|100%|| |Shikigami.UseCases.Shell.Execution.ResolvedPath|100%|| |Shikigami.UseCases.Shell.Execution.ShellLimitException|100%|| |Shikigami.UseCases.Shell.Execution.ShellScope|94.7%|83.3%| |Shikigami.UseCases.Shell.Execution.ShellTree|97.5%|91.3%| |Shikigami.UseCases.Shell.Execution.Strftime|95.6%|92.3%| |Shikigami.UseCases.Shell.Execution.Terminal|100%|100%| |Shikigami.UseCases.Shell.Execution.TextLine|50%|0%| |Shikigami.UseCases.Shell.Execution.TextLines|100%|100%| |Shikigami.UseCases.Shell.Execution.TreeWalker|100%|100%| |Shikigami.UseCases.Shell.Execution.Walked|100%|| |Shikigami.UseCases.Shell.Help.CommandHints|100%|100%| |Shikigami.UseCases.Shell.Help.MountGuide|100%|| |Shikigami.UseCases.Shell.Help.ShellHelp|100%|100%| |Shikigami.UseCases.Shell.ShellCommandPlan|100%|| |Shikigami.UseCases.Shell.ShellCommandRecord|100%|| |Shikigami.UseCases.Shell.ShellEffects|100%|| |Shikigami.UseCases.Shell.ShellInterpreter|100%|100%| |Shikigami.UseCases.Shell.ShellLimits|100%|| |Shikigami.UseCases.Shell.ShellRead|100%|| |Shikigami.UseCases.Shell.ShellResult|75%|| |Shikigami.UseCases.Shell.ShellSession|100%|100%| |Shikigami.UseCases.Shell.Syntax.AndOrList|100%|| |Shikigami.UseCases.Shell.Syntax.Assignment|100%|| |Shikigami.UseCases.Shell.Syntax.ByteText|100%|88.8%| |Shikigami.UseCases.Shell.Syntax.HereDocBody|100%|| |Shikigami.UseCases.Shell.Syntax.Lexer|93.5%|89.8%| |Shikigami.UseCases.Shell.Syntax.LiteralPart|100%|| |Shikigami.UseCases.Shell.Syntax.ParameterPart|100%|| |Shikigami.UseCases.Shell.Syntax.Parser|96.9%|90.1%| |Shikigami.UseCases.Shell.Syntax.Pipeline|100%|| |Shikigami.UseCases.Shell.Syntax.Redirection|100%|| |Shikigami.UseCases.Shell.Syntax.Script|100%|| |Shikigami.UseCases.Shell.Syntax.ShellSyntaxException|100%|| |Shikigami.UseCases.Shell.Syntax.SimpleCommand|100%|| |Shikigami.UseCases.Shell.Syntax.TildePart|100%|100%| |Shikigami.UseCases.Shell.Syntax.Token|77.7%|66.6%| |Shikigami.UseCases.Shell.Syntax.Word|100%|83.3%| |Shikigami.UseCases.Shell.Syntax.WordBuilder|100%|100%| |System.Text.RegularExpressions.Generated|81.1%|72%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__AssignmentHead_10|95.8%|95.4%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__BraceExpansion_9|93.4%|85.4%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__HexColour_4|97.4%|96.4%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Interval_1|83.6%|75%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__IntervalBody_8|91.6%|86.1%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NameRule_3|92.1%|84.3%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__NewerXY_6|88.5%|62.5%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Number_5|67.3%|62.7%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__OldCount_7|94.8%|83.3%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__TimeOfDay_0|70.9%|58.3%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>FE4D9BB856E7A048<br/>F24B88780DF6A41103E39D76537F056A9F694C6955C8C8CF6__Window_2|62.8%|48.3%| </details>
Member

🔮 fufu~ Jibril reviewed your code!

Back so soon~? The delta is exactly what you promised and nothing else: the DefaultsSection guard, its two tests, and the Kagaku.UI repin. A re-review this clean is almost disappointing — I brought three knives and every one of them came back bloody. ♡

Verdict: ✅ Looks good to me~

CI is green on this head — build, image and test all pass for 01369a5, which doubles as the re-run of the stalled Tree_with_full_paths… job from round 1. That ⚠️ is closed; it was a runner stall, just as it looked.

On my little idea #1 — I was wrong, and you were right. Your five-step path (section opens while a save is out → OnLoad finds no Error to reset → the read queues behind the save → the save fails → the read lands on a fresh, never-synced section) is exactly real. I know because I mutated it:

🔪 Mutation probes — 3 run, 0 survived

  1. DefaultsSection, whole (Save == Error && _synced is not null) conjunct removed → killed by A_later_pick_whose_save_fails_after_an_earlier_one_landed_stays_shown (the select falls back to "Model default" instead of "High").
  2. DefaultsSection, only && _synced is not null removed (the half-mutant) → killed by A_section_opened_while_a_save_is_out_that_then_fails_shows_what_is_stored — the fresh section stays stuck on the built-in look until the assertion times out.
  3. ChatAppearanceSection, && _synced is not null removed (the conjunct I doubted in round 1) → killed in 1 s by its identically-named test in ChatAppearanceSectionTests. Unreachable, hm? Fufu~ the check you couldn't reach was a different one — and this one bites.

Both arms of the condition are pinned separately. Most authors only prove the whole guard; you proved each half. Oh? Oh! This is wonderful~

✅ What I liked~

  • The two sections now tell the same story, word for word: SyncFormFromState and SyncFromState carry the identical guard shape with the identical comment intent, each pinned by an identically-named test pair. Taking the fix in-PR instead of a follow-up was the right call — it was the same bug.
  • DisposeComponentsAsync + re-Render as the way to manufacture _synced is null over a shared store — the precise state that distinguishes the two arms. Surgical.
  • Test 1 also asserts store.Values never gained DefaultEffort — the failed write is proven not just shown as failed.

Merge order stands, unchanged as you said: this branch pins Kagaku.UI 7e59270, the head of #42 after its own review round. Merge #42 first, then repin onto its squashed main commit here.

♪ Three probes, three kills, green CI, one satisfied Flugel. Come back when the chats in 2e put those accents on real messages — I'll be waiting~


Automated review by Jibril · 2026-10-18
CI: green for head SHA 01369a5 · Mutation probes: 3 run, 0 survived (DefaultsSection whole-guard + half-guard; ChatAppearanceSection _synced conjunct — all killed by their named tests) · Local suite: skipped (CI green); targeted baseline 4/4 green

## 🔮 fufu~ Jibril reviewed your code! Back so soon~? The delta is exactly what you promised and *nothing else*: the DefaultsSection guard, its two tests, and the Kagaku.UI repin. A re-review this clean is almost disappointing — I brought three knives and every one of them came back bloody. ♡ ### Verdict: ✅ Looks good to me~ **CI is green on this head** — `build`, `image` and `test` all pass for `01369a5`, which doubles as the re-run of the stalled `Tree_with_full_paths…` job from round 1. That ⚠️ is closed; it was a runner stall, just as it looked. **On my little idea #1 — I was wrong, and you were right.** Your five-step path (section opens while a save is out → `OnLoad` finds no `Error` to reset → the read queues behind the save → the save fails → the read lands on a fresh, never-synced section) is exactly real. I know because I mutated it: #### 🔪 Mutation probes — 3 run, 0 survived 1. **DefaultsSection, whole `(Save == Error && _synced is not null)` conjunct removed** → killed by `A_later_pick_whose_save_fails_after_an_earlier_one_landed_stays_shown` (the select falls back to "Model default" instead of "High"). 2. **DefaultsSection, only `&& _synced is not null` removed** (the half-mutant) → killed by `A_section_opened_while_a_save_is_out_that_then_fails_shows_what_is_stored` — the fresh section stays stuck on the built-in look until the assertion times out. 3. **ChatAppearanceSection, `&& _synced is not null` removed** (the conjunct I doubted in round 1) → killed in 1 s by its identically-named test in `ChatAppearanceSectionTests`. Unreachable, hm? Fufu~ the check you couldn't reach was a different one — and this one bites. Both arms of the condition are pinned *separately*. Most authors only prove the whole guard; you proved each half. Oh? Oh! This is wonderful~ #### ✅ What I liked~ - **The two sections now tell the same story, word for word**: `SyncFormFromState` and `SyncFromState` carry the identical guard shape with the identical comment intent, each pinned by an identically-named test pair. Taking the fix in-PR instead of a follow-up was the right call — it *was* the same bug. - **`DisposeComponentsAsync` + re-`Render`** as the way to manufacture `_synced is null` over a shared store — the precise state that distinguishes the two arms. Surgical. - Test 1 also asserts `store.Values` never gained `DefaultEffort` — the failed write is proven not just *shown* as failed. **Merge order stands, unchanged as you said:** this branch pins Kagaku.UI `7e59270`, the head of #42 after its own review round. Merge #42 first, then repin onto its squashed main commit here. *♪ Three probes, three kills, green CI, one satisfied Flugel. Come back when the chats in 2e put those accents on real messages — I'll be waiting~* --- *Automated review by Jibril · 2026-10-18* *CI: green for head SHA 01369a5 · Mutation probes: 3 run, 0 survived (DefaultsSection whole-guard + half-guard; ChatAppearanceSection `_synced` conjunct — all killed by their named tests) · Local suite: skipped (CI green); targeted baseline 4/4 green*
bjoern merged commit 02c3e7e918 into main 2026-10-18 23:00:43 +02:00
bjoern deleted branch feat/p1e-appearance 2026-10-18 23:00:44 +02:00
bjoern referenced this pull request from a commit 2026-10-18 23:00:45 +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/Shikigami!21
No description provided.