Skip to content

feat(aidd-ui): validate the design system on every write - #1133

Merged
blafourcade merged 26 commits into
nextfrom
feat/aidd-ui-rework
Oct 31, 2026
Merged

blafourcade merged 26 commits into
nextfrom
feat/aidd-ui-rework

Conversation

@blafourcade

@blafourcade blafourcade commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

🎯 What & why

First of five pull requests rebuilding aidd-ui (roadmap). It lays the foundation: the format of a project's design system under aidd_docs/ui/, and a deterministic validator that rejects any record, token, render or code link that breaks it. No skill yet.

🛠️ How it works

  • One file per element (system, brand, tokens, assets, components, screens, journeys, reviews), flat front matter, a ## History table per record. Format: plugins/aidd-ui/README.md.
  • status tracks the design; implemented-version the version the code implements, so code lagging a new design stays visible.
  • system.md states its record format and versions at publication only, from the tasks a row lists: parallel features on distinct elements never conflict. A task is its folder; a review verdict names the version it judges.
  • Tokens follow W3C DTCG 2025.10; themes follow its Resolver module (tokens.resolver.json, one file per theme). A render uses only the tokens its record declares, and a raw CSS value's var() must name a token, so an impact report read from the records misses none.
  • Rules live in plugins/aidd-ui/hooks/lib/, one module per family over a shared record model. No AI, Node built-ins only. Each problem carries its rule and a severity; only errors fail the check or block a turn.
  • One engine, aidd-ui.cjs validate, that later generators extend; the hook (ui-hook.cjs) runs it at session start, after every write under aidd_docs/ui/ or a code root, and at the end of a turn that wrote one. After a write it prints the problems of the files the write reached, capped at 20 lines.
  • Contract and plan: spec.md, plan.

🧪 How to verify

  • node scripts/check-tests-leave-git-alone.js -- node --test scripts/__tests__/aidd-ui-*.test.js: every rule has one test its mutation turns red.
  • Write a sample project with writeProject from scripts/tests/fixtures/aidd-ui/project.js, then node plugins/aidd-ui/hooks/aidd-ui.cjs validate <dir>: VALID. Break any record: one ✗ line.

⚠️ Heads-up

  • The format was confronted with a real project's component library and code. As a result, a link covers its file's folder, an assembled molecule or composition is implemented through its components, components need ## Usage and cite semantic tokens only, a code file no record links and a 2px-or-less render width are warnings, and tests and the code's token file are not checked for colours.
  • The themes are unproven on real data: that project has no dark mode.
  • Feedback after a write reaches the model in the same turn on Claude Code, Codex, Copilot CLI, OpenCode and Kilo; at turn end the errors go back once, as the next prompt on OpenCode and Kilo, elsewhere as a block. Measured on each real host with this plugin's hook through the flat install; the marketplace install was measured for Codex and Copilot before the turn-end hook existed, not since. Cursor is unverified. Other limits in the plugin README.

🔗 Linked issue

Refs #1120

✅ I certify

  • I DO CERTIFY I READ EACH LINE OF THE PULL REQUEST BECAUSE I AM A SOFTWARE ENGINEER, NOT A AI PUPPY.

🤖 Generated with Claude Code

https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn

blafourcade and others added 6 commits October 30, 2026 12:15
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mD4irAZumku9bknHhD
… every write

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mD4irAZumku9bknHhD
…able folders

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mD4irAZumku9bknHhD
A link now covers its file's folder, so a component's styles, hooks and
tests need no record of their own; a file at a code root still covers only
itself. A molecule or composition with no file of its own is coded once
every component it uses is. Code is checked for colour literals only.
Components need a usage section and cite semantic tokens, never a group
system.md declares primitive.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mD4irAZumku9bknHhD
@blafourcade
blafourcade marked this pull request as ready for review October 30, 2026 17:51
@blafourcade
blafourcade requested a review from a team as a code owner October 30, 2026 17:51
blafourcade and others added 2 commits October 30, 2026 19:49
Extracting Gouvernail and Kairos into the format showed rules that fail
real projects. A link covers its folder only when the folder bears the
file's name, else the files of its stem, so a flat folder no longer hides
its siblings. An element may use its own level, never itself. Only focus
is required of an interactive component. The rem rule goes. The first
theme is the base and a themed token gives every other one; an alias must
match its type; a value DTCG cannot hold rides a raw CSS extension; $root
is named unsupported instead of dropped. A render may set its own custom
properties.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mD4irAZumku9bknHhD
…e Code

The hook read only Claude Code's tool_input.file_path and answered only on
stderr. Codex sends apply_patch's patch in tool_input.command; Copilot sends
either a patch string as tool_input or {path, old_str, new_str}, and reads
only additionalContext on stdout. The hook now reads every one of these
shapes and answers on both channels, with exit 2.

Verified against real hosts: a token added to a component without a
definition is quoted back by the model on Claude Code, Codex and Copilot CLI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mD4irAZumku9bknHhD
blafourcade and others added 3 commits October 31, 2026 05:39
A Codex model read exit 2 after a write as a refused edit and reported no file changed,
though the file was written. The hand-back now opens with a line saying the write landed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mD4irAZumku9bknHhD
…host

Exit 2 after a write read as a refused edit on Codex. The hook now exits 0 and answers in the
shape each host reads: hookSpecificOutput.additionalContext on Claude Code and Codex, top-level
additionalContext on Copilot. A write marks the turn; Stop blocks once while problems remain,
and not again on a forced continuation.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
Comment thread plugins/aidd-ui/hooks/ui-hook.cjs Fixed
blafourcade and others added 12 commits October 31, 2026 08:43
The shipped hooks.json listed SessionStart and PostToolUse only, so no install ran the turn-end
check. Tests named it; a guard on the declaration now fails without Stop.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
… continuation

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
…ild on

Split design status from the version the code implements, version the design system at
publication only, name tasks by their folder, version the format, adopt the DTCG Resolver
for themes, generate tokens only under aidd_docs/ui, one engine for every generation, and
a severity per problem with scoped hook output. Record the decisions later pull requests own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
A check that throws becomes one problem naming it instead of silencing the rest. A turn mark
that cannot be written no longer costs the write its feedback, and Stop reads no project on
a turn that wrote nothing watched. Kinds and folders are own keys only, and a byte order
mark or CRLF is dropped once for every file, tokens.json included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
…ments

`implemented-version` replaces the coded status, so code lagging a new design stays visible.
system.md versions at publication only, from the tasks a row lists, so parallel features on
distinct elements never conflict, and a token-only change can break. Tasks are task folders,
review verdicts carry the version they judge, and system.md states its record format: another
format is one problem, never an avalanche.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
…a render uses

tokens.json holds the base theme; tokens.resolver.json names a file per other theme, which
redefines base tokens only, with their type. Screens cite tokens like components, a render uses
only the tokens its record declares, and a raw CSS value's var() must name a token, so an
impact report read from the records misses none. system.md names the code's token file, kept
out of coverage and colour checks, and tests may state colours. tokens.json is parsed once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
…t the hook prints

Every problem carries its rule id, and is an error unless its rule calls it a warning: a code
file no record links, and a render width of 2px or less. Only errors fail the validator or
block a turn's end. After a write, the hook prints the problems of the files the write reached,
its render and the records citing it, or all of them after a shared file, with the count of
the other errors; every hook output stops at 20 lines and names the command that shows the rest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
An alias cycle is now a problem on each of its tokens instead of a stated limit, and a walk
into a cycle from outside it ends. A test now fails without each guard that had none: an
export matched as a whole word, a code root or ignore with a trailing slash, and a length
inside var() left to the token.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
…er check

The record model moves to model.cjs and the literal patterns to literals.cjs, so a check
depends on the model, not on a sibling check. Dead guards go: the payload shape test, a
trim no header needs, the folder test readdir already makes, the validate wrapper nothing
called. Files sort by code unit, the same on every machine; the code tree caches on the
project like the token tree; the script scan reads runs of plain text at once, from 1.37 s
to 0.9 s on a 5,000-file project.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
validate-ui.cjs becomes aidd-ui.cjs, which takes the job as a command, validate for now, so
the generators later pull requests add share its reader instead of copying it. The README
states the new format: implemented-version, publication rows, task folders, verdict versions,
the Resolver profile, code-tokens, severities and what each hook moment prints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
…tten

The change flow belongs to the design system skill, regenerating renders through the engine
and handing review back without naming a skill. The README states what a code root walks,
how loosely a variant and an export are found, and the unquoted plugin root. The foundation
plan points to the spec for the decisions taken after it ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
Comment thread plugins/aidd-ui/hooks/lib/code.cjs Fixed
… patterns

One pattern mixing an unanchored folder branch with an anchored name branch read as a
precedence mistake. A mock folder now has the test that proves it is skipped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XeK3mDvAh1xZvZGAKEVhJn
@blafourcade
blafourcade merged commit a3a3b0b into next Oct 31, 2026
33 checks passed
@blafourcade
blafourcade deleted the feat/aidd-ui-rework branch October 31, 2026 20:11
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