Skip to main content
Executive Support by Beige Threat

Governance

A design system is a living contract. Governance is the discipline that keeps that contract honest. Three principles guide every call we make: the lowest-friction proposal, the fastest possible no, and the smallest viable yes.

Triage SLA3 working days
Discussion window2 weeks maximum
Minor releaseThursdays, 14:00 UK
Major releaseTwo weeks’ notice, with migration guide
Deprecation cycleOne minor version, minimum
Lint rules in CIThree – all blocking

Roles

Four roles, each with a clear surface they own and a clear surface they don’t. Reach the role, not the person – inboxes are aliased so coverage doesn’t depend on who’s online.

01 · System lead

Sets direction. Final call on breaking changes.

Owns: roadmap, semver discipline, conflict resolution, the changelog.

Does not own: day-to-day reviews, brand identity, individual component APIs.

design-lead@executivesupport.com

02 · Maintainers

Review proposals. Ship token and component releases.

Owns: triage, code review, release notes, lint rules. Two named people minimum, never one.

Does not own: direction, brand identity, breaking-change decisions.

design@executivesupport.com

03 · Contributors

Anyone in the org may propose.

Owns: the proposal, the use case, the draft. Engineers, designers, editors, marketing – all welcome.

Does not own: approval, scheduling, the API surface of shipped components.

Open an issue on the repo

04 · Brand custodian

Owns the magazine voice and visual identity.

Owns: logo, primitive colour, type, photography direction. Can veto colour and type changes.

Does not own: component APIs, semantic tokens, accessibility rules.

brand@executivesupport.com

Decision RACI

The same six decisions come up again and again. The grid below is the answer key – Responsible, Accountable, Consulted, Informed. Disputes refer back to this table before they escalate.

DecisionResponsibleAccountableConsultedInformed
Add a primitive tokenBrand custodianSystem leadMaintainersContributors
Add a semantic tokenSystem leadSystem leadMaintainersBrand custodian
Add a componentMaintainersSystem leadContributorsBrand custodian (if visual)
Rename a tokenSystem leadSystem leadMaintainers, Brand custodianContributors
Deprecate a tokenMaintainersSystem leadMaintainersContributors
Patch a docs typoAnyoneMaintainer on review

How to propose

The shape of every proposal is the same: what, why, where, who else might use it. If a proposal can’t answer those four, it isn’t ready. The templates below ship as issue forms on the repo.

Token proposal

Open an issue with the W3C DTCG JSON snippet, the use case, and the alternative considered. The form mirrors the existing token files so review is mechanical.

## What
A new semantic token: `color.feedback.notice.surface`.

## Token (W3C DTCG)
{
  "color": {
    "feedback": {
      "notice": {
        "surface": {
          "$value": "{color.mustard.100}",
          "$type": "color"
        }
      }
    }
  }
}

## Why
The notice banner pattern needs a calmer surface than `feedback.warning.surface`.
Mustard 100 reads as informational without alarm.

## Where
Subscriber communications banner, billing-state notices, scheduled-maintenance ribbon.

## Who else
Editorial workflow notices, in-product release notes.

## Alternative considered
Reusing `feedback.info.surface` – rejected because the cool blue reads as system, not editorial.

Component proposal

Open an issue with five things: a problem statement, three product references, a sketch (low-fi is fine), the API surface, and accessibility considerations. Sketches do not need to be Figma frames – paper photos pass triage.

## Problem
Editors saving long interviews can't see how many words have been added since the last save.

## References
1. Google Docs – word-count diff in the footer.
2. Notion – per-block change indicator.
3. Internal sketch from issue 84 retro.

## Sketch
[attach – paper, Figma, screenshot, all fine]

## API surface (proposed)
<WordCountDiff
  baseline={number}
  current={number}
  variant="inline" | "footer"
  ariaLabel={string}
/>

## Accessibility
- Live region: polite, announces every 30s of typing.
- Visible focus ring matches `border.focus`.
- Reads "added 240 words since last save" – not "+240".

Pattern proposal

Patterns aren’t tokens or components – they’re recipes. Propose in a doc PR with a draft of the patterns page entry. The PR is the proposal.

Review process

Five stages. The clock runs on triage and discussion only. Build takes as long as it takes – we’d rather ship the right thing late than the wrong thing on time.

  1. 01

    Triage – within 3 working days

    A maintainer asks three questions: is this a duplicate, is it in scope, is it the right tier? Outcomes: accepted for discussion, redirected, or closed with a one-line reason.

  2. 02

    Discussion – two weeks maximum

    At most two maintainers in the thread. We converge or close. Proposals stalled past two weeks default to “not now” – the author can re-open with new evidence.

  3. 03

    Spike – optional

    A branch with a minimal implementation, behind a feature flag. Used when the design works on paper but the API surface is uncertain. Spikes are time-boxed to one week.

  4. 04

    Build & docs

    Implementation, docs page, tests, tokens, lint rules. The four ship together or not at all – a component without docs is not shippable.

  5. 05

    Ship

    Version bump, changelog entry, release note in #design. Beta first for new components – four weeks minimum before stable.

What’s breaking vs additive

The semver contract is the heart of the system. See /design/changelog/ for the full rules. The short version, written for proposers:

Change classification
major
Breaking

Rename, remove, or invert the meaning of any public surface – a token, a component prop, or a semantic role. Requires a major bump and a one-minor-version deprecation cycle.

Renaming color.brand.primary to color.brand.accent.
Removing the variant=“ghost” prop from Button.
Inverting spacing.tight from 4px to 12px.

minor
Additive

New tokens, new components, new variants. The existing public surface is unchanged. Old code keeps working without edits.

Adding color.feedback.notice.surface.
Adding a new WordCountDiff component.
Adding variant=“quiet” to an existing Button.

patch
Fix

A wrong value, a doc typo, an accessibility regression. The intent does not change – the implementation catches up to it.

Fixing a contrast ratio that fell below 4.5:1.
Correcting a misspelled token in docs.
Restoring the focus ring lost in a refactor.

Breaking changes need a major bump and a deprecation cycle of at least one minor version. The deprecated surface emits a console warning, ships a codemod where possible, and is removed only in the next major.

The lint discipline

Three rules run in CI on every PR. They block merge. Maintainers don’t override – they fix or send back. See /design/naming/ for the rule definitions and the regex behind each. The governance angle:

Do · Treat lint as a teammate

“Failing in CI means we caught it before users did.”

Lint catches the patterns no human reviewer can hold in their head – tier crossing, naming drift, forbidden values. Trust it.

Don't · Override lint to ship faster

”Just this once – the rule is being annoying.”

If a rule is wrong, fix the rule. If the rule is right, fix the code. The third option – overriding for one PR – is how systems silently rot.

Token & component lifecycle

Every primitive moves through the same seven stages. Targets below are the ones we hold ourselves to – missed targets are a maintenance signal, not a failure.

  • Proposal Open-ended Issue opened with the templated form. Author drafts what, why, where, who else.
  • Triage ≤ 3 working days Duplicate, in scope, right tier? One maintainer responds.
  • Spike ≤ 1 week Optional. Minimal branch, behind a flag. Time-boxed.
  • Beta ≤ 4 weeks Shipped behind a flag or namespaced as `*-beta`. Real use, real feedback.
  • Shipped Indefinite Stable. Documented. Linted. Recommended in patterns.
  • Deprecated ≥ 1 minor version Console warning, codemod where possible, replacement named in the changelog.
  • Removed Major release Major version only. Migration guide published two weeks before release.

When to escalate

Most disagreements resolve in the issue thread. The ladder below is for the ones that don’t. Every escalation closes with a written rationale – the next person to hit the same fork should not have to re-litigate it.

ConflictResolves toOutput
Two maintainers disagree on a reviewSystem leadOne-paragraph decision, posted on the issue.
System lead and Brand custodian disagreeJoint call within a weekWritten rationale either way, recorded in the changelog or governance log.
A token is used outside its tierBlocked by lint automaticallyIf recurring, a maintainer flags the pattern – never the person.
A proposal stalls past two weeksDefaults to “not now”Author can re-open with new evidence; no judgement implied.
A breaking change is shipped without a deprecation cycleReverted, no exceptionsSystem lead writes the post-mortem within five working days.

Versioning cadence

Predictable cadence is half the contract. Anyone integrating the system should know when to expect a release and what shape it will take.

Release typeWhenWho can cut
PatchAny timeAny maintainer
MinorThursdays, 14:00 UK – entries close 12:00Two maintainers, paired
MajorScheduled, two weeks’ notice, with migration guideSystem lead, with paired maintainer

Communication

Four channels, each with a single job. If you can’t tell which channel a message belongs in, default to the issue – it has the longest memory.

#design

Every release announced here, with a link to the changelog entry. Quick questions welcome – long ones move to issues.

Issues on the repo

Every proposal lives here – tokens, components, patterns, bug reports. The issue is the source of truth, not the Slack thread.

Design weekly

Tuesdays 10:00 UK. Open to all. Agenda posted 24h ahead in #design – walk-ins welcome, but agenda items get the time.

The changelog page

The source of truth. Every change, every version, every deprecation. If it isn’t in the changelog, it didn’t ship.

Usage rules

Six habits that keep proposals moving and the system coherent. Read once, then refer back when a review feels stuck.

Do · One proposal per issue

”Add a notice surface token.”

Each issue tracks one decision. Bundling five token requests into one issue stalls all five – discussion forks, history blurs.

Don't · Bundle five token requests

”Add notice, success-quiet, warning-loud, info-bold and danger-soft – all related.”

Related is not the same as one decision. Five tokens means five discussions, five trade-offs, five places they’ll be used.

Do · State where else this is used

”Notice surface – billing, scheduled maintenance, editorial workflow.”

The system loves shared use cases. A token used in three places earns its keep – one used in one place is a candidate for an inline value.

Don't · Bypass review for 'small' changes

”It’s just a 2px tweak – I’ll merge it.”

The system reads small additions cumulatively. Ten “just a 2px tweak” merges later, the rhythm is gone.

Do · Ship faster with a draft docs page

”Proposal includes the draft /design/components/word-count-diff/ entry.”

Maintainers approve faster when the docs are already shaped. The draft answers half the review questions before they’re asked.

Don't · Argue past a brand-identity veto

”Brand custodian’s no on visual identity is final, with rationale.”

Voice and visual identity are deliberately not democratic. The custodian writes the rationale; the rationale enters the governance log; the conversation closes.

Do · Treat lint failures as bugs

”CI failed – the rule caught a real tier crossing. Fix and re-push.”

Lint failures are signal, not bureaucracy. They’re how the system tells you the rule you’re proposing already conflicts with the one you wrote last quarter.

Don't · Treat lint failures as bureaucracy

”It’s blocking my PR – can someone disable the rule?”

The rule is doing its job. The fix is upstream – either in the code, or in a proposal to change the rule with the same templated form.