Skip to content

feat(workflows): publish the model brand mark on the workflows entry#177

Merged
Tjemmmic merged 1 commit into
mainfrom
fix/model-brand-on-workflows-entry
Jul 14, 2026
Merged

feat(workflows): publish the model brand mark on the workflows entry#177
Tjemmmic merged 1 commit into
mainfrom
fix/model-brand-on-workflows-entry

Conversation

@Tjemmmic

Copy link
Copy Markdown
Contributor

Problem

The workflow graph's node cards already resolve and render a model's brand mark — src/workflows/node-ui.tsx imports modelBrandFor and ModelBrandStack from ../lib/model-brand. But the only entry that published those two symbols was dashboard.

So a host that wants the same glyph outside the canvas — a node side panel, a run row — had to import them from @tangle-network/sandbox-ui/dashboard, which drags the whole model-picker/widget surface in behind them.

Measured on the platform SPA (products/platform/web), that import cost +3.2 KB gzipped JS — a 192 KB raw prebundled dashboard chunk pulled in to reach a component whose own source is 0.6 KB. It tripped the bundle-size ratchet.

Change

Re-export modelBrandFor, ModelBrandStack, and ModelBrandIdentity from the workflows entry.

This costs the entry nothingnode-ui.tsx already pulls that module into the chunk, so the symbols are already there; they simply weren't reachable. Verified against a real tarball build of this branch: the platform SPA importing the mark from workflows measures byte-identical to deleting the feature entirely (706.9 KB), versus 710.1 KB via dashboard.

It is also where they belong: the mark is a graph-card concept, and a host is already importing the graph from this entry.

Tests

  • src/workflows/entry.test.ts (new) — asserts the entry publishes both symbols and that modelBrandFor resolves a bare model id, so the contract can't silently regress and push consumers back to the dashboard barrel.
  • Full suite green: 798/798, tsc --noEmit clean, re-export identity bridge test 13/13.

Release

Version bumped to 0.82.0 so release.yml publishes on merge. Consumed by tangle-network/agent-dev-container#3572.

The graph's node cards already resolve and render a model's brand mark, but the only entry that published modelBrandFor/ModelBrandStack was dashboard. A host labelling a node outside the canvas — a side panel, a run row — had to import them from there, dragging the model-picker and widget surface in behind them: 3.2 KB of gzipped JS for a glyph, measured on the platform SPA.

They cost this entry nothing — node-ui.tsx already pulls the module — so the same glyph now comes from the entry the host is already importing the graph from.
@Tjemmmic

Copy link
Copy Markdown
Contributor Author

🤖 AI Code Review (ensemble)

Summary

This PR exposes model brand helpers (modelBrandFor, ModelBrandStack, ModelBrandIdentity) from the workflows entry point so external hosts can access them without importing the heavier dashboard entry. The change is focused, well-justified, and includes a regression test for the new contract.

Issues Found

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

ℹ️ P3 — Test couples structural assertion to a live third-party model id

  • File: src/workflows/entry.test.ts:20-24
  • Problem: The happy-path test asserts modelBrandFor("anthropic/claude-sonnet-4-5") resolves to the anthropic lab. If the model registry changes (rename, version bump, id format change), this test breaks even though the PR's actual contract — that the symbols are published — still holds. The null-path assertion is the only branch worth pinning to a concrete value here.
  • Fix: Keep the type checks and the null-path assertion. For the happy path, either use a test fixture/stub lab entry, assert only that a known lab key exists in the registry, or move the Anthropic-specific assertion to a test co-located with lib/model-brand where the mapping is defined.

✅ APPROVE

All three reviewers approved. The export surface change is sound, narrow, and correctly tested. The single P3 finding about test fragility is a valid maintainability concern but does not block merge.

Quick Reference

  • P3: Test couples structural assertion to a live third-party model id

Synthesized by Sokuza AI from multiple independent reviewers

@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

Verdict sound
Concerns 1 (1 weak-concern)
Heuristic 0.0s
Duplication 0.0s
Interrogation 69.9s (2 bridge agents)
Total 69.9s

💰 Value — sound

Zero-cost re-export of the model brand mark from the workflows entry (symbols already in that chunk via node-ui.tsx), so a host labelling a node off-canvas stops dragging the whole dashboard/picker barrel; ships in-grain with a contract test.

  • What it does: Adds modelBrandFor, ModelBrandStack, and type ModelBrandIdentity to the @tangle-network/sandbox-ui/workflows barrel (src/workflows/index.ts:36-40). These were previously reachable only through the dashboard entry (src/dashboard/index.ts:142-144), which also publishes ModelPicker, canonicalModelId, dedupeModels, etc. A new test (src/workflows/entry.test.ts) locks the contract.
  • Goals it achieves: Let a host that already imports the workflow graph reach the same brand glyph it renders on a node card WITHOUT importing the dashboard entry — avoiding the model-picker/widget surface that costs ~3.2 KB gzipped per the PR's measurement. Secondary: make the already-bundled symbols (node-ui.tsx:33 already imports them) actually reachable from the entry, and fix the bundle-size ratchet that the plat
  • Assessment: Good change, squarely in the codebase's grain. Three verifiable facts ground it: (1) src/lib/model-brand.tsx:1-11 is explicitly authored as a LEAF — 'no picker UI, no radix, no lucide' — and declares itself internal ('this module stays internal'), so the intended consumption path IS a domain barrel, never the leaf directly. (2) src/workflows/node-ui.tsx:33 already imports `ModelBrandStack, mod
  • Better / existing approach: none — this is the right approach. Considered a dedicated ./brand or ./model-brand subpath as the 'purest' leaf-level public entry, but it would fight the codebase's stated convention (src/lib/model-brand.tsx:10: 'this module stays internal') and require wiring 3 places (package.json exports + tsup.config.ts entry + new barrel) per CLAUDE.md's subpath contract, for a problem already solved b
  • 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

Re-exports the model brand-mark (already in the workflows chunk via node-ui) so a host rendering the graph can label a node outside the canvas without importing the heavier dashboard barrel — zero bundle cost, correct wiring, tested contract.

  • Integration: Correctly wired. The three symbols are re-exported from ../lib/model-brand in src/workflows/index.ts:36-40; package.json ./workflows already maps to dist/workflows.js and tsup already builds the entry, so no three-place sync was needed (the entry pre-existed). The module is already pulled into the workflows chunk by node-ui.tsx:33, so the re-export is genuinely free — not new surface, just making
  • Fit with existing patterns: Matches the codebase's established pattern exactly: src/dashboard/index.ts:142-144 re-exports the same three symbols (through model-picker) for the same reason — a host holding a model string wants the glyph without re-deriving it. The PR replicates that contract on the lighter entry. The model-brand module is a deliberate leaf (model-brand.tsx:7-11: 'Kept as a LEAF ... so a surface that only draw
  • Real-world viability: Holds up. modelBrandFor (model-brand.tsx:201-207) trims input, short-circuits empty/whitespace, and returns null for any id with no real logo rather than throwing or inventing a mark — the new entry.test.ts:23 asserts the unknown-id null path. ModelBrandStack (model-brand.tsx:211-224) is a pure presentational component that renders null when neither host nor lab has a logo. No concurrency, state,
  • Model: opencode/zai-coding-plan/glm-5.2
  • Bridge attempts: 1

🎯 Usefulness Audit

🟡 workflows is a defensible but graph-flavored home for a mark a non-graph surface may also want [problem-fit] ``

The brand glyph is conceptually broader than the workflow canvas — a run row, a billing usage chart, or a model catalog table has nothing to do with workflows but may want the same mark. Today the dashboard barrel is the only alternative and it is heavier, so /workflows is the right pragmatic pick and the bundle-cost argument (module already in the chunk) is decisive. Worth a one-line note: if a second non-graph surface later needs the glyph, a dedicated ./model-brand leaf subpath (the module is


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 · 20260714T202922Z

@tangletools

Copy link
Copy Markdown
Contributor

✅ No Blockers — bdfc4454

Review health 100/100 · Reviewer score 86/100 · Confidence 70/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 2/2 planned shots over 3 changed files. Global verifier still owns final merge decision.

🟡 LOW CHANGELOG not bumped in this shot (verify elsewhere) — package.json

Version moved to 0.82.0; CLAUDE.md states CHANGELOG.md is hand-maintained per release. CHANGELOG.md is outside this shot's file scope, so unverified here — confirm the PR as a whole updated it.

🟡 LOW Second test case duplicates behavioral coverage already in model-brand.test.ts — src/workflows/entry.test.ts

The 'resolves a brand from a bare model id' case re-asserts modelBrandFor('anthropic/claude-sonnet-4-5')?.lab.key === 'anthropic' and the null fallback for 'some-internal/model-x' — both already covered by src/lib/model-brand.test.ts L20-21 and L31. The incremental value of entry.test.ts is the FIRST case (typeof modelBrandFor/ModelBrandStack === 'function'), which is the genuine entry-publication contract guard. The second case tests the underlying function's behavior, not the entry. Harmless (extra coverage), but if trimming, drop case 2 and keep case 1.

🟡 LOW Re-exporting ModelBrandStack eagerly ships ~28 bundled brand SVGs into the workflows entry — src/workflows/index.ts

model-brand.tsx imports ~28 @lobehub/icons-static-svg icons (L17-45); tsup config marks that package noExternal (tsup.config.ts:32), so esbuild inlines them as data URLs into any bundle that imports the module. After this change, a host importing @tangle-network/sandbox-ui/workflows for ONLY the pure buildWorkflowGraph now also pulls those SVGs + provider-logo.tsx + BrandLogo. The index.ts header comment (L4-10) still literally holds — no optional @xyflow/react peer is loaded — but the 'import stays cheap' spirit is mildly weakened. The added comment at L31-35 justifies the trade-off (alternative is importing the heavier dashboard entry), which is the right call, but worth noting the weight is real and measured-if-bundled. Mitigation if it ever matters: a dedicated ./brand subpath. Not a b


tangletools · 2026-07-14T20:31:11Z · 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 — bdfc4454

Full multi-shot audit completed 2/2 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-14T20:31:11Z · immutable trace

@Tjemmmic
Tjemmmic merged commit 0157dd9 into main Jul 14, 2026
1 check passed
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