Skip to content

feat: consume brand 1.1 canonical palette and expose its named themes#175

Merged
Tjemmmic merged 1 commit into
mainfrom
feat/brand-1.1-canonical-palette
Jul 14, 2026
Merged

feat: consume brand 1.1 canonical palette and expose its named themes#175
Tjemmmic merged 1 commit into
mainfrom
feat/brand-1.1-canonical-palette

Conversation

@Tjemmmic

Copy link
Copy Markdown
Contributor

Why

@tangle-network/brand@1.1.0 ships the canonical Tangle palette — an indigo-cast surface ladder replacing the flat neutral spine (tangle-network/brand#74). This package is what actually delivers it: dist/globals.css inlines brand's tokens at build time, so a brand release changes nothing for any app until sandbox-ui is rebuilt against it.

Change

  • brand → ^1.1.0 (devDependency and peerDependency). The floor matters: ^1.0.0 would let a consumer resolve 1.0.0, which has neither the canonical palette nor the ./styles/named-themes.css export the @import below depends on.
  • globals.css imports brand's named themes, so an app that opts into data-theme="<name>" resolves it through this one composed entry point instead of reaching into brand for a second stylesheet. Without this, an opt-in silently resolves to nothing — the app keeps the base spine and the theme simply never applies.
  • version → 0.79.0.

Verified in the built output

The point of this PR is what lands in dist/globals.css, so that is what was checked:

  • canonical dark canvas: --hsl-background: 240 33% 6% (was the flat 240 7% 9%)
  • canonical light spine: --hsl-background: 223 23% 94% — white paper on a tinted canvas, not white-on-white
  • .dark[data-theme="intelligence"] present and reachable
  • dist/tokens.css byte-identical to brand 1.1.0's tokens.css

typecheck clean; build clean; the built-CSS validator passes.

Known state

src/dashboard/sidebar-collapse.test.tsx fails (11 tests) — pre-existing on main, verified by running it on a clean checkout of main with identical results. Untouched by this PR, which changes only CSS imports and the manifest.

Downstream

Merging this publishes 0.79.0, which unblocks tangle-network/agent-dev-container#3564 (the app-side unification: platform, sandbox and intelligence stop hand-writing palettes and inherit brand's).

@Tjemmmic Tjemmmic added the DO NOT MERGE Not ready for merge label Jul 14, 2026
@Tjemmmic

Copy link
Copy Markdown
Contributor Author

🤖 AI Code Review (ensemble)

Summary

This PR bumps @tangle-network/brand from 1.0.0 to 1.1.0 (including peer dependencies) and imports the brand's named themes stylesheet into the library's global CSS. The code changes are entirely limited to dependency metadata, lockfile resolution, and a stylesheet import, with no new runtime logic, API changes, or violations of existing repository patterns.

Issues Found

1 total — 0 P1 (blocking) · 0 P2 (should fix) · 1 P3 (nice to have)

ℹ️ P3 — Comment lacks available theme names

  • File: src/styles/globals.css:18-22
  • Problem: The comment explains that themes are applied via data-theme="<name>" but does not enumerate which theme names are valid in brand@1.1.0. Consumers reading this code would have to inspect the brand package directly to know what to pass.
  • Fix: List the available theme names in the comment or link to the brand package's documentation. For example: Available themes: dark, light (see @tangle-network/brand docs).

✅ APPROVE

The change is a low-risk dependency bump and stylesheet composition. Reviewer A's P2 findings are discounted because the diff shows the named-themes.css import path mirrors the pre-existing tokens.css import pattern (verifying it resolves correctly), and the skipped version number (0.77.0 to 0.79.0) is a standard package management practice rather than a code flaw. The only valid, diff-supported issue is the missing list of valid theme names in the code comment, which is a P3 nice-to-have. With no P1s or P2s, the PR is approved.

Quick Reference

  • P3: Comment lacks available theme names

Synthesized by Sokuza AI from multiple independent reviewers

@Tjemmmic
Tjemmmic requested a review from tangletools July 14, 2026 05:37

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Value Audit — sound-with-nits

Verdict sound-with-nits
Concerns 2 (1 medium-concern, 1 weak-concern)
Heuristic 0.0s
Duplication 0.0s
Interrogation 293.2s (2 bridge agents)
Total 293.2s

💰 Value — sound-with-nits

Adds a one-line brand CSS import + bumps the brand floor so named themes resolve through sandbox-ui's composed globals.css; correct and in-grain, but the package's own useBrandThemeSync hook will clobber any data-theme="" an app sets, so the opt-in path this enables is unreachable through the

  • What it does: Two changes: (1) bumps @tangle-network/brand peer + dev floor from ^1.0.0 to ^1.1.0 in package.json (lines 126, 181), and (2) adds @import "@tangle-network/brand/styles/named-themes.css"; to src/styles/globals.css:21, right after the existing tokens.css import. At build time, scripts/copy-styles.mjs:37-44 already resolves bare-specifier @imports via Node package-exports and inlines them through
  • Goals it achieves: Make a consuming app that sets data-theme="<name>" (e.g. brand 1.1's intelligence) resolve through sandbox-ui's single composed stylesheet, instead of the app having to reach into @tangle-network/brand/styles/named-themes.css for a second CSS file. Secondary: raise the brand floor so a consumer resolving brand 1.0.0 can't end up with an @import that points at a non-existent export (named-the
  • Assessment: The change is correct, minimal, and squarely in the grain of the existing tokens.css pattern — same import location, same resolution mechanism in copy-styles.mjs, same single-source-of-truth rationale documented in CLAUDE.md:62. The peer-floor bump is justified: the new @import would fail to resolve against brand 1.0.0. The validate-built-css.mjs guard still passes (it only blocks URL @imports and
  • Better / existing approach: none for the CSS layer — extending the existing tokens.css import pattern is the right approach. BUT the package's own useBrandThemeSync hook (src/dashboard/use-brand-theme-sync.ts:24-31) unconditionally force-writes data-theme to 'dark' or 'light' on mount and on every class mutation, and is mounted by both DashboardLayout (dashboard-layout.tsx:218) and SidebarLayout (sidebar-layout.tsx:225). Its
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 2
  • Bridge warning: opencode/kimi-for-coding/k2p7: bridge stream ended without value-audit content

🎯 Usefulness — sound

A 2-line in-grain change that inlines brand 1.1's named-theme scopes into the composed CSS entry so a consuming app's data-theme="<name>" actually resolves; no better approach, no competing pattern.

  • Integration: Reachable and correctly wired. The new @import "@tangle-network/brand/styles/named-themes.css" (src/styles/globals.css:21) sits directly beneath the identical existing @import "@tangle-network/brand/styles/tokens.css" (line 16) and is resolved by the same mechanism: scripts/copy-styles.mjs:37-44 routes bare specifiers through Node's package-exports resolver, then postcss-import inlines the fil
  • Fit with existing patterns: Follows the established pattern exactly. tokens.css was already imported the same way for the same reason (single composed entry point so apps don't reach into brand for a second stylesheet). Positioning is also correct: after tokens.css (named-themes overrides spine tokens declared there) and before @import "tailwindcss" (so Tailwind's utility scan sees the themed values). The named-themes.css
  • Real-world viability: Holds up. The @import is inlined at build time (no runtime resolution risk), the source package's exports map is the only dependency, and the validator (scripts/validate-built-css.mjs) blocks any URL @import leak that would break downstream chain-imports — so the failure mode that motivated this whole pipeline (CHANGELOG 0.10.9) stays guarded. One real edge worth a heads-up: src/dashboard/use-bran
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1

💰 Value Audit

🟠 Named themes exposed in CSS are clobbered by this package's own useBrandThemeSync hook [maintenance] ``

src/dashboard/use-brand-theme-sync.ts:29-30 computes next = dark ? 'dark' : 'light' and writes data-theme=next unconditionally; src/dashboard/dashboard-layout.tsx:218 and src/dashboard/sidebar-layout.tsx:225 mount this hook in every dashboard/sidebar consumer. So an app that sets data-theme='intelligence' (the opt-in path this PR exists to enable) will have it overwritten to data-theme='dark' on mount and on every subsequent light/dark toggle. The PR body's stated win — 'without this, an opt-i

🎯 Usefulness Audit

🟡 useBrandThemeSync will clobber a named data-theme in dashboard-mounted apps [integration] ``

src/dashboard/use-brand-theme-sync.ts:30 writes data-theme to 'dark' or 'light' based solely on the .dark class, and is mounted unconditionally by DashboardLayout (dashboard-layout.tsx:218) and SidebarLayout (sidebar-layout.tsx:225). An app that opts into a brand named theme via <html data-theme="intelligence"> AND mounts either layout will have its theme reset to the neutral spine on mount. Not a defect of this CSS change — the surface it adds is reachable and correct — but the dashboard


What this audit checks

It judges the change on its merits — not whether it was tasked out in an issue. Unticketed, fast-moving work is fine; the question is whether the change is good and whether a better or existing approach should be used instead.

Pass What it asks
Heuristic Vague title? Whitespace-only or cruft-bearing diff? (content signals only)
Duplication Do added function/class names already exist elsewhere in the repo?
Value Audit What does it do? What goal does it achieve? Is it good? Better architecture or already-exists?
Usefulness Audit Does it integrate and fit? Will it hold up in real use and actually get used?

Findings are concerns, not blocks — the human reviewer decides what to do with them.

value-audit · 20260714T053805Z

@tangletools

Copy link
Copy Markdown
Contributor

✅ No Blockers — 6d85b825

Review health 100/100 · Reviewer score 86/100 · Confidence 75/100 · 3 findings (3 low)

glm: Correctness 86 · Security 86 · Testing 86 · Architecture 86

Reviewer score is advisory once the run is complete and the verdict has no blockers.

Full multi-shot audit completed 3/3 planned shots over 3 changed files. Global verifier still owns final merge decision.

🟡 LOW CHANGELOG.md has no entry for the 0.79.0 release (or 0.78.0) — package.json

Version field bumped 0.77.0→0.79.0 but CHANGELOG.md (read lines 1-60) tops out at ## 0.77.0. CLAUDE.md states explicitly: 'CHANGELOG.md is hand-maintained — add an entry when bumping the version.' The release workflow (.github/workflows/release.yml) auto-publishes on a package.json version push, so this will ship to npm with no release notes. Fix: add a ## 0.79.0 section documenting the brand 1.1 consumption, the @tangle-network/brand peer bump, and the (minor) breaking nature of the narrowed peer range.

🟡 LOW Peer range narrowing for @tangle-network/brand excludes 1.0.x consumers — package.json

^1.0.0 (>=1.0.0 <2.0.0) became ^1.1.0 (>=1.1.0 <2.0.0). A downstream app pinned on brand 1.0.x will now fail pnpm peer resolution. The bump is justified — the PR consumes brand 1.1's canonical palette — but in 0.x semver this is the kind of consumer-facing change that belongs in the CHANGELOG as a noted peer-dep requirement. No code change needed; documentation only.

🟡 LOW Version skips 0.78.0 with an open PR #174 in flight — package.json

Jump from 0.77.0 to 0.79.0 leaves 0.78.0 unused. PR #174 ('feat(workflows): brand-marked agent nodes...') is open/unmerged (gh api confirmed state=open, merged_at=null). Two PRs bumping versions in parallel is normal multi-agent state, but the skip is undocumented — a future maintainer reading git log will wonder whether 0.78.0 was reverted or lost. One-line CHANGELOG note or commit body explaining the skip would close the ambiguity.


tangletools · 2026-07-14T05:38:16Z · trace

@tangletools tangletools left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Approved — 3 non-blocking findings — 6d85b825

Full multi-shot audit completed 3/3 planned shots over 3 changed files. Global verifier still owns final merge decision.

Full immutable report for this review: trace

Summary comment for this run: full summary


tangletools · 2026-07-14T05:38:16Z · immutable trace

@Tjemmmic
Tjemmmic merged commit b10c995 into main Jul 14, 2026
1 check passed
@Tjemmmic Tjemmmic removed the DO NOT MERGE Not ready for merge label Jul 14, 2026
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.

2 participants