Skip to content

feat(NO-TASK): Add wp-theme-baseline and wp-design-tokens skills - #10

Merged
aaronware merged 1 commit into
mainfrom
feat/wp-theme-skills
Jul 30, 2026
Merged

feat(NO-TASK): Add wp-theme-baseline and wp-design-tokens skills#10
aaronware merged 1 commit into
mainfrom
feat/wp-theme-skills

Conversation

@aaronware

Copy link
Copy Markdown
Contributor

Why

No skill in this library owned theme development. Every path routed it to upstream wp-block-themes, which knows generic block-theme mechanics but nothing about our lineage, our brand tokens, or the specificity traps in our own CSS. Walking a realistic scenario — build a theme for a new Linchpin property — the workflow rails held at both ends (classify → task → orient → abstraction choice, and QA → audit → ship) and the middle was unowned.

What's here

wp-theme-baseline (Tier B) — a decision skill, not a scaffold. Child theme first, fresh second, fork last. Its Preflight carries a preset-coverage check that decides between the routes, with numbers measured against both real candidate parents:

Parent Presets used Own tokens from presets Hardcoded hex Read
Ollie (255 lines) 21 0 1 uses presets directly — restylable
DocsPress (4,255 lines) 75 41 40 own token layer fed by presets — restylable

Both pass, for different reasons, so the skill teaches reading the ratio rather than a threshold. The command in the skill runs verbatim and reproduces those figures.

wp-design-tokens (Tier B) — theme.json as the source of truth. Promotes four rules out of linchpin.com's project layer, including the one that costs the most time: theme.json element styles are :where()-wrapped at zero specificity, so the SCSS $heading-size-map beats them and a correct-looking edit does nothing.

The correctness fix worth reviewing closely

wp-local-setup told agents to git clone base-wp-theme-2026 and said "Start from the baseline theme, don't build from scratch." That theme was never launched and its theme.json is a stale fork of the brand. It now points at wp-theme-baseline and carries an explicit earlier versions said to note.

Getting it back under the 250-line limit came from deleting two Gotchas that duplicated its own Guardrails verbatim — nothing load-bearing was cut.

Two research claims I had to correct

Both were in my first draft from reading the repos, and both were wrong. Flagging them because the corrected versions are what the reference file now asserts:

  1. "Ollie's border-light #DADEE3 survives verbatim in base-wp-theme-2026" — false. Ollie's value is #E3E3F0; #DADEE3 is ours. The fork evidence is the slug vocabulary, plus the spacing/font-size slug sets and the regular: 425 weight map, which are verbatim.
  2. "27 style variations collapsed to one" — wrong theme, and the real sequence is more useful. Counts are Ollie 27 → base-wp-theme-2026 23 → themes/linchpin 2. The palette went paint-named first, which is what made the variations unmaintainable later. That's a better argument for role-named slugs than the one I originally wrote.

Also corrected: "46 --dp-* tokens" → 32 distinct tokens with 41 preset-fed definitions driving 383 usages.

Everything else was verified against the files, including all five contrast ratios recomputed independently (2.15:1, 7.25:1, 9.86:1, 8.79:1, 3.06:1).

Verification

  • node scripts/validate-skills.mjs --strict22 skills, 0 errors, 0 warnings. The library previously failed --strict on wp-local-setup's length.
  • All relative cross-references resolve (only the intentional <sibling> placeholder in the authoring template does not).
  • Installer smoke-tested in a throwaway dir: both skills auto-discovered, references/ copied along.
  • Nothing release-please owns was touched — no CHANGELOG.md, package.json, manifest, or README version marker.

Follow-ups for other repos (not in this PR)

  • linchpin.com/ONBOARDING.md still lists base-wp-theme-2026 as a required checkout.
  • linchpin-theme-conventions Rule 1 needs the palette-definition carve-out, or the next agent flags themes/docspress-linchpin as a violation.
  • The 2.15:1 button contrast question from PR #918 has no recorded decision.
  • docspress-linchpin's role vocabulary is DocsPress's, not ours. Until Linchpin owns one, each new property child inherits its parent's names and the properties keep diverging.

🤖 Generated with Claude Code

No skill in the library owned theme development — every path routed it to upstream
wp-block-themes, which knows generic block-theme mechanics but nothing about our
lineage, our brand tokens, or the specificity traps in our own CSS.

wp-theme-baseline is a decision skill, not a scaffold: child theme first, fresh
second, fork last. It carries a preset-coverage check that decides between them,
measured against both candidate parents — Ollie (255 lines) uses presets directly
at 21 uses and 1 hex; DocsPress (4,255 lines) feeds its own 41-definition token
layer from presets, reaching 383 usages with 40 hexes outside it. Both are
restylable from theme.json, for different reasons, so the skill teaches reading
the ratio rather than a threshold.

wp-design-tokens owns theme.json as the source of truth. It promotes four rules
out of linchpin.com's project layer, including the one that costs the most time:
theme.json element styles are :where()-wrapped at zero specificity, so the SCSS
$heading-size-map beats them and a correct-looking edit does nothing. It also
records the palette-definition carve-out to Rule 1, so a child theme's literal
hexes are no longer read as a violation, and documents the Figma exporter
honestly as a plugin an agent cannot run.

Also corrects wp-local-setup, which told agents to clone base-wp-theme-2026 and
said "start from the baseline theme, don't build from scratch". That theme was
never launched and its theme.json is a stale fork of the brand. Trimming it back
under the 250-line limit came from removing two Gotchas that duplicated its own
Guardrails verbatim.

The lineage and the docspress-linchpin worked example move into reference files so
the recurring "should we start from Ollie" question stays closed — Ollie is what
base-wp-theme-2026 is already a fork of.

Validated: 22 skills, 0 errors, 0 warnings under --strict. The library previously
failed --strict on wp-local-setup's length.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@aaronware
aaronware merged commit 117de3e into main Jul 30, 2026
2 checks passed
@aaronware
aaronware deleted the feat/wp-theme-skills branch July 30, 2026 02:29
@aaronware

Copy link
Copy Markdown
Contributor Author

Follow-ups from this PR are now tracked in Linchpin → Coding Standards, alongside LINCHPIN-5164 (the task that created this library):

Task Priority Item
LINCHPIN-5250 High Add palette-definition carve-out to linchpin-theme-conventions Rule 1 — without it, an agent flags themes/docspress-linchpin's literal hexes as a violation and breaks the theme
LINCHPIN-5251 High Decide the primary button contrast contract — #3fc1d0 on #ffffff is 2.15:1, below AA, raised in linchpin.com PR #918 with no decision recorded
LINCHPIN-5252 Normal Remove base-wp-theme-2026 from linchpin.com/ONBOARDING.md, where it's still a required day-one checkout
LINCHPIN-5253 Normal Establish a Linchpin-owned role vocabulary — docspress-linchpin's slugs are DocsPress's, so each new property child inherits its parent's names
LINCHPIN-5254 Low Fix the stale release-tooling paragraph in this repo's CLAUDE.md (see below)

On LINCHPIN-5254 — worth flagging here since it affects anyone working in this repo. CLAUDE.md says "this repo has no commitlint, husky, release-please, or Renovate — it's a plain npm package published by hand." All of that is wrong except husky: release-please.yml is live with npm Trusted Publishing (OIDC), release-please-config.json and the manifest both exist, validate-skills.yml enforces the conventional-commit header on PR titles, and Renovate branches are on origin. The same section's npm version patch && npm publish instruction would fight release-please and bypass Trusted Publishing.

Reading the actual config rather than the doc is how this PR knew NO-TASK was an accepted scope and that feat maps to "Features ✨" — but the next person may not.

aaronware added a commit that referenced this pull request Jul 30, 2026
…t the paint-name claim (#13)

* docs(LINCHPIN-5253): Document the Linchpin slug vocabulary and correct the paint-name claim

Measuring slug usage across the 265 pattern and part files in themes/linchpin
showed the vocabulary problem is much narrower than assumed, and that what I
wrote in #10 was wrong.

Of 1,813 slug references, 96% already flow through Ollie's structural core -
base 557, primary 277, border-light 236, main-accent 203, secondary 178, main
143. The paint tail is 73 references, about 4%. So base-wp-theme-2026 did not
replace the vocabulary; it kept the structural core and appended paint names
alongside it. The precedents reference said themes/linchpin was "still
paint-named", which overstates it. Corrected.

wp-design-tokens now names the structural slugs to reach for, lists the paint
names to avoid in new work, and flags that accent means different colours in
themes/linchpin and themes/docspress-linchpin, so it can never be assumed.

Also records why the tail cannot simply be retired. No two slugs in the palette
share a value, so every remap is a visual change rather than a rename, and
removing a slug stops WordPress emitting its preset custom property, which
silently breaks saved post content carrying has-slug-background-color. That work
needs a live content audit and design sign-off.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs(LINCHPIN-5253): Promote the portable contrast rules out of the project skill

Applying the placement test to what PR 928 added to linchpin-theme-conventions:
some of it is true on any project and belongs here, not in one repo's file.

Moved up, because they hold regardless of whose brand it is:

  - measure every state, not just the resting one. A resting state that passes
    tells you nothing about hover, and auditing only rest states is how a button
    ships that is accessible only while being clicked
  - interaction ramp direction follows the label colour - light surface with a
    dark label lightens, dark surface with a white label darkens. Get this
    backwards and no amount of tuning the resting colour fixes it
  - disabled controls are exempt under WCAG SC 1.4.3, and a 16px bold button
    label is not large text, so 4.5:1 applies rather than 3:1

Stays in linchpin.com because it is one brand's decision: the specific teal, the
hex values and ratios, and the ghost-button gap.

Also removes a stale entry that should never have been in a portable skill - the
2.15:1 button contract was recorded here as an open question, and PR 928 decided
it. Project-specific open items do not belong in the library layer; the durable
lesson does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

1 participant