feat(shell): show the MinVer build version in the app header #6

Merged
bjoern merged 1 commit from feat/header-build-version into main 2026-09-18 19:40:53 +02:00
Member

Port of Kagura PR 260 — the MinVer build version now shows in the app header, between the spacer and the settings menu.

What

  • AppHeader.razor: a <span class="app-header__version"> reading the AssemblyInformationalVersion MinVer stamps at build time. Short commit id visible (0.0.0-dev.0.310+59d3038), full string in the tooltip. Read once into static readonlys; the running build never changes.
  • AppHeader.razor.css: quiet chrome — muted, monospace, text-sm, nowrap. Same tokens as Kagura.
  • AppChromeTests.cs: new fact The_header_shows_the_build_version_with_the_full_sha_in_its_tooltip — reads the attribute the same way the component does (no fixture value that could drift), pins the encoded tooltip, the class+title pairing, and the 7-char commit split.

Verified

  • Build: 0 warnings, 0 errors (warnings-as-errors on)
  • AppChromeTests: 8/8 (new fact included)
  • Full integration suite: 23/23; Domain 40/40, UseCases 1/1, BlazorAdapter 15/15
  • MinVer plumbing (Directory.Build.props → tags/Docker APP_VERSION) already in place from the skeleton — unchanged
Port of Kagura PR 260 — the MinVer build version now shows in the app header, between the spacer and the settings menu. ## What - `AppHeader.razor`: a `<span class="app-header__version">` reading the `AssemblyInformationalVersion` MinVer stamps at build time. Short commit id visible (`0.0.0-dev.0.310+59d3038`), full string in the tooltip. Read once into static readonlys; the running build never changes. - `AppHeader.razor.css`: quiet chrome — muted, monospace, `text-sm`, `nowrap`. Same tokens as Kagura. - `AppChromeTests.cs`: new fact `The_header_shows_the_build_version_with_the_full_sha_in_its_tooltip` — reads the attribute the same way the component does (no fixture value that could drift), pins the encoded tooltip, the class+title pairing, and the 7-char commit split. ## Verified - Build: 0 warnings, 0 errors (warnings-as-errors on) - `AppChromeTests`: 8/8 (new fact included) - Full integration suite: 23/23; Domain 40/40, UseCases 1/1, BlazorAdapter 15/15 - MinVer plumbing (`Directory.Build.props` → tags/Docker `APP_VERSION`) already in place from the skeleton — unchanged
feat(shell): show the MinVer build version in the app header
All checks were successful
CI / build (pull_request) Successful in 27s
CI / test (pull_request) Successful in 33s
b1636eb0de
Port of Kagura PR 260: a quiet span between the spacer and the settings
menu reading the MinVer-stamped AssemblyInformationalVersion — short
commit id visible, full string in the tooltip. Pinned by a new
AppChromeTests fact that reads the attribute the same way the component
does.

🔄 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: b1636eb · Generated: 2026-09-18 17:33:20 UTC · Revision: #1

Summary

Summary
Generated on: 09/18/2026 - 17:33:20
Coverage date: 09/18/2026 - 17:33:15 - 09/18/2026 - 17:33:18
Parser: MultiReport (4x Cobertura)
Assemblies: 6
Classes: 35
Files: 32
Line coverage: 91% (602 of 661)
Covered lines: 602
Uncovered lines: 59
Coverable lines: 661
Total lines: 1931
Branch coverage: 77.5% (138 of 178)
Covered branches: 138
Total branches: 178
Method coverage: Feature is only available for sponsors

Coverage

Tsumugi.BlazorAdapter - 74.4%
Name Line Branch
Tsumugi.BlazorAdapter 74.4% 64.2%
Tsumugi.BlazorAdapter.BlazorAdapterAssembly 100%
Tsumugi.BlazorAdapter.Graphs.GraphCanvas 37.5% 25%
Tsumugi.BlazorAdapter.Graphs.GraphPlaygroundPage 20% 25%
Tsumugi.BlazorAdapter.Notifications.DomainChangedBridge 94.4% 83.3%
Tsumugi.BlazorAdapter.Notifications.DomainChangesReceived 50% 0%
Tsumugi.BlazorAdapter.Runs.RunChangedBridge 97.1% 90.6%
Tsumugi.BlazorAdapter.Runs.RunChangesReceived 100%
Tsumugi.BlazorAdapter.Runs.RunTextReceived 100%
Tsumugi.Domain - 96%
Name Line Branch
Tsumugi.Domain 96% 100%
Tsumugi.Domain.Documents.Document 96.2% 100%
Tsumugi.Domain.Documents.DocumentCategory 95.2%
Tsumugi.Domain.Documents.DocumentPlacement 100% 100%
Tsumugi.Domain.Stories.Chapter 93.9% 100%
Tsumugi.Domain.Stories.Provenance 100% 100%
Tsumugi.Domain.Stories.Segment 95.7% 100%
Tsumugi.Domain.Stories.Story 95.7% 100%
Tsumugi.Domain.Text 100% 100%
Tsumugi.Infrastructure - 93.2%
Name Line Branch
Tsumugi.Infrastructure 93.2% 75%
Tsumugi.Infrastructure.DependencyInjection 100%
Tsumugi.Infrastructure.Notifications.InProcessDomainChangedBus 100% 100%
Tsumugi.Infrastructure.Persistence.SqlitePragmaInterceptor 55.5% 0%
Tsumugi.Infrastructure.Persistence.TsumugiDbContext 100%
Tsumugi.Infrastructure.Runs.InProcessRunEventBus 100% 100%
Tsumugi.Kernel - 90.9%
Name Line Branch
Tsumugi.Kernel 90.9% 75%
Tsumugi.Kernel.Err`1 100%
Tsumugi.Kernel.Ok`1 100%
Tsumugi.Kernel.Result`1 88.8% 75%
Tsumugi.Server - 100%
Name Line Branch
Tsumugi.Server 100% 75%
Program 100% 85.7%
Tsumugi.Server.Components.App 100%
Tsumugi.Server.Components.Layout.AppHeader 100% 50%
Tsumugi.Server.Components.Layout.MainLayout 100%
Tsumugi.Server.Components.Pages.Gate 100% 100%
Tsumugi.Server.Security.AccessGate 100% 66.6%
Tsumugi.Server.Security.AccessSecret 100% 50%
Tsumugi.Server.VolumeStartupValidator 100% 100%
Tsumugi.UseCases - 100%
Name Line Branch
Tsumugi.UseCases 100% ****
Tsumugi.UseCases.DependencyInjection 100%
Tsumugi.UseCases.Notifications.DomainChanged 100%
Tsumugi.UseCases.Runs.RunEvent 100%
<!-- 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:** `b1636eb` · **Generated:** 2026-09-18 17:33:20 UTC · **Revision:** #1 # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 09/18/2026 - 17:33:20 | | Coverage date: | 09/18/2026 - 17:33:15 - 09/18/2026 - 17:33:18 | | Parser: | MultiReport (4x Cobertura) | | Assemblies: | 6 | | Classes: | 35 | | Files: | 32 | | **Line coverage:** | 91% (602 of 661) | | Covered lines: | 602 | | Uncovered lines: | 59 | | Coverable lines: | 661 | | Total lines: | 1931 | | **Branch coverage:** | 77.5% (138 of 178) | | Covered branches: | 138 | | Total branches: | 178 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Tsumugi.BlazorAdapter - 74.4%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.BlazorAdapter**|**74.4%**|**64.2%**| |Tsumugi.BlazorAdapter.BlazorAdapterAssembly|100%|| |Tsumugi.BlazorAdapter.Graphs.GraphCanvas|37.5%|25%| |Tsumugi.BlazorAdapter.Graphs.GraphPlaygroundPage|20%|25%| |Tsumugi.BlazorAdapter.Notifications.DomainChangedBridge|94.4%|83.3%| |Tsumugi.BlazorAdapter.Notifications.DomainChangesReceived|50%|0%| |Tsumugi.BlazorAdapter.Runs.RunChangedBridge|97.1%|90.6%| |Tsumugi.BlazorAdapter.Runs.RunChangesReceived|100%|| |Tsumugi.BlazorAdapter.Runs.RunTextReceived|100%|| </details> <details><summary>Tsumugi.Domain - 96%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Domain**|**96%**|**100%**| |Tsumugi.Domain.Documents.Document|96.2%|100%| |Tsumugi.Domain.Documents.DocumentCategory|95.2%|| |Tsumugi.Domain.Documents.DocumentPlacement|100%|100%| |Tsumugi.Domain.Stories.Chapter|93.9%|100%| |Tsumugi.Domain.Stories.Provenance|100%|100%| |Tsumugi.Domain.Stories.Segment|95.7%|100%| |Tsumugi.Domain.Stories.Story|95.7%|100%| |Tsumugi.Domain.Text|100%|100%| </details> <details><summary>Tsumugi.Infrastructure - 93.2%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Infrastructure**|**93.2%**|**75%**| |Tsumugi.Infrastructure.DependencyInjection|100%|| |Tsumugi.Infrastructure.Notifications.InProcessDomainChangedBus|100%|100%| |Tsumugi.Infrastructure.Persistence.SqlitePragmaInterceptor|55.5%|0%| |Tsumugi.Infrastructure.Persistence.TsumugiDbContext|100%|| |Tsumugi.Infrastructure.Runs.InProcessRunEventBus|100%|100%| </details> <details><summary>Tsumugi.Kernel - 90.9%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Kernel**|**90.9%**|**75%**| |Tsumugi.Kernel.Err`1|100%|| |Tsumugi.Kernel.Ok`1|100%|| |Tsumugi.Kernel.Result`1|88.8%|75%| </details> <details><summary>Tsumugi.Server - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Server**|**100%**|**75%**| |Program|100%|85.7%| |Tsumugi.Server.Components.App|100%|| |Tsumugi.Server.Components.Layout.AppHeader|100%|50%| |Tsumugi.Server.Components.Layout.MainLayout|100%|| |Tsumugi.Server.Components.Pages.Gate|100%|100%| |Tsumugi.Server.Security.AccessGate|100%|66.6%| |Tsumugi.Server.Security.AccessSecret|100%|50%| |Tsumugi.Server.VolumeStartupValidator|100%|100%| </details> <details><summary>Tsumugi.UseCases - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.UseCases**|**100%**|****| |Tsumugi.UseCases.DependencyInjection|100%|| |Tsumugi.UseCases.Notifications.DomainChanged|100%|| |Tsumugi.UseCases.Runs.RunEvent|100%|| </details>
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! A port of Kagura #260, wearing brand-new Tsumugi clothes~ ♪ I diffed your three files against the Kagura sibling line by line, and it's a faithful little twin — same static-readonly read, same + split, same quiet monospace chrome, same self-reading test. Ports this disciplined make my wings flutter~

Verdict: ✅ Looks good to me~

✅ What I liked~

  • The test reads the attribute the way the component does (typeof(Program).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()) instead of a fixture value — the pin can't drift from what production renders. That's the right kind of lazy, fufu~
  • And it has real teeth — I checked. Mutation probes on the component, all red on exactly the new fact: tooltip carrying the short version instead of the full one → red; the 7-char commit shortening dropped → red; the whole span deleted → red. Not a tautology in sight~ ♡
  • Encoding awareness: the test encodes its expectations with HtmlEncoder.Default (so + → &#x2B;) rather than assuming raw markup — matches how Razor actually emits attribute values and text. The other tests in this file already knew that trick (image/svg+xml icon pin); consistency~
  • Sibling parity is exact: markup order (spacer → version → settings menu), CSS rule, and comment intent all mirror Kagura's approved form — with the ADR reference correctly remapped 0015 → 0001 (Tsumugi's skeleton ADR). No cargo-cult citations on my watch~
  • The Split('+') is [var tag, var commit, ..] split is semantically safe: semver build metadata can't contain +, so first-split is always the right split; the .. rest and the ?? "unknown" are honest defensive fallbacks, same shape as the sibling. Coverage agrees: AppHeader 100% line coverage (the 50% branch is exactly those two static-init fallback arms — unreachable without assembly-swap tricks, identical to Kagura; not worth contorting tests for).
  • All three CSS tokens exist in the vendored Kagaku.UI design system (--font-mono at kagaku-ui.css:78; --text-muted/--text-sm already in use in this very file). No magic values, no new tokens invented.
  • Surgical scope: +58/−0 across exactly 3 files, MinVer plumbing untouched as the PR body claims.

Every "Verified" claim in the PR body held up under my local run: build 0 warnings/0 errors with warnings-as-errors on, AppChromeTests 8/8.

Fufu~ merge it before I change my mind~ ♡


Automated review by Jibril · 2026-09-18
CI/CD: passed for head SHA b1636eb (build + test, coverage comment 8078: AppHeader 100% lines) · Local checks: build + AppChromeTests 8/8 + 3/3 mutation probes red (full suite skipped, CI green)

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! A port of Kagura #260, wearing brand-new Tsumugi clothes~ ♪ I diffed your three files against the Kagura sibling line by line, and it's a faithful little twin — same static-readonly read, same `+` split, same quiet monospace chrome, same self-reading test. Ports this disciplined make my wings flutter~ ### Verdict: ✅ Looks good to me~ #### ✅ What I liked~ - **The test reads the attribute the way the component does** (`typeof(Program).Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()`) instead of a fixture value — the pin can't drift from what production renders. That's the *right* kind of lazy, fufu~ - **And it has real teeth — I checked.** Mutation probes on the component, all red on exactly the new fact: tooltip carrying the short version instead of the full one → red; the 7-char commit shortening dropped → red; the whole span deleted → red. Not a tautology in sight~ ♡ - **Encoding awareness**: the test encodes its expectations with `HtmlEncoder.Default` (so `+` → `&#x2B;`) rather than assuming raw markup — matches how Razor actually emits attribute values and text. The other tests in this file already knew that trick (`image/svg+xml` icon pin); consistency~ - **Sibling parity is exact**: markup order (spacer → version → settings menu), CSS rule, and comment intent all mirror Kagura's approved form — with the ADR reference correctly remapped 0015 → 0001 (Tsumugi's skeleton ADR). No cargo-cult citations on my watch~ - **The `Split('+') is [var tag, var commit, ..]` split is semantically safe**: semver build metadata can't contain `+`, so first-split is always the right split; the `..` rest and the `?? "unknown"` are honest defensive fallbacks, same shape as the sibling. Coverage agrees: AppHeader 100% line coverage (the 50% branch is exactly those two static-init fallback arms — unreachable without assembly-swap tricks, identical to Kagura; not worth contorting tests for). - **All three CSS tokens exist** in the vendored Kagaku.UI design system (`--font-mono` at kagaku-ui.css:78; `--text-muted`/`--text-sm` already in use in this very file). No magic values, no new tokens invented. - **Surgical scope**: +58/−0 across exactly 3 files, MinVer plumbing untouched as the PR body claims. Every "Verified" claim in the PR body held up under my local run: build 0 warnings/0 errors with warnings-as-errors on, AppChromeTests 8/8. Fufu~ merge it before I change my mind~ ♡ --- *Automated review by Jibril · 2026-09-18* *CI/CD: passed for head SHA b1636eb (build + test, coverage comment 8078: AppHeader 100% lines) · Local checks: build + AppChromeTests 8/8 + 3/3 mutation probes red (full suite skipped, CI green)*
bjoern merged commit 864558e598 into main 2026-09-18 19:40:53 +02:00
bjoern deleted branch feat/header-build-version 2026-09-18 19:40:53 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
TeamAI/Tsumugi!6
No description provided.