Skip to content

fix(theme): make msn-shared.css canonical here and gate the copies by hash - #72

Merged
krisarmstrong merged 1 commit into
mainfrom
fix/ui-fleet-1-canonical-theme
Sep 16, 2026
Merged

krisarmstrong merged 1 commit into
mainfrom
fix/ui-fleet-1-canonical-theme

Conversation

@krisarmstrong

@krisarmstrong krisarmstrong commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Summary

ui/src/theme/msn-shared.css had drifted into three different files across
the four UI repos with every repo green throughout: seed and niac-go
byte-identical, stem carrying its own darker success green, trellis
carrying an extra typography block. A per-repo check cannot see a fleet-wide
divergence — which is how all four shipped a light-mode
--color-surface-border at 1.45:1, against WCAG 1.4.11's 3:1 for a UI
edge.

This makes the file canonical here and gates the copies by sha256:

  • ui/theme/msn-shared.css is the one copy. Light
    --color-surface-border #d9d2bd#8e7f52 and --color-status-success
    #2f7d4f#2a7146 (the value stem had already reached on its own).
  • The .dark block is the approved 2026-09-15 dark-palette proposal
    verbatim
    — dark is now the night version of the warm light theme
    (hue 43–51°) instead of the cold-steel palette that shared only the status
    hues. --color-accent-gold joins the shared file (it was the same value in
    all four product-*.css), so the dark lift is one decision; .kicker-accent
    consumes it.
  • ci-conformance check 9 compares each repo's copy by sha256. A repo with
    no ui/src is out of scope; a missing copy in a UI repo is a finding.
  • The set C product hues are published in ui/theme/README.md. They stay
    in each repo's product-<name>.css — decision D6 (no shared TS package)
    stands, and the brand anchor is the one thing the products do not share.

Two scope notes, both deliberate:

  • trellis's extra .heading-1 / .body-small / .gap-* block is not in
    the canonical file. The siblings define those in their own index.css, so
    adopting the block here would duplicate three existing definitions. UI-TRL-8
    moves trellis's copy into its index.css instead.
  • --color-text-disabled stays at 3.0:1. It is out of this row's acceptance
    and raising it would erase the disabled affordance; the sites that use it for
    real text are the adoption rows' problem, not the token's.

The four adoption PRs are separate rows (UI-SEED-7, UI-STEM-7, UI-NIAC-9,
UI-TRL-8), so the check fails all four repos until those land — see Risk.

Linked Issue

Fixes #69

Type of Change

Bug fix (accessibility) plus a new fleet gate. No product code.

Risk

Medium, and deliberately visible. The moment this merges, ci-conformance
fails in all four product repos, because none of them carries the canonical
file yet. That is the gate doing its job — the adoption rows (UI-SEED-7,
UI-STEM-7, UI-NIAC-9, UI-TRL-8) are queued behind it and each is a verbatim
copy. Verified, not assumed: all four repos pin this workflow at a SHA
(ci-conformance.yml@048d173… in seed/stem/trellis, @1920efa… in niac-go),
so a repo only sees the new check when it bumps that pin — the same change as
its adoption PR. Nothing goes red on merge.

Two consequences to expect rather than triage:

  • Renovate will raise a ci-conformance.yml digest bump in each repo. That PR
    is born red until the repo's adoption row lands, so it is not a clean bot
    PR to arm under rule 9b — land it with the adoption change.
  • ci-conformance-schedule.yml runs the same script against all four repos
    from .github HEAD, so its next daily tick reports four theme findings on
    the existing tracking issue until adoption. Correct, and expected.

The colour changes are confined to two light tokens and the .dark block. The
light border is visibly darker than #d9d2bd; that is the WCAG fix, not a
regression.

Testing Evidence

RED first — the three new cases fail with the check stubbed out:

$ python3 scripts/test-check-ci-conformance.py   # shared_theme() stubbed to return []
FAIL: test_comment_only_theme_drift_is_rejected
FAIL: test_drifted_theme_copy_is_rejected
FAIL: test_missing_theme_in_a_ui_repo_is_rejected
Ran 16 tests in 2.910s
FAILED (failures=3)

GREEN with the check in place (the full suite, i18n tests and compileall — the
three steps this repo's python job runs):

$ python3 scripts/i18n/test-check-keys.py && python3 scripts/i18n/test-es-fill.py
i18n keys OK
es-fill OK

$ python3 scripts/test-check-ci-conformance.py
test_backend_only_repo_is_out_of_scope ... ok
test_comment_only_theme_drift_is_rejected ... ok
test_drifted_theme_copy_is_rejected ... ok
test_identical_theme_copy_passes ... ok
test_missing_theme_in_a_ui_repo_is_rejected ... ok
----------------------------------------------------------------------
Ran 16 tests in 3.180s

OK

$ python3 -m compileall -q scripts/
compileall OK

The check run against the four real repos at their current origin/main — all
four differ, as expected until adoption:

$ for r in seed stem niac-go trellis; do (cd ~/Developer/MustardSeedNetworks/$r && \
    python3 .../scripts/check-ci-conformance.py | grep msn-shared); done
seed      ::error::ui/src/theme/msn-shared.css has drifted from the canonical theme
stem      ::error::ui/src/theme/msn-shared.css has drifted from the canonical theme
niac-go   ::error::ui/src/theme/msn-shared.css has drifted from the canonical theme
trellis   ::error::ui/src/theme/msn-shared.css has drifted from the canonical theme
          expected: sha256 b073e5e15bab (MustardSeedNetworks/.github ui/theme/msn-shared.css)

Contrast, measured with a WCAG relative-luminance script, not eyeballed:

=== acceptance: light border >= 3:1 ===
  border #8e7f52 on base   #fbfaf5: 3.79 PASS
  border #8e7f52 on raised #ffffff: 3.96 PASS
  border #8e7f52 on hover  #f3efe2: 3.44 PASS
  border #8e7f52 on sunken #e9e3ce: 3.08 PASS
  border #8e7f52 on deep   #efe9d8: 3.26 PASS
  (was #d9d2bd: 1.45 on base, 1.51 on raised)

=== acceptance: light success >= 4.5:1 ===
  success #2a7146 on pill wash   #eaf2ed: 5.19 PASS
  success #2a7146 on running row #e8efe9: 5.06 PASS
  success #2a7146 on raised      #ffffff: 5.92 PASS
  (was #2f7d4f: 4.42 and 4.31 — both failing)

=== dark block vs the approved table (on raised #23211a) ===
  text-primary   #f3efe2: 14.00  text-secondary #b5ac8c: 7.09
  text-muted     #91896e:  4.61  border         #746d58: 3.12 (3.50 on base)
  success        #3cb46e:  6.09  warning        #ca9721: 6.10
  error          #de8787:  6.08  info           #5da5e5: 6.12
  accent-gold    #b88a1e:  5.13  log-fatal      #f15050: 4.60
  every value matches the approved "Dark proposed" column

Markdown gate on the files this PR changes:

$ npx --yes markdownlint-cli2@0.23.2 ui/theme/README.md
Summary: 0 issues in 0 files

README.md's MD013 findings are pre-existing on origin/main (long table
rows) and this repo runs no markdownlint gate; the new file is clean.

Security and Release Checklist

  • No secrets, credentials or tokens added.
  • No workflow permissions changed; no new uses: or unpinned tool install.
  • No product code, no authz or crypto touched — colour tokens and one
    read-only conformance check.
  • The new check fails closed: a UI repo with a missing or differing copy is
    a finding, and a canonical edit that is not re-copied fails too.
  • Not a release; .github is not versioned by release-please.

… hash

The four UI repos each kept a copy of the shared colour tokens and they had
drifted into three different files with every repo green: seed and niac-go
identical, stem carrying its own darker success green, trellis carrying an
extra typography block. A per-repo check cannot see a fleet-wide divergence,
which is how all four shipped a light-mode --color-surface-border at 1.45:1
against WCAG 1.4.11's 3:1 for a UI edge.

- ui/theme/msn-shared.css is now the one copy. Light --color-surface-border
  #d9d2bd -> #8e7f52 (3.08-3.96:1 on every light surface) and
  --color-status-success #2f7d4f -> #2a7146 (5.06:1 on the running-row wash
  status pills sit on), which is the value stem had already reached alone.
- The .dark block is the approved 2026-09-15 dark-palette proposal verbatim:
  dark is now the night version of the warm light theme (hue 43-51 deg)
  rather than the cold-steel palette that shared only the status hues.
- ci-conformance compares each repo's ui/src/theme/msn-shared.css to it by
  sha256; a repo with no ui/src is out of scope.
- The set C product hues are published in ui/theme/README.md. They stay in
  each repo's product-<name>.css: decision D6 stands.

The four adoption PRs are separate rows (UI-SEED-7, UI-STEM-7, UI-NIAC-9,
UI-TRL-8), so the check fails all four repos until they land.

Fixes #69
@krisarmstrong
krisarmstrong force-pushed the fix/ui-fleet-1-canonical-theme branch from b039670 to 74a80b2 Compare September 16, 2026 13:01
@krisarmstrong
krisarmstrong enabled auto-merge (squash) September 16, 2026 13:02
@krisarmstrong
krisarmstrong merged commit 75ad8d1 into main Sep 16, 2026
4 checks passed
krisarmstrong pushed a commit to MustardSeedNetworks/seed that referenced this pull request Sep 16, 2026
MustardSeedNetworks/.github#72 made ui/theme/msn-shared.css canonical and
gated the product copies by sha256 at 13:03Z today, so every seed PR is
red on ci-conformance until the copy is refreshed. This is the file
verbatim (sha256 b073e5e15bab): the WCAG fixes to the light border and
success green, and the warm dark palette the owner approved on
2026-09-15. No local edits — one would fail the hash by construction.

Fixes #2647
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(theme): msn-shared.css has drifted into three versions; make one canonical and check it

1 participant