Skip to content

fix: harden 0.2 for existing 0.1 consumers (layer order, CLI package, upgrade gaps) - #54

Merged
yomybaby merged 27 commits into
feat/astryx-foundationfrom
feat/consumer-hardening
Oct 2, 2026
Merged

yomybaby merged 27 commits into
feat/astryx-foundationfrom
feat/consumer-hardening

Conversation

@yomybaby

Copy link
Copy Markdown
Member

Stacked on #53. Fixes found by applying ui-common upgrade --from 0.1 to the six 0.1 consumers (backend.ai-go, continuum-hub, mlxcel, mlxcel-internal, ui-ai, ui-charts) with a packed 0.2.0-alpha.14.

Summary

  • Cascade layer order (blocker). Component stylesheets opened @layer ui-common{…} before the app's order statement loaded, so ui-common became the lowest layer and Astryx base/theme beat ui-common composites (StatCard overflow: hidden lost to Card's clip). Every shipped stylesheet now opens with the full order statement from scripts/layer-order.mjs; check:pack and the fixture check gate it (the fixture check fails on the old build). Confirmed in headless Chromium.
  • CLI split into @lablup/ui-common-cli (packages/cli, lockstep version), the way Astryx ships @astryxdesign/cli beside core. The library loses bin, @astryxdesign/cli, jscodeshift and postcss: prod install of a library-only app 196 MB / 132 pkgs → 31 MB / 25. CLI engines is >=22.13.0 (what @astryxdesign/cli needs). check:pack validates both tarballs.
  • Publishing: both packages in lockstep; any prerelease goes to next, so 0.1's alpha tag is not moved.
  • CI: fixture installs with pnpm and carries the allowBuilds snippet consumers need (pnpm 11 fails with ERR_PNPM_IGNORED_BUILDS otherwise), then runs the CLI end to end.
  • Dev-only duplicate-copy warning (src/instance.ts), stripped in production.
  • Upgrade codemod: follows the project's own barrels (tsconfig paths) and lists wrappers for review; no more unparseable output on removed-type re-exports; wires the 0.2 stylesheets when the app never imported base.css, before ui-common imports; inserts <Theme> at a single clear root and reports 0.1 theme switches; searches tests/e2e/scripts for findings (--scan); drops React 18 from library peers; adds allowBuilds and the CLI devDependency; lower-confidence section for class names the project owns.
  • Docs: README setup (allowBuilds, layer statement, <Theme> requirement and dark mode, Vitest server.deps.inline), integration Theme path, CHANGELOG Upgrading from 0.1 + link refs.

Effect on a real consumer (continuum-hub)

before after
files changed by upgrade 21 (3 refused as unparseable) 257
tsc errors after upgrade 1,902 1,796

What remains is mostly call sites of the app's own wrapper components (9 wrappers, listed in the report), deliberately not rewritten.

Consumer-side follow-ups

  • backend.ai-webui's counterpart branch must add @lablup/ui-common-cli (tarball) as a devDependency where it runs pnpm exec ui-common.
  • ui-ai / ui-charts ship 0.1.0-alpha.6 with ui-common as a regular 0.1 dependency (lablup/ui-ai#9, lablup/ui-charts#15), so apps can move to 0.2 before those libraries do.

Verification

pnpm run verify: 76 files, 1390 passed / 2 skipped; check:pack clean for both packages; integration check ok.

Not verified: a registry pnpm dlx @lablup/ui-common-cli run and the publish workflow itself (need a real release); the v0.2.0-alpha.* CHANGELOG link refs resolve only once those tags exist.

…package

@lablup/ui-common carried the ui-common bin, its codemods and the
migration map, and with them @astryxdesign/cli, jscodeshift, postcss and
postcss-selector-parser as production dependencies: about 168 MB of a
dev-time toolchain in every consumer's production install.

The CLI now lives in packages/cli as @lablup/ui-common-cli, the way
Astryx splits @astryxdesign/core from @astryxdesign/cli: one repository,
two packages at one version. The CLI takes @lablup/ui-common as a peer
(workspace:*, published as the exact version). The repository root stays
the library; it keeps @astryxdesign/cli as a devDependency for its own
theme and integration scripts.

cli/paths.mjs no longer treats one directory as both the CLI and the
library it reads. The CLI root resolves the Astryx CLI and jscodeshift;
the ui-common root, found from the project first and then from the
CLI's peer, supplies the version, the export lists and the Astryx
packages it pins. upgrade reads its target's pins from the CLI's peer,
since the project may still be on the version it upgrades from.
sync-astryx finds the repository from anywhere under it and moves the
Astryx CLI pin in both package.json files.

The CLI tests move beside the package and still run under the root
vitest run.
0.1 shipped the ui-common bin inside @lablup/ui-common; from 0.2 it is
@lablup/ui-common-cli. The 0.1 -> 0.2 package.json codemod now adds it
to devDependencies at exactly the target version, or pins an existing
entry there, so pnpm exec ui-common keeps working after the upgrade.

The help, the upgrade report header and the agent block name the new
entry points: pnpm dlx @lablup/ui-common-cli upgrade --from 0.1 (or npx)
for a one-off run, and pnpm exec ui-common with the CLI installed as a
devDependency beside ui-common.
check:pack now packs the library and the CLI with pnpm, the way they are
published, and reads the packed manifests. The library tarball must not
contain bin/, cli/, codemods/ or migration/, declare a bin, or depend on
the CLI toolchain. The CLI tarball must contain its bin, modules and
migration map and nothing of dist/, sit at the library's version with an
exact @lablup/ui-common peer (no workspace: range left), and every import
in it must resolve to a packed file or a declared dependency.
Both jobs check that the two packages share one version and, on a
release, that it matches the tag. pnpm packs both, which rewrites the
CLI's workspace:* peer to the exact version; npm then publishes the
library tarball first and the CLI second, to each registry, keeping
provenance on npmjs and the dry-run path on workflow_dispatch.

Any prerelease now publishes under the next dist-tag and a plain version
under latest. 0.2's alphas were approved for next, so the alpha tag
0.1 used is no longer moved.
The external-install job installed the packed tarball with npm, which
never reports a dependency's unapproved build script. Every consumer
installs with pnpm 11, which fails with ERR_PNPM_IGNORED_BUILDS on
Astryx's postinstall. The fixture now installs with pnpm as its own
workspace, and fixture/pnpm-workspace.yaml carries the allowBuilds
block a consumer needs for @astryxdesign/core and @astryxdesign/cli.

It also installs the @lablup/ui-common-cli tarball as a devDependency
and runs the bin from there: --version, --help, agents, a passed-through
component lookup and an upgrade dry run.
README's CLI and 0.1-upgrade sections now name the new entry points: a
one-off pnpm dlx @lablup/ui-common-cli upgrade --from 0.1 (or npx), and
pnpm exec ui-common with the CLI as a devDependency pinned to the
library's version, plus the allowBuilds block pnpm 11 needs. CONTRIBUTING
and docs/astryx.md follow the moved paths under packages/cli.
The disclosure scan now covers what @lablup/ui-common-cli publishes: its
README and NOTICE and its bin, cli, codemods and migration sources, which
ship as written. ui-common-cli joins the allowlist as this repository's
own package, and a period that ends a sentence after an allowed name no
longer counts as part of the name.
A module that re-exports a 0.1 type through its own import
(import type { X } from "…/DataTable"; export type { X };) lost the
import but kept the export, so the output named an undefined binding and
the file was refused as unparseable, leaving it unmigrated.

The re-export now goes with the import, the same way a re-export straight
from @lablup/ui-common already does, with a TODO on the export (or where it
stood) telling importers they need a type of their own. No placeholder
alias is declared: an `unknown` type would keep every importer compiling
against a type that no longer exists.
…rrels

A consumer that re-exports ui-common components from a module of its own
(export { Button } from "@lablup/ui-common/components/Button", export *,
or an import then export { … }) had the barrel rewritten under the 0.1
names while every module importing from it kept passing 0.1 props.

The codemod now reads the project's modules as they were before the run,
resolving relative imports and tsconfig paths/baseUrl, and follows
re-exports through barrels. An element of a component imported that way
gets the same rewrite as a direct import; the import itself stays, since
the barrel keeps the 0.1 name. A removed type imported or re-exported
through a barrel goes, as it does from ui-common. An import left unused
once every element became another component (BaseCard -> ClickableCard) is
removed.

A component of the project's own that wraps a 0.1 one and takes its props
(its props type is built on the 0.1 props type, or it spreads its props
into the element) is not a re-export: its call sites are left alone and
the report lists it under "Local wrappers around 0.1 components", with
how many scanned modules import it. Imports through aliases the upgrade
cannot resolve (bundler aliases) are named in the report's notes.

Also fixes two cases the new fixture exposed: `import { StatusTag } …;
export { StatusTag };` lost its public name on the rename, and a
re-export of only removed types from ui-common was kept, pointing at a
subpath 0.2 no longer has. A module the codemod empties keeps its TODOs
on an `export {};`.
The report only scanned src/ (or the paths given), so it missed the
places a 0.1 consumer names 0.1 classes and stylesheet paths outside it:
Playwright specs under tests/ and e2e/, and scripts that check the orange
theme sheets.

The codemods still run over src/ (or paths), but the finding scan now
reads the whole project: git's file list where there is one (so ignored
files are skipped), without node_modules, build output and tool state,
bundles, files over 512 KiB, and packages nested in the project. Those
files are read, never written. --scan <path> (repeatable) narrows it.

The test-query and DOM-hook scans also recognise Playwright's locator(),
waitForSelector() and $/$$/$eval, and Cypress's cy.get()/cy.find().
Generic 0.1 names (.button, .select, .tabs__tab) are often a project's
own classes, and a project that vendored its components before ui-common
existed has hundreds of findings on them, burying the ones that matter.

A class the project both defines in its own stylesheets as a rule of its
own (.tabs__tab { … }) and renders in its own markup (className=
"tabs__tab", outside tests) now moves its CSS-selector, DOM-hook and
test-query findings to a separate "your own CSS also defines (lower
confidence)" section, tagged with where each came from. A definition
alone does not count: an override of ui-common's class looks the same.
… base.css

A 0.1 app could rely on each component importing its own CSS and never
import styles/base.css. 0.2 components load no CSS, so after the upgrade
nothing loaded Astryx's stylesheets or the theme, and the report said
nothing about it.

When no file of the project loads @lablup/ui-common's stylesheets, the
upgrade now writes the same ui-common-entry.css the base.css rewrite
writes, beside the app's entry script (the module script index.html
loads, else package.json main, else src/main.* / src/index.*), and
imports it there. Libraries are left alone. With no entry to be found,
the report opens with an "Action required" section giving the
stylesheet set to load.

The entry import, added or rewritten from base.css, now goes before every
import that loads styles: stylesheets, @lablup/ui-common modules and the
app's own modules. It used to land wherever base.css had been, after
them, so the @layer order statement came too late to fix the cascade.
…itches

0.2 needs the app wrapped in <Theme theme={lablupTheme}>, and <Theme> owns
html[data-theme], setting it to light or dark. The upgrade never added
the wrapper nor said it was missing, and did not flag 0.1 theme switching:
dataset.theme = "orange-dark", setAttribute("data-theme", …) and
[data-theme="orange-…"] selectors.

When no module of an app uses <Theme>, the upgrade now wraps its root
render, createRoot(…).render(<X />), in it (inside StrictMode when that
is the root) and imports Theme and lablupTheme, as text edits that keep
the file's formatting. The root is the one module that renders one, or,
among several, the entry index.html loads; the others are named in the
report. Otherwise, or when those names are taken, the report opens with
the step under "Action required". Libraries are left alone.

A new report section lists data-theme writes other than "light"/"dark"
literals, the 0.1 theme names in scripts, and selectors on any other
data-theme value (one row per value and stylesheet, comments skipped),
with the 0.2 replacement.
A library that takes ui-common as a peer had its ui-common peer bumped to
0.2 but kept react/react-dom at "^18.2.0 || ^19.0.0", so it still
claimed to install into a React 18 app, where 0.2 cannot run.

The upgrade now removes the alternatives of those peer ranges that accept
React below 19 ("^18.2.0 || ^19.0.0" -> "^19.0.0"), falling back to
the target ui-common's own React peer when none is left, and says so in
the report. A project whose own react / react-dom dependency is below 19
gets a note to upgrade React too.
…lowBuilds

pnpm 11 stops an install (ERR_PNPM_IGNORED_BUILDS) until every dependency
with a postinstall is allowed or declined, and the upgrade adds two:
@astryxdesign/core (through ui-common) and @astryxdesign/cli (through
@lablup/ui-common-cli). A consumer's first install after the upgrade
failed, and pnpm left 'set this to true or false' placeholders behind.

In a pnpm project the upgrade now adds "@astryxdesign/core": false and
"@astryxdesign/cli": false to allowBuilds in the pnpm-workspace.yaml it
already edits for lab's override (created when missing), the same block
fixture/ carries. Existing entries set to true or false are kept; any
other value, pnpm's placeholder included, counts as undecided and is set
to false. Comments and other lines are left as they are.
Each component module imports its own stylesheet, and each of those opens
@layer ui-common{...}. A consumer imports ui-common's modules before its
entry stylesheet with the order statement, and a layer's position is fixed
by first appearance, so ui-common became the lowest layer and Astryx's
base and theme rules beat its composites (the fixture bundle opened with
@layer ui-common{.uic-skeleton-shape...}; StatCard's overflow:hidden lost
to Card's overflow:clip).

scripts/layer-order.mjs now defines the order once, and the build prepends
the statement to every stylesheet in dist: the emitted component sheets,
ui-common.css, legacy-tokens.css, the deprecated styles/, the pre-built
Lablup theme and the one-line Astryx @import mirrors (a layer statement
may precede @import). Repeating an identical statement is a no-op.

check-pack fails on a packed stylesheet without the statement, and the
fixture check reads the layer order the consumer bundle establishes (the
statement text itself does not survive Lightning CSS minification, which
folds it into the following blocks).
Two copies of @lablup/ui-common split module state (the modal stack) and,
when each brings its own @astryxdesign/core, Astryx's Theme, i18n and
layer contexts. Nothing fails; components quietly stop seeing the
providers the app rendered.

Each copy now records {version, astryxVersion, url, astryxIdentity} under
globalThis[Symbol.for("@lablup/ui-common/instance")], and the first copy
to find another there warns once, naming each copy and saying whether they
also run on separate Astryx cores (compared by the identity of core's
InternationalizationContext).

Registration runs on first use of the string translator and the modal
stack rather than at module scope: the package declares its JS modules
side-effect free, and rolldown drops a module-scope call from such a
module even in development. It sits behind process.env.NODE_ENV !==
"production", as Astryx's own dev warnings do, so production bundles
drop it. The version comes from package.json through a build-time define.

A second Astryx core that ui-common does not import itself (lab resolving
its own core without the override) is not detectable this way: core has
no global registration and lab exposes no handle on its core.
The agent docs and the ui-common doc page told agents to take lablupTheme
from @lablup/ui-common/theme/lablup, the theme as source, which Theme
injects at runtime. The setup they sit beside imports theme.css, whose
pair is theme/lablup/built; the source form next to theme.css registers
the same theme twice. README and the ui-common agents block already say
/built.
…d Vitest setup

- pnpm 10 and later: decline Astryx's postinstall scripts under
  allowBuilds, or pnpm 11 fails with ERR_PNPM_IGNORED_BUILDS (pnpm 10
  warns).
- Every shipped stylesheet now opens with the layer order statement;
  keep declaring it in the entry stylesheet too.
- <Theme theme={lablupTheme}> is required: theme.css is scoped to
  [data-astryx-theme="lablup"], so without it the app silently renders
  Astryx's default palette. Dark mode is <Theme mode>; the root Theme
  owns html[data-theme], so 0.1-style data-theme="orange-dark" toggles
  no longer work.
- Vitest with jsdom needs server.deps.inline for @lablup/ui-common,
  since its modules import CSS.
- The development warning for a second copy.
- [Unreleased]: the layer order fix, the duplicate-copy warning and the
  setup documentation.
- "Upgrading from 0.1": the breaking changes of the 0.2 alphas rolled up
  in one place, each pointing at the alpha that made it, from the existing
  entries and migration/0.1-to-0.2.json.
- Link references: [Unreleased] compared from v0.1.0-alpha.19; it now
  compares from v0.2.0-alpha.14, and 0.1.0-alpha.20 to .23 and every 0.2
  alpha get their own, in the repository's v<version> tag form.
…t/consumer-hardening

# Conflicts:
#	.prettierignore
#	README.md
#	eslint.config.js
#	vite.config.ts

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

The upgrade can miss local barrels or stylesheet wiring, corrupt some peer ranges, and fail shadow commands on Windows.

Review effort: Balanced
Findings: 2 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Hardens the 0.2 migration and packaging for existing 0.1 consumers by fixing cascade ordering, splitting the CLI package, and expanding upgrade automation.

Changes:

  • Prepends the canonical cascade-layer order to shipped stylesheets.
  • Moves tooling into @lablup/ui-common-cli with lockstep publishing and CI coverage.
  • Extends codemods for stylesheet wiring, theming, barrels, wrappers, dependencies, and reporting.
File Description
vite.config.ts Injects layer order and build constants.
test/​upgrade/​fixtures/​adapter/​expected/​src/​main.tsx Removes obsolete fixture output.
src/​ui-common.css Updates layer-order guidance.
src/​types/​build-constants.d.ts Declares injected version constants.
src/​migrationMap.test.ts Reads the relocated migration map.
src/​layerOrder.test.ts Tests layer-order utilities.
src/​instance.ts Adds duplicate-copy detection.
src/​instance.test.ts Tests instance registration.
src/​i18n/​useUicTranslator.ts Registers instances during translation.
src/​components/​Modal/​modalStack.ts Registers instances for modal state.
scripts/​layer-order.mjs Centralizes layer-order handling.
scripts/​layer-order.d.mts Types layer-order utilities.
scripts/​check-fixture-styles.mjs Validates bundled layer order.
scripts/​check-boundary.mjs Covers the CLI package boundary.
pnpm-workspace.yaml Defines the root and CLI workspace packages.
pnpm-lock.yaml Records split-package dependencies.
packages/​cli/​test/​upgrade/​stylesheets.test.ts Tests script stylesheet ordering.
packages/​cli/​test/​upgrade/​local-modules.test.ts Tests local-module resolution.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​input/​src/​themeToggle.ts Adds unwired theme-switch input.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​input/​src/​main.tsx Adds unwired app entry input.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​input/​src/​index.css Adds unwired application CSS.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​input/​src/​App.tsx Adds unwired component input.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​input/​package.json Defines the unwired fixture.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​input/​index.html Defines its browser entry.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​expected/​ui-common-upgrade-report.md Captures expected migration findings.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​expected/​src/​ui-common-entry.css Expects generated style entry.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​expected/​src/​themeToggle.ts Preserves reported theme code.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​expected/​src/​main.tsx Expects stylesheet and Theme wiring.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​expected/​src/​index.css Preserves reviewed CSS.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​expected/​src/​App.tsx Expects component migration.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​expected/​package.json Expects dependency upgrades.
packages/​cli/​test/​upgrade/​fixtures/​unwired/​expected/​index.html Preserves the HTML entry.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​input/​src/​styles/​theme.ts Adds subpath stylesheet input.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​input/​src/​styles/​families.css Adds legacy selector input.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​input/​src/​reports/​ReportPreviewFrame.tsx Adds DOM-hook input.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​input/​src/​components/​common/​Select.test.tsx Adds legacy test-query input.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​input/​src/​components/​common/​index.ts Adds subpath barrel input.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​input/​src/​components/​common/​DataTableWrapper.tsx Adds complex migration input.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​input/​package.json Defines the subpath fixture.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​expected/​ui-common-upgrade-report.md Updates expected findings.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​expected/​src/​styles/​ui-common-entry.css Expects generated style entry.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​expected/​src/​styles/​theme.ts Expects rewritten style import.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​expected/​src/​styles/​families.css Preserves flagged selectors.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​expected/​src/​reports/​ReportPreviewFrame.tsx Preserves flagged DOM hooks.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​expected/​src/​components/​common/​Select.test.tsx Expects a migration TODO.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​expected/​src/​components/​common/​index.ts Expects barrel rewrites.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​expected/​src/​components/​common/​DataTableWrapper.tsx Expects component rewrites.
packages/​cli/​test/​upgrade/​fixtures/​subpath-barrel/​expected/​package.json Expects CLI dependency addition.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​input/​src/​themes/​violet.css Adds root-barrel CSS input.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​input/​src/​pages/​ModelsPage.tsx Adds root-import migration input.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​input/​src/​pages/​ModelsPage.test.tsx Adds mock and selector input.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​input/​src/​chat/​InputPopup.tsx Adds DOM and token input.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​input/​package.json Defines the root-barrel fixture.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​expected/​ui-common-upgrade-report.md Updates expected root findings.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​expected/​src/​themes/​violet.css Preserves flagged theme CSS.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​expected/​src/​pages/​ModelsPage.tsx Expects root-import rewrites.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​expected/​src/​pages/​ModelsPage.test.tsx Preserves review-only test findings.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​expected/​src/​chat/​InputPopup.tsx Preserves review-only hooks.
packages/​cli/​test/​upgrade/​fixtures/​root-barrel/​expected/​package.json Expects CLI dependency addition.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​input/​tsconfig.json Adds path-alias configuration.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​input/​src/​pages/​Settings.tsx Adds unresolved-alias input.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​input/​src/​pages/​Overview.tsx Adds local-barrel usage input.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​input/​src/​components/​common/​table.ts Adds removed-type re-export input.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​input/​src/​components/​common/​status.ts Adds import-then-export input.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​input/​src/​components/​common/​Select/​index.tsx Adds wrapper input.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​input/​src/​components/​common/​index.ts Adds local barrel input.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​input/​package.json Defines the local-barrel fixture.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​expected/​ui-common-upgrade-report.md Captures wrapper and type findings.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​expected/​tsconfig.json Preserves alias configuration.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​expected/​src/​pages/​Settings.tsx Expects unresolved-alias TODOs.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​expected/​src/​pages/​Overview.tsx Expects local usage rewrites.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​expected/​src/​components/​common/​table.ts Expects removed type cleanup.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​expected/​src/​components/​common/​status.ts Expects alias rewrites.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​expected/​src/​components/​common/​Select/​index.tsx Expects wrapper migration TODOs.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​expected/​src/​components/​common/​index.ts Expects barrel migration.
packages/​cli/​test/​upgrade/​fixtures/​local-barrel/​expected/​package.json Expects upgraded dependencies.
packages/​cli/​test/​upgrade/​fixtures/​library/​input/​src/​chat/​ReasoningBlock.tsx Adds library-consumer input.
packages/​cli/​test/​upgrade/​fixtures/​library/​input/​package.json Adds React 18 peer input.
packages/​cli/​test/​upgrade/​fixtures/​library/​expected/​ui-common-upgrade-report.md Expects peer-range reporting.
packages/​cli/​test/​upgrade/​fixtures/​library/​expected/​src/​chat/​ReasoningBlock.tsx Expects library codemods.
packages/​cli/​test/​upgrade/​fixtures/​library/​expected/​package.json Expects React 19 peers.
packages/​cli/​test/​upgrade/​fixtures/​css-entry/​input/​src/​print.css Adds conditional import input.
packages/​cli/​test/​upgrade/​fixtures/​css-entry/​input/​src/​index.css Adds CSS entry input.
packages/​cli/​test/​upgrade/​fixtures/​css-entry/​input/​package.json Defines the CSS fixture.
packages/​cli/​test/​upgrade/​fixtures/​css-entry/​expected/​ui-common-upgrade-report.md Updates expected CSS report.
packages/​cli/​test/​upgrade/​fixtures/​css-entry/​expected/​src/​print.css Expects conditional-import TODO.
packages/​cli/​test/​upgrade/​fixtures/​css-entry/​expected/​src/​index.css Expects full stylesheet replacement.
packages/​cli/​test/​upgrade/​fixtures/​css-entry/​expected/​package.json Expects CLI dependency addition.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​input/​src/​main.tsx Adds adapter entry input.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​input/​src/​index.scss Adds SCSS migration input.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​input/​src/​design-system/​common-components.css Adds legacy theme CSS.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​input/​src/​design-system/​common-adapters.tsx Adds adapter component input.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​input/​package.json Defines the adapter fixture.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​expected/​ui-common-upgrade-report.md Updates expected adapter report.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​expected/​src/​ui-common-entry.css Expects adapter stylesheet entry.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​expected/​src/​main.tsx Expects Theme and styles wiring.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​expected/​src/​index.scss Expects SCSS stylesheet replacement.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​expected/​src/​design-system/​common-components.css Expects dropped theme import.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​expected/​src/​design-system/​common-adapters.tsx Expects adapter rewrites.
packages/​cli/​test/​upgrade/​fixtures/​adapter/​expected/​package.json Expects adapter dependencies.
packages/​cli/​test/​upgrade/​codemods.test.ts Tests removed types and peer ranges.
packages/​cli/​test/​cli/​lab-peer.test.ts Updates split-package paths.
packages/​cli/​test/​cli/​cli.test.ts Tests CLI version lockstep.
packages/​cli/​scripts/​extract-legacy-classes.mjs Relocates the legacy-class generator.
packages/​cli/​README.md Documents the standalone CLI.
packages/​cli/​package.json Defines the published CLI package.
packages/​cli/​NOTICE Adds CLI attribution.
packages/​cli/​codemods/​upstream.mjs Wraps upstream Astryx codemods.
packages/​cli/​codemods/​registry.mjs Extends codemod step hooks.
packages/​cli/​codemods/​lib/​todo.mjs Centralizes TODO placement.
packages/​cli/​codemods/​0.2/​scan.mjs Expands migration findings.
packages/​cli/​codemods/​0.2/​map.mjs Resolves split-package migration data.
packages/​cli/​codemods/​0.2/​index.mjs Wires project-level upgrade hooks.
packages/​cli/​cli/​sync-astryx.mjs Synchronizes both package pins.
packages/​cli/​cli/​shadow.mjs Adds temporary Astryx lookup environments.
packages/​cli/​cli/​semver.mjs Adds internal version handling.
packages/​cli/​cli/​rewrite.mjs Rewrites Astryx CLI output.
packages/​cli/​cli/​report.mjs Expands upgrade reports.
packages/​cli/​cli/​passthrough.mjs Runs and rewrites Astryx commands.
packages/​cli/​cli/​main.mjs Updates CLI help and version output.
packages/​cli/​cli/​diff.mjs Adds dry-run line diffs.
packages/​cli/​cli/​agents.mjs Documents the split CLI dependency.
packages/​cli/​bin/​ui-common.mjs Adds the CLI executable.
package.json Removes production CLI dependencies.
fixture/​pnpm-workspace.yaml Configures consumer build-script decisions.
eslint.config.js Updates CLI and fixture paths.
docs/​astryx.md Documents split packaging and checks.
CONTRIBUTING.md Updates contributor CLI paths.
codemods/​0.2/​package-json.mjs Removes the old codemod location.
cli/​paths.mjs Removes the old CLI path utility.
astryx/​docs/​ui-common.doc.mjs Corrects the built theme import.
astryx.integration.mjs Corrects integration theme guidance.
.prettierignore Updates fixture paths.
.gitignore Ignores the fixture lockfile.
.github/​workflows/​publish.yml Packs and publishes both packages.
.github/​workflows/​ci.yml Tests both tarballs with pnpm.
Files not reviewed (1)
  • pnpm-lock.yaml: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread packages/cli/codemods/0.2/local-modules.mjs Outdated
Comment thread packages/cli/codemods/0.2/package-json.mjs Outdated
Comment thread CONTRIBUTING.md
…ed aliases

localExports skipped any module whose imports all started with a word
character or `@` (other than `@/`), so a barrel such as
`export * from "components/common"` resolved through tsconfig `baseUrl`, or
one re-exporting through a `@ui/*` paths alias, was never read and its
callers stayed on 0.1 props. The bail-out now asks the resolver whether a
specifier reaches a project file. That lookup is a probe, so specifiers the
text scan finds in comments do not inflate the unresolved-alias notice.
dropBelow19 kept or dropped each `||` alternative by its first number, so
`>=18 <21 || ^22` lost its React 19 and 20 support and became `^22`, and a
range with nothing left was replaced by a guess. The React peers are now
intersected with the floor the target ui-common's own react peer starts at
(19.2.0 when that cannot be read), alternative by alternative:
`>=18 <21 || ^22` becomes `>=19.2.0 <21 || ^22`, an alternative already at
or above the floor keeps its text, and a range that admits no such React
(`^17`) is left alone and reported. The range arithmetic lives in the CLI's
own semver helper; no dependency is added.
CONTRIBUTING still named codemods/0.2/legacy-classes.json, the upgrade
fixture test's header ran `vitest run test/upgrade` from a root that no
longer has it, and the migration map links read migration/... though they
point into packages/cli. Package-relative paths inside packages/cli and
released changelog entries are left as written.
The CLI package publishes only prereleases, which go to `next`, but the
registry sets a package's `latest` on its first publish whatever `--tag`
says, so a bare `pnpm dlx @lablup/ui-common-cli` / `npx` resolves to the
first alpha for as long as 0.2 is in prerelease. Every documented one-off
invocation (README, the CLI README, the changelog, `--help`, `upgrade
--help` and the agent block) names `@next` and says it becomes plain once
0.2.0 is published. publish.yml keeps its tags and only explains why the
docs say `@next`.
…t/consumer-hardening

# Conflicts:
#	CHANGELOG.md
#	codemods/0.2/package-json.mjs
#	packages/cli/codemods/0.2/stylesheets.mjs
#	packages/cli/test/upgrade/codemods.test.ts
#	packages/cli/test/upgrade/package-json.test.ts
@yomybaby

yomybaby commented Oct 2, 2026

Copy link
Copy Markdown
Member Author

Ready-gate agent review (Opus) — blocking issues only

# File:line Finding Outcome
O1 .github/workflows/publish.yml (dist-tag step), README.md:453, packages/cli/README.md, CHANGELOG.md:17,83 @lablup/ui-common-cli only ever publishes prereleases to next; npm sets latest on a first publish, so the documented bare pnpm dlx @lablup/ui-common-cli … would resolve a stale first alpha forever Fixed in 80117fe: every documented invocation (README, CLI README, CHANGELOG, --help, agents block) uses @lablup/ui-common-cli@next while 0.2 is prerelease; the workflow keeps latest untouched and says why

Copilot: reviewed — 3 threads, all fixed (172c2f7, 796cc35, 56fa070).
Fixes and the merge of #53's review fixes (436b72a) landed after both reviews and were not re-reviewed; pnpm run verify passes on 436b72a (1430 tests).

@yomybaby
yomybaby marked this pull request as ready for review October 2, 2026 04:52
@yomybaby
yomybaby merged commit fcf5df0 into feat/astryx-foundation Oct 2, 2026
3 checks passed
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