Repository navigation
Conversation
…eset Adds @skillsoft/gamut-codemods: the CLI (clean-tree guard, --dry, --only, --no-report, --force), the runner for ast, splice, and file migrations, the shared helpers (module-string finder, leftovers report, version-range checks, flat ESLint config detection), the preset registry, and the fixture harness. The scope-swap preset has its package map but no migrations yet, so a run only reports the lines that still name an old package. Each breaking change lands its migration in its own PR. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…swap scope-rename swaps @Codecademy/gamut* and eslint-plugin-gamut for their @SkillSoft names in every module position and in comments. package-json, mdx-imports, and yarnrc cover dependencies, MDX ESM blocks, and .yarnrc.yml lists. @codecademy/gamut-kit has no replacement, so package-json and mf-shared expand it into the packages it bundled. In Module Federation config that makes Gamut a real singleton, which the checklist calls out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ides moved-exports moves Video and VideoProps from the root to @Codecademy/gamut/Video (scope-rename then swaps the scope). markdown-video-overrides adds explicit iframeOverride/videoOverride to each <Markdown>, since it no longer renders video through Video by default, and drops the removed skipDefaultOverrides keys. tsconfig-dom warns about tsconfigs without "dom", which Video used to supply. On the Gamut side, a Video/package.json stub makes the subpath resolve under node10, MarkdownVideo no longer passes NaN sizes, and a one-line <video> is no longer wrapped in a <p>. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ectDropdown elements Exports formFieldStyles, formFieldPaddingStyles, conditionalStyles, ButtonBaseProps, HTMLToReactNode, MenuToolTipWrapper, and Menu's list elements from the root. The list elements and SelectDropdown's option component are renamed (MenuList*, MenuListButton, IconOptionComponent) so they don't collide with the public List component and IconOption type. The deep-imports codemod rewrites known /dist/ paths to the root, keeps local names across renames, merges into existing imports, and warns on paths with no public replacement. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
eslint-comments rewrites gamut/ directives to @skillsoft/gamut/, and eslint-config updates the plugin name, plugin: extends, and rule keys in legacy .eslintrc files. Under a flat config the prefix is the plugins key, so eslint-comments skips itself and the checklist explains why. Also types eslint-plugin-gamut's recommended severities as literals, so the plugin fits ESLint's Plugin type in a typed flat config. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@skillsoft/gamut ships strict-ESM .mjs. With experimental.esmExternals off, Next require()s server externals and default imports from @emotion/styled and react-select break while it collects page data. next-config is report-only: dropping the flag can take other config with it, so it warns and adds a checklist item instead of rewriting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ap-skill # Conflicts: # packages/gamut-codemods/README.md # packages/gamut-codemods/src/presets/scope-swap/index.ts
# Conflicts: # packages/gamut-codemods/README.md # packages/gamut-codemods/src/__tests__/lib.test.ts # packages/gamut-codemods/src/presets/scope-swap/index.ts
…p-skill # Conflicts: # packages/gamut-codemods/README.md # packages/gamut-codemods/src/__tests__/cli.test.ts # packages/gamut-codemods/src/presets/scope-swap/index.ts
The skill works alongside the scope-swap codemod: it reads the warnings, leftovers, and next steps, and helps with what the codemod can't rewrite. BREAKING_CHANGES.md lists every change in the move, and NEXT_EMOTION_INTEROP.md covers the Next.js esmExternals fallback. Also restores the end-to-end and MDX fixtures that run every migration together, and fixes the cli.test merge between the sibling branches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CodeQL read `migration.match(file)` in cli.ts as String.prototype.match on a command-line argument and flagged js/regex-injection. Nothing builds a regex from the path; the method just had the same name. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…migrations Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…migrations Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…migrations Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…migrations Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The package-json warning already names each range that's newer than the fork point, so the extra next step only repeated it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rkdown # Conflicts: # packages/gamut-codemods/src/presets/scope-swap/index.ts
# Conflicts: # packages/gamut-codemods/src/presets/scope-swap/index.ts
# Conflicts: # packages/gamut-codemods/src/presets/scope-swap/index.ts
…swap-skill # Conflicts: # packages/gamut-codemods/src/presets/scope-swap/index.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves Gamut color names onto the generated color system's roles using design's migration map (gamut-sandbox c363244). Renames and merges are applied; splits, retired and pending names get a color-roles comment and a warning. Old palette names and runtime-built names only warn. Presets are now generic over their manifest and bring their own pre-filter and leftovers report. scope-swap's behavior is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#45 landed as a squash with later edits, so the color-roles preset is reapplied on main's codemod framework. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@skillsoft/eslint-plugin-gamut
@skillsoft/gamut
@skillsoft/gamut-agent-tools
@skillsoft/gamut-codemods
@skillsoft/gamut-icons
@skillsoft/gamut-illustrations
@skillsoft/gamut-patterns
@skillsoft/gamut-styles
@skillsoft/gamut-tests
@skillsoft/variance
commit: |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #53 +/- ##
===========================================
+ Coverage 79.78% 96.99% +17.21%
===========================================
Files 296 31 -265
Lines 6643 1299 -5344
Branches 2287 422 -1865
===========================================
- Hits 5300 1260 -4040
+ Misses 1334 38 -1296
+ Partials 9 1 -8
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…Card variants - A color-roles-stylesheets migration renames old --color-* variables to --colors-<role> in .css, .scss and .less, and marks splits with design's rule. The leftovers report now scans stylesheets too. - The color-roles transform does the same for var(--color-*) inside JS string and template literals, with the comment outside the string. - Card's variant moves onto design's default and brand; a navy card gets a comment, since it now renders light. - The alias map is regenerated from design's map at sandbox df33b47: shadow-primary and shadow-secondary split onto shadow-key and shadow-ambient, and border-primary's rule covers floating surfaces. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dreamwasp
left a comment
There was a problem hiding this comment.
Stylesheets, JS strings and Card variants, plus design's map at sandbox df33b47. Notes on the lines below.
| kind: 'file', | ||
| description: | ||
| 'Rename old `--color-*` variables in stylesheets; mark the ones a person has to pick.', | ||
| appliesTo: (file) => /\.(css|scss|less)$/.test(file), |
There was a problem hiding this comment.
The type check can't see var(--color-*) in stylesheets, so without this pass they'd break silently. Indented-syntax .sass is left out on purpose: a comment mid-value can break it. The checklist tells people to search those by hand.
| }); | ||
|
|
||
| /* | ||
| `var(--color-…)` in a string or template literal. A rename is applied |
There was a problem hiding this comment.
For a split inside a string, the comment goes in front of the literal rather than inside it, so it never ships in runtime CSS and can't break the string's quoting.
| Card's variants are design's two (sandbox df33b47): white, beige and navy | ||
| become `default`; yellow and hyper become `brand`. | ||
| */ | ||
| const CARD_VARIANTS: Record<string, string> = { |
There was a problem hiding this comment.
Design's sandbox update, 2026-11-03: Card collapses to default and brand. Only Cards imported from gamut are touched. navy gets a comment because it now renders light; wrapping it in <ColorMode mode="dark"> keeps it dark.
| to: ['surface-error'], | ||
| rule: 'The error tint behind an alert or inline validation message.', | ||
| }, | ||
| 'shadow-primary': { |
There was a problem hiding this comment.
Design's sandbox update, 2026-11-03: regenerated from design's map at df33b47. shadow-primary and shadow-secondary go from pending to a split onto shadow-key + shadow-ambient, and border-primary's rule now covers floating surfaces.
A color-roles-themes migration moves imports from gamut-styles onto the brand themes that replace them: percipioTheme → skillsoftTheme, coreTheme → originalCodecademyTheme, PercipioTheme → SkillsoftTheme. An aliased import only changes its imported name; an unaliased one is renamed wherever the file uses it, keeping shorthand object keys. A CoreTheme type gets a color-roles comment pointing at SkillsoftTheme. Front's provider imports `percipioTheme as theme`, and no codemod handled it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| person, since it's usually a Theme augmentation the app owns. | ||
| */ | ||
|
|
||
| const RENAMES: Record<string, string> = { |
There was a problem hiding this comment.
percipioTheme is removed and skillsoftTheme replaces it; coreTheme still exists but defines no roles, so components lose their colors on it, and originalCodecademyTheme is its rebuild. Front's provider imports percipioTheme as theme, which no codemod handled before this. CoreTheme has no same-named successor, so it gets a comment instead of a rename.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`n is Node` narrowed every non-string node to `never`, so the tsc build failed on the branches after an isString check. Jest doesn't typecheck, so the tests still passed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The generator, and design's migration map with it, moved from gamut-styles' src/colorSystem to @skillsoft/gamut-brand. aliases.ts is regenerated from the moved map; only its header comments change. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… prefix The codemod emitted --colors-<role>. main and gamut-styles use --color-, so the rewrite now emits --color-<role> too: the stylesheet rename, the JS var rewrite, the changeset and the fixtures. A rewritten name is a role, and no role is also an old alias key, so a second run leaves it alone. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
…o cass-gmt-1825-color-codemod
The fixture test ran the second-run check only for JS migrations. The stylesheet pass returned early, so a rewritten --color-<role> was never re-checked. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Overview
Adds a
color-rolespreset that moves Gamut color names onto the generated system's roles, using design's migration map. Presets can now have their own manifest, pre-filter and leftovers report; scope-swap's behavior is unchanged. Draft, stacked on #45.Framework
lib/types.ts,lib/run-source.ts,presets/index.ts—Preset<M>and the migration types are generic over their manifest, defaulting to scope-swap's. A preset brings its ownmentionspre-filter and an optionalleftoversreport.cli.ts,transform.ts,presets/scope-swap— call those hooks; scope-swap passes the pre-filter and leftovers report the CLI used to call directly.__tests__/manifest.test.ts,fixtures.test.ts— the export check covers manifests that promise exports; end-to-end fixtures for other presets live in__tests__/__testfixtures__/<preset>/.color-roles
migrations/color-roles— one splice migration. Rename and merge rows are applied. Split, retired and pending names stay (they still fail the type check), with a/* color-roles: … */comment carrying design's rule and a warning. Old palette names and runtime-built names (${variant}-hover) only warn.&&, responsive values),theme.colors.x/['x'],themed('colors.x').variant="primary"and other look-alike strings are left alone.presets/color-roles— the manifest (32 aliases, 43 roles, 104 old palette names), a leftovers report of unresolvedcolor-roles:comments, the checklist.aliases.tsis generated from gamut-stylescolorSystem/migration.ts.Tests and docs
color-roles-manifest.test.ts: every applied row names exactly one real role.README.md— running color-roles, what it changes, its limits.PR Checklist
c363244)Testing Instructions
yarn nx test gamut-codemods→ 128 tests pass; scope-swap's 100 are unchanged.yarn nx build gamut-codemods, thennode packages/gamut-codemods/dist/bin.js list→color-rolesis listed.node packages/gamut-codemods/dist/bin.js color-roles packages/gamut/src --dry. On feat(gamut-styles)!: brands, overrides and Original Codecademy on the color system #52's branch: 60 files, 171 warnings, 0 errors.Known gap:
aliases.tsis a generated copy of design's map, and the generator (gen-manifest.ts) still lives outside the repo, because this branch and #50 don't share gamut-styles yet. It should move in and read the workspace package once they do.🤖 Generated with Claude Code