Skip to content

feat: script to generate skills from storybook#8001

Draft
gusch wants to merge 7 commits into
masterfrom
new-skill-script
Draft

feat: script to generate skills from storybook#8001
gusch wants to merge 7 commits into
masterfrom
new-skill-script

Conversation

@gusch

@gusch gusch commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

What the script does :

  • Enhance SKILL.md and index.md to facilitate trigger
  • Generate a skill for each mdx in carbon repository

  • Generate a sub folder examples/ for each skill which will contain as many files as there are examples for that component
  • Add some more references docs like validation and useMediaQuery.

Things to decide /improve :

  • update description to be skill efficient : « Captures a single line of text. » does not explain well when to use a TextBox so the skill may not trigger.

  • Some have no description at all : use the one from design system ?

  • Add a category ? (ex: input, button, presentation, …)

  • Many examples are missing context. They just have the code.

  • Some examples are not up to date : usage of deprecated color prop on Typography for example
  • Some links remain : DS, react doc, translation keys

  • Some skill are too long : >500 lines (ex: simple/filterable/multi select)
  • Do we keep « Ref methods » section ?

  • Do we keep "translation keys" section ?
  • The reference docs would need the same kind of script than for the components' mdx to correctly manage links and stories

Problems to correct :

  • MenuSegmentTitle : problem to get metadata for props (already a problem in storybook)

  • image : problem to get metadata for props

  • Icon : problem to display list of icons
  • date : problem to get metadata for props
  • checkbox : problem to get metadata for props
  • checkboxgroup : problem to get metadata for props

@gusch gusch self-assigned this Jun 4, 2026
@gusch gusch requested review from a team as code owners June 4, 2026 14:22
@gusch gusch requested a review from Copilot June 5, 2026 07:12

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 wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@quinnturner

quinnturner commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Hi there, I am the author of build_script.mjs.

I think there are many good changes in this PR. However, I have some major concerns:

  1. The root SKILL.md is missing. This violates the skill specification: https://agentskills.io/specification#directory-structure.
  2. I believe the removal of the references is going to be significantly detrimental to the performance of the agent. In my coding sessions, the recommended-practices one is frequently loaded and referenced. I've found my agents doing a lot of const Comp = styled(Box) without it.
  3. A significant reason why I introduced these skills was to help consumers migrate from the older design system to the newer design system. This was heavily praised by consumers with large projects that require piecemeal upgrades. With this change, agents can no longer perform that migration. The previous skills were heavily referenced and effectively used during updates.
  4. The removal of the index.md may result in agents not knowing what components are available. Right now, that's the main mechanism for providing context on which components are available to agents.
  5. Recursively nested SKILL.mds are not supported by any coding agent: Skills: nested skills in skills/*/SKILL.md not discovered anthropics/claude-code#28266 + Copilot. Renaming them is arguably an anti-pattern because when consumers Command + P in VSCode to find a skill to reference, instead of being shown a few (one per actual skill), they're now shown ~100 because it's now per component.

I like the changes in the folder structure + the introduction of examples/. I like the shortening of files. I like removing much of the prop-focused complexity.

IMO, while I have no say on this project, I think it would be beneficial to refactor the examples/props without removing the deprecation notices or documentation references (those aren't hurting anyone + I definitely see value almost every single day using them), without removing the SKILL.md or changing the component file names to SKILL.md, and ideally without removing index.md. Those are still critical to my day-to-day workflow as one of Carbon's leading internal adopters.

@gusch gusch force-pushed the new-skill-script branch from 0b9d570 to 47301b9 Compare June 10, 2026 14:36
@gusch gusch force-pushed the new-skill-script branch from 47301b9 to 6eb7bdb Compare June 10, 2026 14:39
@gusch

gusch commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

I would like to discuss the format of stories because the result in both storybook and skills will greatly depend of it.
The script will display the story as it is, Storybook can use spread objects, replace args, ....

If i use spread object and args in the story, Storybook will display only the render part with args replaced by the values.
In the skill, it will display the code of the story and thus will not be very efficient for the model which will have to interpret/guess the object and args.
Story : image
Storybook : image
Skill : image

If i use a return in the story, Storybook will display correctly but will encapsulate with () => {}
In the skill, it will be more readable for the model (no guessing)
But it means duplication between stories.
image
image
image

Is it ok to replace all mutualisation/args (and to not use it in the future) ?

@gusch gusch marked this pull request as draft June 12, 2026 07:56
@ibutakova

Copy link
Copy Markdown
Contributor
  1. I noticed a structural mismatch between skills/carbon-react/index.md file and the actual files generated by the script. The index.md currently contains links pointing directly to flat markdown files. But the generator script outputs components into nested directories, and the PR shows the older flat .md files being deleted. For me this looks like the links in the main index file are broken. I also see components/accordion/index.md to be the only nested component file. Could you clarify if the script is intended to update these index links to match the new nested directory structure, or if this is an incomplete or partial generation run?
  2. The script deletes the entire skills/carbon-react directory before writing the new output. This approach carries some risk, as we might accidentally lose valuable documentation if it is not explicitly captured in wouldWrite. Wouldn't it be better to narrow the cleanup scope? For example, keep all automatically generated files under a nested path like skills/carbon-react/generated/ (or something like this, low cost, easy to maintain) or maintain a manifest of generated file paths and configuring the script to only delete files listed in that manifest (overhead).
  3. pr removes older references such as colors/styling docs. If those are intentionally deprecated or replaced, could we document what should be used instead? Otherwise, should they be added to docsReferenceFiles?
  4. Good to keep storybook stories optimized for developers while having the generator produce explicit code for AI agents. I mean where it is safe to do so, the script could evaluate simple object variables and flatten them directly into readable JSX props within the generated markdown files. If an example is too complex to safely unpack, the script can just fall back to the original code and append a quick note indicating it uses Storybook spreads.
  5. It would be very useful to have “When to use” section for each component instead of generic description for some components. For example, Textbox should explain when it is preferred over Textarea, etc. This would make the skill more useful for component selection, not just prop lookup.

Never mind if some of these points may duplicate or reinforce points already raised in the discussion)

@ibutakova

Copy link
Copy Markdown
Contributor

I also wonder if it is possible improve the script. For example, to split it into parser, resolver, writer, etc modules? I mean what if skill generation logic changes or grows, and it becomes hard to maintain all concerns that are mixed in a single file?
And a developer should read and understand the whole script before providing new changes. Let’s say build_skills responsible for finding docs, reading mdx, parsing metadata and storybook examples, rewriting links, generating md and index, etc.
Just as an example, we can have parcers folder with mdx, stories, and generators folder with component, references, etc, utils folder with some utils.

@ibutakova

Copy link
Copy Markdown
Contributor

Also good to think about regex parsers vs abstract syntax tree parsers for complex extraction logic to reduce fragility if docs formatting affects.

@ibutakova ibutakova left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe I misunderstood or didn't get the context right, but following issues might break current system behavior (you can find more details in pr conversation):

  1. index.md: there seems to be a structural mismatch where index points to flat markdown paths, but the script deletes them and outputs nested directories
  2. wiping the entire skills/carbon-react directory before a write run looks risky
  3. pr removes core styling and color documentation. If they are deprecated, we should document what replaces them

Also, here are a few things that would be great to have to improve long-term maintainability and AI skill quality:

  1. Where safe, let's have the script evaluate simple object variables and flatten them into explicit JSX props in the markdown. Or fall back to the original code + a disclaimer note for complex spreads.
  2. Adding high-level guidance "When to Use" (like when to choose Textbox over Textarea) could improve the skill.
  3. As the script handles a lot of mixed concerns right now, splitting it into separate modules (like /parsers, /generators, and /utils) would make it much easier to maintain. Switching from regex to an AST parser for complex extractions would also make it less fragile to future documentation format changes.

Let me know what you think and if I missed any context

@gusch

gusch commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

@ibutakova
1- There were too many files generated so what you are seeing now is a partial generation (i only kept Accordion).
The current goal is to demonstrate/validate what the script does before going further.

2- i did not change the behavior of the script (delete all -> generate).
Besides, the source of truth is the code (mdx + stories + docs) not what is in skills/carbon-react. So there is no risk to delete all each time.

3- i removed colors and styles docs because they are not up to date.
They could easily be added again

4- It is something i wanted to discuss

5 - the description is meant to carry the "When to use" part.
I updated it using Design System and AI.
As any AI thing, it is open for improvement after usage if we see something is missing.

Concerning the script maintenance, i would agree but i focused on correctly generating the files.
All the updates to the script were done using Copilot.

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 wasn't able to review this pull request because it exceeds the maximum number of files (300). Try reducing the number of changed files and requesting a review from Copilot again.

@edleeks87 edleeks87 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I've had to manually review this as the PR is too big for copilot to review so I may have missed or misunderstood something. Overall I'm happy with the approach to add more useful information to the skill files and restructure them so they're more efficient, as long as we don't lose the migration capabilities we had previously (along with anything else @quinnturner got from it etc). I do have concerns about relying on the storybook files for things like deprecations and types (less concerning as it pulls from the interfaces) as they still rely on the authors of these files not missing something at the minute. I'd feel more confident if we were still pulling things like that from parsing/inspecting the AST for a given module and then relying on the MDX etc for things like description, usage and examples etc.

To use accordions, import the `Accordion` component and pass the desired content as child components.

```javascript
import { Accordion } from "carbon-react/lib/components/accordion";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

comment: whilst the imports are still being included, we run the risk of this being wrong as it seems to be just reading from the MDX now which relies on them being added correctly or at all etc. Previously this was pulled by parsing and inspecting the module's AST to pull the import. In the long run we could look to have some form of linting/validation but it might be better to continue the old approach whilst we don't have that


for (const mdxPath of allMdxFiles) {
const content = await fs.readFile(mdxPath, "utf8");
const isDeprecated = content.includes("<DeprecationWarning");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

comment: this seems to rely on the author of whatever changes lead to a deprecation including a DeprecationWarning in the mdx. I think it would be more secure to capture this from the actual module inspecting it for a jsdoc @deprecated. We're still doing this for deprecated props but we've potentially introduced a blind spot here imo

});
}
storyMap.set(componentName, existing);
const props = resolvePropsForStories(storiesPath);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

question/suggestion: it looks like we have some inconsistencies between this and reference-mdx.mjs where there's a fallback to resolveArgTypesFromMeta if resolvePropsForStories returns empty etc. I wonder if it's worth adopting the same approach here? I could very well be missing something here so apologies if this is off the mark

);
} else {
// Clean entire output directory then recreate structure
await fs.rm(skillsRoot, { recursive: true, force: true });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion: previously we were explicitly ensuring idempotency with respect to file line endings: if it was CRLF it was CRLF and if it was LF it was LF but this seems to be making it all LF. Several places even explicitly normalise input via .replace(/\r\n/g, "\n"), e.g. in mdx-discovery.mjs and reference-mdx.mjs. I wonder if it's worth adding a .gitattributes file to explicitly define how MD files in carbon handle EOL

// .gitattributes
*.md text eol=lf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

5 participants