Skip to content

chore(openspec): adopt openspec 1.9.0 and archive completed changes - #1927

Merged
misama-ct merged 1 commit into
mainfrom
openspec-1.9-button-modified-scenario
Aug 18, 2026
Merged

chore(openspec): adopt openspec 1.9.0 and archive completed changes#1927
misama-ct merged 1 commit into
mainfrom
openspec-1.9-button-modified-scenario

Conversation

@misama-ct

Copy link
Copy Markdown
Collaborator

Summary

Adopts @fission-ai/openspec 1.9.0 — the second of the two packages held back in #1926 — and reconciles the change backlog that adopting it exposed.

The openspec validate --all --strict gate now passes for the first time: 120 passed / 0 failed (main is 120 passed / 2 failed).

Why 1.9.0 was blocked

1.9.0 adds a stricter rule: a ## MODIFIED Requirements block replaces the whole requirement, so it must repeat every scenario the current spec still has. It rejected add-button-allow-focus-when-disabled:

✗ MODIFIED "useButton Hook Integration" omits scenario(s) the current spec
  still has: "Disabled state delegation"

This was a rename, not a dropped scenario. The change renamed Disabled state delegationDisabled state delegation (default) and narrowed its WHEN, keeping all three THEN/AND bullets verbatim, then added a sibling for the new focusable-disabled behavior. The validator compares scenario names literally and cannot detect a rename.

Correcting the record: #1926's body described this as "a genuine latent defect" that would "silently drop the scenario." That was wrong — no requirement coverage was ever at risk. The rule is a true positive against the tool's contract, but a false positive against the author's intent.

The fix restores the original scenario name (one line), so the default-path scenario keeps its identity and the new behavior lands as a sibling.

Archiving 17 completed changes

Every change was verified as actually shipped, not trusted from its task checkboxes — each target symbol was confirmed present in the built public type surface (1131 .d.ts files):

Tree · ActivityIndicator · useSlidingIndicator · Breadcrumbs · allowFocusWhenDisabled · ChatMessage · ChatMessageList · DropZone · FileTrigger · Item · Markdown · Region · useResponsiveSplitterSizes · Skeleton · Slider · Splitter

Twelve were already marked complete. Four were marked in-progress but were finished — their open items sit under headings their own authors marked out of scope:

Change Open item Why it doesn't block
add-responsive-splitter-sizes-hook 40/41 11.1 Under ## 11. Tracked separately (not part of this change) — "land as an independent fix". Already implemented (see below).
add-item-component 21/22 9.1 Under ## 9. Figma Code Connect — DEFERRED, blocked on a Figma source existing
add-breadcrumbs-component 33/34 7.3 Accept Chromatic baselines in the Chromatic UI — not a code task
2026-06-08-add-tree-component 28/34 6.1–6.3, 8.1–8.3 §6 is Post-development (follow-up, out of scope for this PR); §8 is Validation (follow-up changes). 8.1/8.2 are satisfied (lint, typecheck, build and tests pass; SubTree/useTree/TreeItem in built types) and 8.3 already shipped — the CHANGELOG documents both, with zero pending changesets. Stale checkboxes.

Nothing was dropped. Every archive reported zero removals (- 0), a diff scan confirms no ### Requirement or #### Scenario line was removed from any tracked spec, and no two changes touched the same spec capability, so there were no ordering hazards.

Archive count: 31 → 48. Active changes: 0.

New requirement: nimbus-splitter → "Layout is applied before paint"

While auditing the leftovers, one turned out to be a genuine spec gap rather than pending work. Splitter already guarantees the configured size is applied before the first paint, and splitter.reconcile-timing.spec.tsx is a dedicated "Regression guard for the first-paint 50/50 flash." The spec never said so — Initial size from defaultSize promised the size would be applied but not when, and the controlled size requirement was silent on timing.

Reading the code and test showed the guarantee has two mechanisms the original task text didn't separate:

  1. initial layout seeded synchronously during render via useState(initialDisplay), not adopted in a mount effect;
  2. controlled size changes reconciled in a layout effect, so they land in the same commit.

Both are now specified, with scenarios for the uncontrolled, controlled and collapsed-on-mount seeds plus the same-commit reconcile. Timing that is implemented and regression-tested but unspecified is free to be refactored away; this protects it.

It is an ADDED requirement rather than MODIFIED because the guarantee spans both the controlled and uncontrolled paths — MODIFIED would have meant re-transcribing 10 scenarios across two requirements, risking exactly the scenario loss the 1.9.0 rule exists to prevent, and duplicating the clause in two places.

No runtime code changed, so no changeset is required.

Removing two empty change directories

add-menubar-component and add-sidebar-component contained zero files. Git cannot track empty directories, so they failed openspec validate in local checkouts while being invisible to git status — which is why this gate was red on main and green in CI.

On Figma Code Connect

Two archived changes carry deferred Figma Code Connect items. Nothing was changed for them, because there is nothing to change:

  • openspec/specs/tree/spec.md contains no Figma requirement.
  • .figma.tsx appears only in the nimbus-code-connect skill (a generator), not in CLAUDE.md, docs/, .claude/commands/, or the component templates.
  • 46 of 89 components have Code Connect — it is already opt-in where a Figma source exists.

If it should ever be specified without being forced upfront, nimbus-chat-message has the pattern: a conditional scenario — "WHEN the component is mapped in Figma → THEN SHALL provide a Code Connect mapping."

Testing

Every gate from .github/workflows/build-and-test.yml, run on the final rebased tree:

Gate Result
pnpm build (full, incl. docs) ✅ pass
pnpm openspec validate --all --strict 120 passed / 0 failed (main: 120 / 2)
pnpm lint ✅ pass
pnpm typecheck:strict ✅ pass
pnpm check:package-shape ✅ pass (attw + publint)
pnpm test 3225 / 3225 tests, 250 / 250 files

⚠️ Unrelated pre-existing flaky test (found while verifying this PR)

One verification run of this branch failed 2 tests in confirmation-dialog.stories.tsx (Destructive Intent, Async Confirm); an immediate re-run of the identical tree passed 3225/3225. This is a pre-existing flake on main, not caused by this PR — nothing here touches runtime code, and it reproduces with axe-core 4.12.1, the version main already ships.

It also corrects the diagnosis in #1926, which attributed this failure to axe-core 4.13.0. That was wrong. The root cause is a design-token contrast shortfall that both axe versions detect:

  • Button's default variant is subtle: bg: colorPalette.3, color: colorPalette.11, _hover: { bg: colorPalette.4 }.
  • The story clicks the colorPalette="critical" trigger, so the pointer stays over it and the a11y afterEach measures the hover background.
  • critical.11 #ce2c31 on critical.4 #ffdbdc = 57.96Lc, against the repo's own 60Lc threshold. The base state (critical.3 #feebec) measures 64.89Lc and passes — which is exactly why the test only fails when hover happens to still be active.

Sweeping every solid palette for the subtle hover pair (.11 on .4) shows this is systemic rather than critical-only — 8 of 27 fail:

Palette Lc Palette Lc
orange 54.28 pink 59.13
tomato 56.73 crimson 59.43
red (= critical) 57.96 ruby 59.66
teal 59.13 jade 59.91

(*Alpha palettes are excluded — they are transparent, so APCA against a nominal hex is not meaningful for them.)

This needs a design decision — nudge colorPalette.11 darker, lighten colorPalette.4, or revisit the 60Lc threshold — so it is deliberately not addressed here. Two consequences worth noting: axe-core did not actually need holding back in #1926, and adopting 4.13.0 will likely make this flake fire more often, so the token fix should land first.

Review notes

The diff is large but almost entirely mechanical: 75 file moves into openspec/changes/archive/, 17 new capability specs under openspec/specs/, and two one-line edits to pnpm-workspace.yaml/pnpm-lock.yaml.

The three parts worth actual review are small:

  1. the restored scenario name in the button change's delta,
  2. the new Layout is applied before paint requirement,
  3. the judgement that the four in-progress changes were finished — the table above shows the evidence for each.

Adopt @fission-ai/openspec 1.9.0, held back in #1926, and reconcile the
change backlog that adopting it exposed.

1.9.0 adds a stricter MODIFIED-requirement rule: a MODIFIED block replaces
the whole requirement, so it must repeat every scenario the current spec
still has. It rejected add-button-allow-focus-when-disabled, whose block
renamed "Disabled state delegation" to "... (default)". That rename kept all
three THEN/AND bullets verbatim, but the validator compares scenario names
literally and cannot detect a rename, so the original name is restored.

Archive 17 changes. Each was verified as actually shipped rather than trusted
from its task checkboxes: every target symbol was confirmed present in the
built public type surface (Tree, ActivityIndicator, useSlidingIndicator,
Breadcrumbs, allowFocusWhenDisabled, ChatMessage, ChatMessageList, DropZone,
FileTrigger, Item, Markdown, Region, useResponsiveSplitterSizes, Skeleton,
Slider, Splitter).

Four were marked in-progress but were complete. Their remaining items sit
under headings their own authors marked out of scope: Figma Code Connect
deferred until a design source exists, Chromatic baseline acceptance done
out-of-band in the Chromatic UI, and a splitter fix explicitly "tracked
separately". The tree change's validation checkboxes were simply stale --
lint, typecheck, build and tests all pass, and its changeset had already
shipped in the published CHANGELOG.

No requirement or scenario was dropped anywhere: every archive reported zero
removals, and no two changes touched the same spec capability, so there were
no ordering hazards.

Also add a nimbus-splitter requirement, "Layout is applied before paint",
recording a guarantee that was implemented and regression-tested but never
specified: the initial layout is seeded synchronously during render, and a
controlled `size` change is reconciled in a layout effect, so no frame is
ever painted at the 50/50 fallback. It is its own requirement rather than a
clause duplicated into the controlled and uncontrolled requirements, both of
which it spans.

Remove two empty, untracked change directories (add-menubar-component,
add-sidebar-component). Git cannot track empty directories, so they failed
`openspec validate` locally while being invisible in git status.

The openspec gate now passes for the first time: 120 passed, 0 failed
(main was 120 passed, 2 failed).
@misama-ct
misama-ct requested a review from a team as a code owner August 17, 2026 08:52
@changeset-bot

changeset-bot Bot commented Aug 17, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 40cf5f2

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel

vercel Bot commented Aug 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
nimbus-documentation Ready Ready Preview Aug 17, 2026 8:55am
nimbus-storybook Ready Ready Preview Aug 17, 2026 8:55am

Request Review

@github-actions

Copy link
Copy Markdown
Contributor

Bundle Size Report

Last updated: 2026-08-17 08:54:51 UTC

Package Format Current Baseline Delta Status
@commercetools/nimbus dist 18950.9 KB 18950.9 KB -0.0% ✅ ok
@commercetools/nimbus-icons dist 4787.6 KB 4787.6 KB +0.0% ✅ ok
@commercetools/nimbus-tokens dist 408.9 KB 408.9 KB +0.0% ✅ ok

Baseline source: comment-chain

@chromatic-com

chromatic-com Bot commented Aug 17, 2026

Copy link
Copy Markdown

Tip

All tests passed and all changes approved!

🟢 UI Tests: 1207 tests unchanged
🟢 UI Review: 1207 stories published -- no changes
Storybook icon Storybook Publish: 1207 stories published

@misama-ct
misama-ct merged commit 8362fbf into main Aug 18, 2026
14 checks passed
@misama-ct
misama-ct deleted the openspec-1.9-button-modified-scenario branch August 18, 2026 06:58
@github-actions github-actions Bot added the bundle-sizes Housekeeping for merged PRs - allows the fetch sizes script to find the latest bundle check comment. label Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bundle-sizes Housekeeping for merged PRs - allows the fetch sizes script to find the latest bundle check comment.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants