Repository navigation
feat(gamut-agent-tools): add the gamut-scope-swap skill - #45
Merged
Merged
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>
This was referenced Oct 20, 2026
Merged
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
# Conflicts: # packages/gamut-codemods/src/presets/scope-swap/index.ts
…p-skill # Conflicts: # packages/gamut-codemods/src/presets/scope-swap/index.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LinKCoding
approved these changes
Oct 27, 2026
LinKCoding
left a comment
Contributor
There was a problem hiding this comment.
Ran against this:
REPO=/Users/kenny.lin/Documents/eng/codecademy-eng/skillsoft-gamut
rm -rf /tmp/swap-app && mkdir -p /tmp/swap-app/src && cd /tmp/swap-app && git init -q
cat > package.json <<'EOF'
{
"name": "swap-app",
"version": "1.0.0",
"dependencies": {
"@codecademy/gamut": "^1.0.0",
"@codecademy/gamut-styles": "^1.0.0",
"@codecademy/gamut-icons": "^1.0.0",
"@codecademy/gamut-kit": "^1.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
EOF
cat > tsconfig.json <<'EOF'
{ "compilerOptions": { "lib": ["es2020"], "jsx": "react" } }
EOF
cat > next.config.js <<'EOF'
module.exports = { experimental: { esmExternals: false } };
EOF
echo '{ "plugins": ["gamut"], "extends": ["plugin:gamut/recommended"] }' > .eslintrc.json
cat > src/App.tsx <<'EOF'
import { Box, Video } from '@codecademy/gamut';
import { theme } from '@codecademy/gamut-styles';
import { ArrowIcon } from '@codecademy/gamut-icons';
// eslint-disable-next-line gamut/no-inline-style
export const App = () => <Box style={{}}><Video /><ArrowIcon /></Box>;
EOF
git add -A && git commit -qm init
node $REPO/packages/gamut-codemods/dist/bin.js scope-swap .
git diff --stat
node $REPO/packages/gamut/bin/gamut.mjs plugin install claude
node $REPO/packages/gamut/bin/gamut.mjs plugin list
And then prompted the agent to use the skill and it worked through the issues and had gave me:
What the codemod changed
- src/App.tsx: the imports now use @skillsoft/*, and Video now comes from @skillsoft/gamut/Video. The eslint-disable directive was renamed to @skillsoft/gamut/no-inline-style.
- .eslintrc.json: the plugin and the extends entry now use @skillsoft/gamut. They match the directive prefix, so the directive will still work.
- package.json: gamut-kit was replaced with the individual @skillsoft packages.
What I fixed
- next.config.js: I removed experimental.esmExternals: false. It was the only setting in the file, so the config is now {}. The failure only shows up when Next collects page data, so you need a full next build to confirm. There were no @emotion aliases or transpilePackages entries to remove.
- tsconfig.json: I added "dom" to lib. It's harmless to keep. If type-checking passes without it, you can take it back out.
- package.json, Video peers: I added @vidstack/react@~1.12.12 and react-player@^3.4.0. Gamut supports only 1.12.x of @vidstack/react, so don't use the npm latest tag.
- package.json, @skillsoft/gamut-tests: I moved it from dependencies to devDependencies, since the codemod put it in the same field gamut-kit was in.
What's left for you
1. Run yarn. If it warns about missing @emotion/cache or stylis peers for @skillsoft/gamut-styles, add them.
2. Run prettier --write and eslint --fix, then type-check, test and build.
3. The ranges are ^0.0.1, which can resolve to a release older than the codemod expects. If @skillsoft/gamut/Video or MenuList isn't found after install, check node_modules/@skillsoft/gamut/package.json and its exports.
4. The repo has no sync-gamut-deps script, so the gamut-kit cleanup needs nothing.
5. src/App.tsx imports theme but never uses it. It was already like that before the swap, but lint will flag it.
I haven't committed anything. Say if you want me to run yarn and the checks.
|
@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: |
Drop the stale empty-preset changeset and the per-PR codemods and Video changesets. Their details now live in gamut-codemods-scope-rename, and the duplicate Video bullets in gamut-video-markdown are already in move-video-out-of-barrel. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
dreamwasp
added a commit
that referenced
this pull request
Oct 28, 2026
#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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Last PR in the stack. It adds the
gamut-scope-swapagent skill and the fixtures that run every migration together.Note
This branch is a merge of the Video/Markdown, deep imports, ESLint, and Next.js PRs, because the skill and the combined fixtures need all of them. Its base is the scope-rename PR, so until those four merge, this diff includes their changes. Review only the last commit (
feat(gamut-agent-tools): add the gamut-scope-swap skill), and rebase ontomainonce the others land.Stack (split from #28, merge in order):
mainmaingamut-scope-swapskill in@skillsoft/gamut-agent-tools. It works alongside the codemod: it reads the warnings, leftovers, and next steps, and helps with what the codemod can't rewrite. That covers deep imports, Video, the renamed Menu exports, tsconfigdom, jest mocks, ESLint plugin keys, Module Federation config, and preview builds. It doesn't run the codemod unless asked.BREAKING_CHANGES.mdis the short list of every change in the move, with the manual ones marked.NEXT_EMOTION_INTEROP.mdis the fallback for Next.js apps that can't dropesmExternals: falseyet. The codemods README now links to it.gamut-agent-toolsREADME and the codemods README point to the skill.gamut-kitin one file.cli.test.tsmerge between the sibling branches.PR Checklist
Testing Instructions
yarn nx test gamut-codemods. Expect 100 tests to pass, including the combined end-to-end and MDX fixtures.Run the whole preset on a consumer repo (or a copy of one), then install the skill from the app repo:
Ask the agent to work through the output. It should use the warnings and leftovers, refer to
BREAKING_CHANGES.mdfor anything it can't rewrite, and not rerun the codemod unless you ask it to.Read
BREAKING_CHANGES.mdagainst the PRs in the stack. Every breaking change should be listed.PR Links and Envs
🤖 Generated with Claude Code