Agent docs

Kit changelog

What each release adds, what changes on screens an app already has, and what an app can delete once it takes it.

What each release adds, what changes on the screens an app already has, and what an app can delete once it takes the release (the Retires line). Written for the person or agent moving a pin; the upgrade procedure is the "Upgrading an app's pin" section of README.md beside this file. Older releases are reconstructed from the kit's commit log; a release with no Retires line retires nothing an app is known to carry. A change that came out of a consumer's CANON-NOTES.md entry cites it as From the notes: <repo> <date>, which is the loop's closure (docs/canon/NOTEBOOK.md).

Unreleased (on main after 0.2.2; ships with the owner's next bump)#

  • Consumer enablement: the package now carries its method and answers its own questions. USAGE.md is the six-step front door (agent path first, fetchable raw from the repo); method/ holds verbatim copies of the design canon, the app-patterns recipes and the do-nots aggregate, synced by scripts/sync-method-docs.mjs; docs/KIT-INVENTORY.md and docs/llms.txt are the derived inventory of every component and pattern page, with the admission rules that place a new one; a second bin, kit-inventory, answers --find <term> from inside a consumer against exactly what that consumer's tree resolves, stamping the installed version and saying pin drift and symlink trees out loud; and prompts/claims.md is a brief a consumer's own agent runs over their app for claims that stopped being true. Nothing here runs in anyone's CI or blocks any build outside this repo. docs/patterns.md stops hand-keeping its catalog and points at the inventory.

  • PageSkeleton: the Suspense fallback promoted under D7 (doc 44), which ruled that "Skeleton + panel can be a wrapper around the unitary components". Two page shapes, list (toolbar over table rows) and cards (stacked cards at measured px heights), composing Card and Skeleton. Takes the page's OWN container class rather than shipping a container map, so one map decides the box on both sides; layout is required with no default because a default is a guess about a page nobody looked at. header accepts the page's real header element so the top does not redraw when data lands, headroom holds open chrome the placeholder does not draw. Retires, once an app takes this release: nothing outright. Speedway's WorkspaceSkeleton body is replaceable by this, but its PANEL map is speedway's own layout classes and stays local (per the Retires-line rule: name only what fully dies).

  • Input: a string top now becomes the field's accessible name. top renders outside the <label> that wraps the control, so until now every field built with top="Email" reached a screen reader or a password manager unnamed; the contract doc carried this as a known defect. Reported from the forge console, which measured it in the DOM. Not an htmlFor/id pairing, because the file stays hook-free and server-renderable. A caller's own aria-label or aria-labelledby still wins. Screens change only for assistive tech; nothing moves visually. Still yours to name: a placeholder-only field, and a ReactNode top.

  • Alert: the neutral tone gets its own --neutral-soft surface token instead of bg-base-200. On any page or AppShell frame, both of which are base-200, a neutral alert was the same colour as what it sat on and only its border separated it. The new token sits at the tinted softs' elevation in each theme, above both the page and the card in dark. This visibly changes every neutral Alert in every app that takes the release, which is the point, but look at yours.

  • SidePanel: closing returns focus to whatever opened the panel, but only when focus is still inside the panel at close time. A keyboard user closing via the X or ESC lands back on their trigger instead of losing focus to a hidden element; a pointer user whose focus already moved on is never yanked back, because the panel is a non-modal inspector rather than an overlay. Modal needs none of this: a native <dialog> restores focus itself. Screens change only for keyboard and assistive-tech users; nothing moves visually.

  • Breadcrumbs: deriveCrumbs, the path-to-crumbs seam the items prop always assumed and nobody shipped. An app declares its rules once (static labels, page-less segments, a dropped pair, namers for dynamic values, a hide predicate) and the walk is derived from location.pathname, router-free. Distilled from speedway's ShellCrumbs, whose SEGMENT_LABEL/NO_PAGE/TAB_CRUMBS/HIDDEN tables were the hand-roll this replaces; at the pin move that file shrinks to its rules feeding Breadcrumbs presets="trail" (the ?tab= crumb stays caller-appended). One deliberate divergence from the hand-roll: the last derived crumb never carries an href, per this kit's own Banned rule that the current page does not link to itself. Retires, once an app takes this release: the walking half of speedway's ShellCrumbs.tsx; its rule tables stay local by design.

  • InputContainer: disabled and readOnly now reach the frame. Both props were declared and documented as driving the muted surface, and neither was ever read, so a container wrapping a caller's own control stayed in its resting state no matter what the caller passed. The theme has carried .field-disabled and .field-readonly for exactly this case all along: the :has(input:read-only) selectors beside them only match a native input or textarea, so a select, a combobox, or any custom control fell through both paths. Screens change where an app passes either prop to InputContainer; a plain Input is unaffected, since its state reaches the DOM element and the :has() rules already saw it.

  • Button: the split button's caret gets an accessible name. Passing dropdown renders a second button holding nothing but a chevron, and it sat outside the name ladder the file already runs for icon-only buttons, so a screen reader announced it as "button" with no indication of what menu it opens. It now borrows the main action's words when they are a plain string ("More Export options") and falls back to "More actions" otherwise, plus aria-haspopup="menu". Screens change only for assistive tech; nothing moves visually.

  • canon-check now actually ships. package.json declared bin.canon-check while files omitted bin, so every tarball through 0.2.2 shipped no bin/ directory and npx canon-check resolved to nothing. Five places told consumers to use it, including the app template's own npm script. It went unnoticed because pr-claude fetches the raw file from versable-builder@main rather than from the package.

  • Stepper: the horizontal pipeline strip promoted under D7 (doc 44) from three hand-builds (speedway WorkflowStageChain's band, walmart PipelineStepper and the Jobs-row chain). Status circles (pending number, active ping honouring reduced motion, complete check, blocked pause), completion-keyed connectors, Kicker labels, a quiet detail or amber warn line, optional onStep buttons with disabledReason as the polite refusal, aria-label required, sizes sm/md. Retires, once an app takes this release: walmart's PipelineStepper.tsx and the Jobs-row chain's strip markup; speedway's WorkflowStageChain stepper BAND only, the file's banner and stage list stay local (per the Retires-line rule: name what fully dies).

  • Tint-ladder audit: 230 off-ladder opacity suffixes across the kit and playground moved onto their ladder rungs by role (pnpm lint:tokens 245 to 15 warnings; the 15 are named deliberate one-offs in .claude/output/20260820-tint-audit/report.md awaiting either a rung or an owner ruling). Verified in both themes on the app-shell, card and admin surfaces.

  • canon-check hardened against its own adversarial gate (14 dodges found, .claude/output/20260820-canon-gate/report.md): the seam now requires an ADDED dated note line, not a touched file; non-ASCII and spaced paths are inspected instead of silently skipped; theme modules, style preprocessor files, .mdx and the tailwind/postcss/next config files owe notes; a deleted or unreadable UI file is a finding, never silence; the overrule reason must read as a sentence and a fenced one does not count; inspectors match a two-line window (Prettier-formatted JSX), em-dash entities, and re-exported kit names.

0.2.2 (2026-08-20)#

  • canon-check, a package bin (bin/canon-check.mjs with the inspectors in bin/canon-classes.mjs): the canon feedback loop's fail-closed seam. A change that touches UI paths must add a line to the repo's CANON-NOTES.md or carry a human canon-note: none because <reason> line in the PR body; the lines it added are read for the deviation classes nobody writes a note about (raw controls beside a kit import, react-icons at a call site, arbitrary pixel sizes, colour and font literals, a kit component restyled through className, a local export shadowing a kit export, em dashes, loading text), each finding citing the canon paragraph. Marked deviations (// canon: <reason>) are notes. Plan: docs/plan/71-canon-feedback-loop-plan.md.

0.2.1 (2026-08-20)#

  • Theme: --font-mono puts Menlo ahead of ui-monospace, so an app that loads JetBrains Mono as a Google subset (no box-drawing glyphs) still draws ASCII diagrams with lines that meet; SF Mono's box characters are wider than the face's letters.

  • Sidebar/AppShell take navGrouping: flat (default, nothing changes) or railed, the group kicker at the idiom's quiet weight with rows one step in behind a hairline rail, for a long column (canon 08 §A10); the group holding the current page opens on arrival and can be closed again.

  • Markdown: links read in the primary ink and underline on hover; a link whose text is inline code keeps the chip, underlined at rest, and the chip takes the primary tint on hover.

  • Card takes iconVariant (disc, default, darkens a rung under the pointer; plain, bare at rest, the disc arrives on hover) and iconTone (a theme tone for icon and disc), every wash a rung of the tint ladder (canon 01 §A8).

  • Card takes the standard icon prop group: Icon renders left of the title in PageTitle's disc one size down, standard header meta for a section card; iconWrapClassName slot. NavGroup takes Icon, a mark beside the kicker, so a docs column and its index cards share one icon per section (owner, 2026-08-19, doc 69 D4, D7).

  • Sidebar/AppShell nav: a NavGroup takes groups (sub-groups under its rows, each with a smaller kicker and caret, one level) and defaultCollapsed (start closed; a long sidebar opens only the group the reader is in). Asked for by the playground's patterns and docs columns (owner, 2026-08-19); docs/app-shell.md.

  • SchemaForm polish (owner round R10, doc 67): the kit's RequiredMark (a red asterisk with a "Required" tooltip, now exported) replaces the required dot at every label site, labelTone="soft" for a quieter label; a warned control carries the warning edge and every coloured edge darkens a step on hover; segmented and radio groups use borders instead of outlines, an unselected segment showing the light primary edge; options read as sentences and take icons, swatches, trailing text and descriptions through x-option-meta (or straight from resolveOptions), a checklist can stack its descriptions with x-option-layout: stacked; Input md reads 14px at 40px like Select and Button (D3a). Spec 65 sections 6.2 and 7.1, canon 13 and canon 01 §A8 (the tint ladder) follow.

  • Select options take trailing (a right-side helper) and swatch (a colour dot on the row and beside the selected value, and the row's own hover tint); warning prop for the warning edge.

  • CodePill: a status pill for a module's own codes, reading label and description from the map its manifest declares (error_types, review_reasons); an undeclared code shows as typed in mono. Asked for by the forge console (gcp-opus).

  • SchemaForm and lintSchema: a form rendered from a JSON Schema in the kit's subset (docs/schema-form.md), with one field anatomy, type-derived widths, sections, x-when and x-tier, options from context or a resolver, tables and lists with their row lifecycle, mode choosers over a discriminated oneOf, colour, file and prompt widgets, plain-sentence validation, review and snapshot modes, presets with dirty tracking, a shape-matched loading skeleton, and refusal by name for anything outside the subset. Select gained an id prop. The canon is docs/design-language/13-forms-and-fields.md, the recipe docs/app-patterns/16-recipe-module-settings-form.md. Retires: every hand-built module settings form in the console once it adopts the schemas; walmart's and speedway's per-module parameter panels are the evidence, not consumers, until their own bump.

  • Timestamp and its formatters pin the locale (DEFAULT_LOCALE, en-US) instead of reading the runtime's, so a server-rendered app no longer risks a hydration mismatch when server and browser locales differ; locale prop to change it deliberately. formatCompactDateTime and DEFAULT_LOCALE are exported from the barrel. Retires: speedway's app/lib/datetime.ts locale pin, once it upgrades.

Added: Breadcrumbs (presets trail for a page trail, topbar for a topbar crumb, promoted from speedway's ShellCrumbs and walmart's topbar shape) · Markdown (a stored doc rendered with kit parts, raw HTML sanitized) · Kicker (default and bricked) · Input presets (email, password, search, url, numeric) and a unit adornment · WorkspaceSwitcher items with disabled, disabledReason and loading · CodeBlock colours bash command lines and gains a size prop · icon keys InputSearch, InputSpark, InputForm · the rich Tooltip (title, body, footer) as the standard for icon-only actions · Progress animates value changes · Chip click feedback on every type · PageTitle icon stagger and a phone-size title floor.

Changed on existing screens: sidebar groups collapse by default with an index row above them (opt out with collapsible: false, docs/app-shell.md) · Alert centres its icon and flows its body inline, border at /18 · Dropzone shows its error below the row · CodeBlock collapses its header on untitled fences · kicker and stat-hint ink at /65 · the topbar search is centred.

Kit-internal, no API change: the table module is exported by name from src/index.ts (the barrel is the inventory again); a render smoke suite and pnpm test exist.

Retires, once an app takes this release: speedway app/components/ShellCrumbs.tsx (use Breadcrumbs preset trail); any hand-rolled workspace picker in either app (speedway's local WorkspaceSwitcher.tsx already has no importers).

0.2.0 (2026-08-16)#

Added: Select gains a multiple mode (chips, the property word on the closed control) · FacetBar composes it and retires its private multi control · PageTitle, StatTile and Alert enter with fadeInUp (noAnimate opts out) · CodeBlock colours bash, python, yaml, html, csv, jsonc plus the ts and jsx aliases · Modal header and footer borders as independent options.

Changed on existing screens: the neutral shade tint is lighter kit-wide (8/14 from 12/20) · solid warning ink is white on amber-600, soft warning keeps amber ink · a Select multiple panel sizes to content, so a FacetBar menu loses its fixed w-60 box · the three components above animate in unless told not to.

Retires: walmart's local Radix multi-select and the hand-rolled MultiFacetControl in FacetToolbar.tsx (the kit's Select multiple and FacetBar cover both; docs/GUIDEBOOK.md section 7, row 20).

0.1.0 (2026-08-16)#

The batch-1 supersets as the first minor. Added: FacetBar (the union of both product toolbars) · col.link (the navigating cell that keeps its tooltip) · ListState (the four-way list branch) · TableSkeleton preset promoted from walmart's four-page shape · Chip presets · EmptyState forwards tone · CodeBlock learns tsx · useDebounce defaults to the canon's 300ms.

Changed on existing screens: dark neutral becomes a raised dark gray with ink remapped · Modal loses the phantom right gutter and trims footer spacing · InlineEdit keeps its content-sized box in column-flex parents · PageLoading drops trailing ellipses · toolbar coherence (one control skin, one menu anatomy) · FacetBar chips take the lg frame and the property prefix.

Retires: walmart's local TableSkeleton (adopted 2026-08); any hand-rolled EmptyState tone wrapper; walmart's .modal-box { scrollbar-gutter: auto } override (frontend/src/index.css:112-114), because the kit stopped reserving the gutter in 6ff8ac3.

0.0.14 to 0.0.25 (2026-07-16 to 2026-08-11)#

Twelve patch releases while both apps were under active development; each app moved its pin the same day a release landed. Not reconstructed here. To see one: git log <previous bump>..<bump> -- packages/ui/src, where the bump commits are git log --format='%h %s' -L '/"version"/,+1:packages/ui/package.json'. 0.0.25 (2026-08-11) carried "the six fixes" walmart's tech-debt review asked for and is the version walmart's README once told adopters to wait for.

@versable-git/ui · reference, canon, and method, read in place