docs(spec): module design pack — permissive components + tokens so modules match the desk (HT-95) - #104
docs(spec): module design pack — permissive components + tokens so modules match the desk (HT-95)#104zaridan wants to merge 9 commits into
Conversation
📝 WalkthroughWalkthroughAdds a draft Design Pack v1 specification covering module theming, component distribution, permissive publication, provenance checks, upstream synchronization, CI drift detection, marketplace conformance, and deferred core-screen UI embedding. ChangesDesign Pack v1
Estimated code review effort: 1 (Trivial) | ~5 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
specs/modules/design-pack-v1.md (1)
61-62: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winClarify that the typed token export cannot bundle runtime values.
The pack is required to consume installed-desk token values, but “typed export” could be interpreted as shipping default values that modules import and bundle. Define it as token names/types only, or specify a runtime resolver, and explicitly prohibit packaged defaults from becoming the module’s theme source.
Also applies to: 77-81
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@specs/modules/design-pack-v1.md` around lines 61 - 62, Clarify the “Tokens” definition in the design-pack specification to state that typed exports contain token names and types only, not bundled runtime/default values. Specify that modules must consume installed-desk token values through the existing runtime mechanism and prohibit packaged defaults from serving as the module theme source; apply the same clarification to the related section at lines 77–81.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@specs/modules/design-pack-v1.md`:
- Around line 110-122: Update the marketplace conformance requirement in the
listed-module rules so consuming the design pack for every operator-visible
surface is mandatory rather than recommended. Define the permitted exceptions
and require documented review evidence, including the existing explicit
sign-off, while preserving the prohibition on impersonating core Helpthread UI.
- Around line 53-55: Update the design-pack repository recommendation in “Open
decision 2” to define an exact upstream ds/ revision pin for generation, and
require CI to regenerate from that pinned revision before performing a
byte-for-byte comparison. Specify that this drift gate distinguishes stale
generated output from intentional source revisions.
- Around line 26-34: Add a provenance and license audit requirement to the
design-pack specification before selecting MIT or Apache-2.0. Document the
rights chain for the Claude Design source, generated ds components, theme
tokens, and bundled assets, and require confirmation that each can be
redistributed under the chosen license; do not treat generation from AGPL
sources as sufficient evidence.
---
Nitpick comments:
In `@specs/modules/design-pack-v1.md`:
- Around line 61-62: Clarify the “Tokens” definition in the design-pack
specification to state that typed exports contain token names and types only,
not bundled runtime/default values. Specify that modules must consume
installed-desk token values through the existing runtime mechanism and prohibit
packaged defaults from serving as the module theme source; apply the same
clarification to the related section at lines 77–81.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: b1163a0a-fc3d-4989-9739-0f8360a4c3f5
📒 Files selected for processing (1)
specs/modules/design-pack-v1.md
|
@coderabbitai review Incremental review is off by config, and |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@specs/modules/design-pack-v1.md`:
- Around line 156-159: Update the terminology in the design-sync options to use
the defined AI-actor vocabulary: replace “agent session” with “Assistant
session” and “scheduled agent” with “scheduled Assistant,” while preserving the
surrounding meaning and wording.
- Around line 131-135: Update the fenced source-tree diagram in the “Claude
Design project” section to specify the text language, using a text-labeled fence
so the diagram remains unchanged while satisfying Markdown linting.
- Around line 69-72: Update the Fonts section in design-pack-v1.md to address
the remote Google Fonts dependency: document the Google Fonts runtime requests,
third-party data-egress and CSP/policy requirements, offline behavior, and
fallback fonts, or remove the dependency by vendoring the OFL font files and
updating the licensing statement accordingly.
- Around line 92-97: Reconcile the component inventories in Sections 3 and 5 so
they use one consistent v1 package scope and totals. Align the core and inbox
lists, including the four staged primitives, and update every stated count to
match the intended upstream package contents before implementation.
- Around line 173-182: Update the content-hash manifest specification to cover
the complete generated package rather than only sourced files. Define an exact
set of expected package paths, including derived artifacts such as typed token
exports, and record SHA-256 hashes for every path so CI detects modified,
missing, or extra files while preserving the existing upstream-moved and
hand-edited distinctions.
- Around line 148-162: Clarify the “Sync is a process, not a pipe” section to
distinguish unattended synchronization from unattended merge or release:
scheduled agents may run the sync and prepare or open a PR, but merging and
releasing must remain human-reviewed and approved. Update the conflicting “no
unattended sync” wording while preserving the reviewed-PR requirement.
- Around line 112-121: Update the specification’s v1 decision and corresponding
requirement language to resolve the cross-origin theming gap: either define the
public token transport and its behavior, or explicitly exempt
own-origin/cross-origin Modules from the white-label parity MUST requirement.
Apply the same clarification to the related section around the other referenced
requirement, keeping embedded Modules’ inherited desk-token behavior unchanged.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 1efde955-29a3-4c92-a108-1ee086dafdb1
📒 Files selected for processing (1)
specs/modules/design-pack-v1.md
|
@coderabbitai review Incremental review is off by config. Two commits since your last pass ( |
|
✅ Action performedFull review finished. |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@specs/modules/design-pack-v1.md`:
- Around line 7-10: Reconcile the component inventory in the design-pack
specification: clarify whether CredentialRow and PasskeyList are separate
components or one combined artifact, then consistently update the component
names, total count, and “16 of 20” statement, including the related inventory
section.
- Around line 52-58: Update the provenance audit requirements in the design-pack
specification so rights clearance is a blocking release gate before the first
MIT publication. Require documented confirmation of copyright and relicensing
rights for every published artifact, explicitly including token and theme
artifacts, rather than relying on authorship or AI-assisted generation claims.
- Around line 227-240: Update the manifest specification so it exhaustively
hashes every published package path, including checked-in source copies and
release-only files such as package metadata, README, and license files, in
addition to sources and generated artifacts. Ensure CI compares the complete
checked-in package tree against the regenerated manifest so hand edits or
added/removed non-generated files fail validation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: f345ba81-1e3b-4b6b-93f5-5f4c055fdd17
📒 Files selected for processing (1)
specs/modules/design-pack-v1.md
Per TJ, 2026-07-20: 'let's have the gate work on modules, too.' The filter listed catalog.md, marketplace-v1.md, substrate-v1.md by name, which left design-pack-v1.md ungated — so PR #104, encoding an MIT relicensing decision, would have passed the gate untouched. Widened to ^specs/modules/ so every module spec, present and future, carries a verdict and provenance table. Rule doc updated in both copies to match. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@coderabbitai review Incremental review is off, so requesting explicitly. All three findings from your last pass are addressed in
|
|
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 37 minutes. |
…dules match the desk (HT-95) Modules are out-of-process and render their own UI, so nothing today makes a module look like the desk it installs into. web/src/components/ds/ and web/src/theme/tokens/ are the right raw material but are AGPL, and a born-proprietary paid module importing them links AGPL code in-process — the case the §7 Module API Exception covers, which is still DRAFT. Proposes publishing the pack under a permissive license as its own package: needs no §7 exception at all, and paid → free is the permitted direction under catalog.md §1. Components are not the moat. Also: theming resolves against the installed desk (white-labeling is a paid item), the pack is generated from ds/ rather than forked (same discipline as CLAUDE.md's UI-fidelity rule, one hop out), and conformance is a marketplace listing requirement since no runtime check can ever enforce it. Docs only. ds/ is owned by HT-93 (PR #103) and HT-94 — untouched here. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… endpoint (HT-95) Apache-2.0 was considered and rejected: no patentable invention in a component library, so its patent grant covers a threat that does not exist, while NOTICE preservation is real overhead. MIT is the React component-library norm and readable without legal review. Adoption friction is the live constraint. Pack ships as its own repo (helpthread-design-pack, @helpthread/design-pack) — a permissive directory inside an AGPL tree gets misread by the audience that needs to trust it. Token transport: custom properties ship with the pack, desk values win. Embedded modules inherit the desk scope for free; a public endpoint waits until an operator has both re-skinned and installed a cross-origin module. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… not downstream (HT-95) Chaining pack <- ds/ <- design project would propagate any ds/ drift into every module — the same failure the spec exists to prevent, one layer down. As siblings, the desk and its modules cannot drift from each other without both drifting from a single source that byte-comparison catches. Also unblocks: 16 of 20 components are already promoted upstream, so the pack no longer waits on HT-93/HT-94. The four new primitives arrive when HT-94 part B promotes them out of templates/new-primitives/. Verified against the design project's file list rather than assumed — it already carries components/core/, components/inbox/, tokens/, theme/, and fonts/. Sync is documented as a process, not a pipe: DesignSync authenticates through a claude.ai login and its writes need interactive plan approval, so it cannot run unattended in CI. Options are the /design-sync skill or a scheduled agent that opens a PR — cadence automation, not a live connection. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…gate, MUST-level conformance (HT-95) Three Major findings, all real. Provenance (§2.1): relicensing requires owning the rights, and generation establishes origin, not grantability. Fonts verified clear — fonts.css @imports Source Serif 4 and Source Code Pro from Google Fonts, both OFL, no binaries bundled, so nothing is redistributed. Components still need an audit against the repo's provenance/AI policy. Noted the asymmetry that lowers the stakes: MIT grants whatever rights exist, so uncopyrightability means 'cannot enforce', not 'infringing' — near-harmless for a pack meant to be used. Drift gate (§5): a revision pin is not available — the design project is not a git repo and DesignSync exposes no version identifier. Baseline is a content-hash manifest instead, which separates 'upstream moved' from 'pack was hand-edited'; byte-compare alone conflates them. Conformance (§6): SHOULD-consume contradicted calling it a listing requirement. Now MUST, but on the outcome (matches the desk) rather than the mechanism (imports the pack) — otherwise a module with no operator-visible UI would be non-conformant for having nothing to style. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Vocabulary (CLAUDE.md violation, mine): 'agent session' and 'scheduled agent' described AI automation. Agents are human support staff; Assistants are AI actors. Corrected, with the rule cited inline so the next editor does not repeat it. Inventory: §3 said 16 core, §5 said 12 core with 4 staged — both true at different times, neither said when. Now stated as 12 core at v1, 16 after HT-94 part B, with totals given once (16 -> 20) and a rule for reading every other count in the doc. Cross-origin conformance: §6's MUST required matching a white-labeled desk while §4 shipped no token transport, so a cross-origin module could not conform. Made the exemption explicit and time-bound — a conformance rule nobody can satisfy is worse than no rule. Drift gate: hashing only sourced files cannot distinguish expected generation from hand edits, since the pack also contains derived output. Now two closed path sets, sources and generated, with appearing/vanishing files failing the gate. Truth table extended to all four states. Fonts: excluded from the pack pending HT-99. Licensing was settled (OFL, no binaries vendored) but the @import means every module page would hit fonts.googleapis.com with the visitor's IP — inconsistent with shipping open-tracking-off as a free-core position, and a CSP/offline problem for self-hosters. Already live in the desk, so filed against core. Sync wording: 'no unattended sync' contradicted permitting scheduled sync. Reworded to bound it at the PR — an Assistant may prepare and open, never merge or release. Markdown: fenced the source-tree diagram as text (MD040). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…T-95)
TJ ratified MIT explicitly ('yes MIT') after confirming the scope: the design
pack only. Core stays AGPL-3.0, LICENSE untouched, ds/ stays part of the AGPL
core. Recorded as his decision with his words, per the verdict protocol — the
earlier PR body framed it as settled on the strength of 'MIT, shit, i don't
care', which is not ratification of a one-way licensing door.
Noted the nuance that makes it low-risk: this is not relicensing core code.
Resonant IQ holds the copyright outright — ds/ has a single author — so the same
components are published under a second licence in a separate package while the
copies inside the core remain AGPL. Dual-licensing your own work costs the core
nothing.
Added the one boundary worth holding: brand assets are excluded permanently. The
wordmark, logo, and any Helpthread-identifying mark stay out of the pack and its
repo. MIT grants copyright and not trademark, so nobody could call their product
Helpthread either way — but shipping the wordmark inside an MIT package invites
the confusion legal/trademark-policy.md exists to prevent. The pack ships the
system, never the identity.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…hash coverage (HT-95) Three findings, all real. Inventory: the spec counted 'CredentialRow/PasskeyList' as one item, leaving the post-HT-94 total ambiguous. Verified against the file — CredentialRow.jsx exports BOTH CredentialRow and PasskeyList, and there is no separate PasskeyList.jsx. So it is one file, two components. Counts are now given as an explicit files-vs- components table (20 files / 21 components after HT-94 part B) with a stated default so every other figure in the doc reads unambiguously. Provenance: the audit was described as 'due diligence, not a blocker to design around', on the reasoning that MIT grants only whatever rights exist so the downside is unenforceability rather than infringement. That reasoning is sound about the downside and wrong about the sequencing — MIT publication is a one-way door, and copies already taken cannot be recalled. It is now a blocking release gate with four named items: every published path cleared (tokens and theme, not just components), sole authorship verified and dated, AI-assisted generation reconciled against legal/provenance-policy.md, and the clearance written down in the pack repo. Hash coverage: the manifest covered sourced and generated files but not release-only paths — package.json, README, LICENSE, CI config. A hand-edit there would pass both existing checks. Added a third 'static' set and stated the invariant plainly: the manifest is exhaustive over the published package, not merely over its inputs, and any published path missing from the manifest fails the gate. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CodeRabbit was rate limited, so an independent adversarial pass ran in its place. Six findings, five blocking. All were mine. 1. THE COPYRIGHT CLAIM CONTRADICTED THE CHARTER. The spec asserted 'Resonant IQ holds the copyright outright (ds/ has a single author)'. Checked: git log returns one name, TJ Baker — an individual, not the company — and CHARTER.md §3 says contributions arrive under DCO with no assignment and 'Contributors keep the copyright on their work'. The project holds an inbound AGPL licence, not title. Single authorship records who committed, not who owns. Publishing under MIT still works — a sole author may license their own work — but a public claim about which entity holds title, contradicted by the repo's own constitution, must not ship. Naming the grantor is now item 5 of the §2.1 gate. 2. WRONG AUTHORITY CITED. catalog.md's 'paid → free stays possible' is a monetization axis — whether a paid module may later join the free core. It says nothing about copyleft→permissive. Citing it made relicensing look pre-approved by an accepted spec. Withdrawn; the argument stands without it. 3. THE BLOCKING GATE COULD NOT BLOCK. It governed a repo that does not exist yet, with no owner, no artifact, and no mechanism — prose wearing the word 'blocking', the same shape as the instructions that failed in this repo's own audit. Now: a dated CLEARANCE.md in the pack repo, asserted by the publish workflow and failing npm publish if missing or stale, owned by TJ, with the pack repo not created until the grantor question is answered. 4. THE ANTI-DRIFT TABLE WAS ITSELF WRONG. It counted only .jsx and omitted 21 .d.ts files and primitives-support.jsx — a shared helper the four newest primitives import, which ships and would break the package if left out. Real counts, verified against the tree: 34 core + 8 inbox = 42 published files; 20 components across 21 .jsx. Files is now the stated default unit, which is also what the clearance gate and the manifest operate on. 5. .d.ts WERE CLASSIFIED AS GENERATED. They are fetched verbatim from the design project (HT-97 re-pulled 21), so they belong in 'sources'. As written, upstream .d.ts churn could never trip the 'upstream moved' row. 6. THE BRAND CARVE-OUT EXCLUDED ALMOST NOTHING. It pointed at theme/helpthread.css, which is a comment plus three @imports and holds no brand value. Meanwhile the token files that DO ship are brand-bearing: colors.css opens with a block commented '/* identity */' above --ht-accent, and typography.css sets --ht-serif to the wordmark face. Now states plainly that the palette and type scale ship and are meant to be overridden; only the marks are withheld. Also dropped a restatement of the Agent/Assistant vocabulary rule — that definition was revised 2026-07-31 and a copy here is one more place to drift. Rebased on current main; HT-93 and HT-94 have merged, so the counts reflect the tree as it stands rather than a pending promotion. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cc8ad67 to
022d9df
Compare
§2 still read '20 files / 21 components after HT-93' — a figure from before the counts were verified against the tree. It is 42 published files (§3). Caught on re-check after committing; the earlier replacement had matched an intermediate version of the line rather than the final one. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 25 minutes. |
🟡 NEEDS YOUR DECISION → awaiting bot re-review
Spec only — adds
specs/modules/design-pack-v1.md. The licensing decision is now ratified. Verdict flips to 🟢 once CodeRabbit confirms on the current head; nothing else is outstanding.Decision provenance
Scope of the MIT decision
Design pack only. The core stays AGPL-3.0,
LICENSEis untouched,web/src/components/ds/stays part of the AGPL core.Not a relicensing of core code: Resonant IQ holds the copyright outright (
ds/has a single author), so the same components are published under a second licence in a separate package while the copies inside the core remain AGPL.Excluded permanently: wordmark, logo, any Helpthread-identifying mark. MIT grants copyright, not trademark — and shipping the wordmark in an MIT package invites the confusion
legal/trademark-policy.mdexists to prevent.Why MIT is actively useful: a paid module cannot legally use AGPL components without the §7 exception, which is still an unadopted draft no human has read. MIT removes that dependency for every module author.
Bot findings
CodeRabbit ran twice: 10 findings, all adjudicated and fixed — provenance gate, drift baseline, conformance level, fonts privacy, inventory inconsistency, cross-origin conformance gap, hash coverage, an Agents/Assistants vocabulary violation, sync wording, markdown lint. None outstanding. A third review is requested on the current head; the verdict stays 🟡 until it lands.
One finding escalated out of this PR: the Google Fonts
@importsends visitor IPs to Google from the live desk — HT-99. Fonts are excluded from the pack pending that call.Also settled in the spec
ds/, not downstream — a chain would pushds/drift into every module