Add CI, generate tokens from tokens.json, gate shared/ against client-shared - #7
Merged
Conversation
…ient-shared This repo had NO CI — `.github/` held only banner images — so a change could land unbuilt and `shared/` could diverge from SmooAI/client-shared with nothing to say so. It already had: the monogram fix in f230808 ("restore the inner 'S' curve and the dot") never crossed, so client-shared served a monogram with no S and no dot, and its styles.css lost the whole `.input` family. Both repos were green the entire time, because neither ran anything. - **CI** (`.github/workflows/rust.yml`): fmt, clippy `--all-targets -D warnings`, tests, the module-tree guard, and the shared/ drift gate. - **`shared/` drift gate.** SmooAI/client-shared owns the design system (it is the declared successor and what `th` ships); this repo keeps a copy for observability-studio and smooblue, and CI fails if the copies differ. The gate compares git blob SHAs from the contents API against `git ls-tree`, so adds and deletes are caught too — no filename list to fall behind. Deliberately one-directional: client-shared is ungated so a change lands there and this repo follows; a bidirectional gate deadlocks, with neither PR able to green until the other merges. Chosen over a cargo dependency on client-shared because both crates are git deps, and depending across would put two independently rev-pinned git deps in one graph for any consumer wanting both. - **`shared/tokens.json` was inert** — read by no code in any language while the Rust constants hand-mirrored the same values. `rust/build.rs` now generates the whole `tokens` module from it via `shared/tokens_codegen.rs`, so a token cannot exist in the design system and be missing from Rust. That surfaced six tokens the CSS had and Rust omitted (MUTED, MUTED_FOREGROUND, ACCENT, INPUT, RING, SIDEBAR) plus the radius/space/font scales. `RADIUS_PX` stays as an alias of the generated `RADIUS_MD_PX` so observability-studio keeps compiling. - **`tokens_match_css` could not fail in the direction that mattered.** It asserted each constant appeared *somewhere* in the CSS as a substring: it passes with a constant bound to the wrong property, and nothing walked the CSS, so a token the CSS had and Rust lacked was invisible. `shared/tokens_css_check.rs` parses `:root`, resolves `var()`, and checks both directions. Verified red by drifting a token value and by adding an untracked `--surprise` colour. - **Module-tree guard** (`scripts/check-module-tree.py`): fails if any `.rs` file under `rust/src/` is unreachable from a `mod` declaration — the class that let client-shared ship 174 lines of `auth/refresh.rs` that never compiled. shared/ is byte-identical to SmooAI/client-shared@main (7c5b948); all five blob SHAs verified equal. Tests 6/6, fmt + clippy clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
This repo had no CI.
.github/held two banner images and nothing else — no build, no test, no lint. A change could land unbuilt, andshared/could diverge fromSmooAI/client-sharedwith nothing to say so.It already had diverged. The review that prompted this recorded the two repos'
shared/as byte-identical; onorigin/mainthis morning they were not:The monogram fix in
f230808— "restore the inner 'S' curve and the dot" — never crossed. client-shared, which is what thethCLI ships in production, served a monogram with no S and no dot. Itsstyles.csshad separately lost the entire.inputfamily, and its class-existence test had drifted along with it so nothing was red. Both repos were green the whole time, because neither ran anything.The upstream half is fixed in SmooAI/client-shared#7. This PR is the gate that stops it recurring.
What changed
CI exists —
.github/workflows/rust.yml:cargo fmt --check,clippy --all-targets -D warnings, tests, the module-tree guard, and theshared/drift gate.shared/drift gate. client-shared owns the design system; this repo keeps a copy forobservability-studioand smooblue, and CI fails if they differ. It compares git blob SHAs from the GitHub contents API againstgit ls-tree, so added and deleted files are caught as well as edited ones — there is no hand-maintained filename list to fall behind, which is the failure mode afor f in a b cloop would have.shared/tokens.jsonis code input now. It was read by no code in any language while the Rust constants hand-mirrored the same values.rust/build.rsgenerates the wholetokensmodule from it viashared/tokens_codegen.rs, so a token cannot exist in the design system and be missing from Rust — nobody types the constants. That immediately surfaced six tokens the CSS declared and Rust omitted (MUTED,MUTED_FOREGROUND,ACCENT,INPUT,RING,SIDEBAR) plus the radius / space / font scales.RADIUS_PXis kept as an alias of the generatedRADIUS_MD_PXsoobservability-studio(pinned attag = v0.1.0) keeps compiling when it retags.tokens_match_csscould not fail in the direction that mattered. It asserted each constant appeared somewhere in the CSS as a substring — it passes with a constant bound to the wrong custom property, and nothing walked the CSS, so a token the CSS had and Rust lacked was structurally invisible.shared/tokens_css_check.rsparses:root, resolvesvar()to a fixed point, and asserts both directions.Module-tree guard.
scripts/check-module-tree.pyfails if any.rsunderrust/src/is unreachable from amoddeclaration — the class that let client-shared ship 174 lines ofauth/refresh.rsthat never compiled once, invisible tobuild,clippy,testand coverage alike.Verification — every new check confirmed red before green
tokens_match_csscolor.brand.orangein tokens.jsoncss_colors_are_all_tokens--surprise: oklch(…)to styles.csscheck-module-tree.py.rsshared/verified byte-identical toSmooAI/client-shared@main(7c5b948) — all five blob SHAs equal. Tests 6/6,fmtandclippy --all-targets -D warningsclean.Judgment calls
shared/outright — both crates are git deps rather than crates.io publishes, so it is possible. But it would put two independently rev-pinned git deps in one graph for any consumer that ever wants both, and ui's live consumer is tag-pinned. The gate closes the silent-divergence defect without the coupling.Pearls: th-42c460, th-ea969b
🤖 Generated with Claude Code
https://claude.ai/code/session_0152bbE1veqfG1SVJdyLCBxC