Skip to content

fix(ai): rules use paths: frontmatter, only task-scoped guidance becomes skills - #6613

Open
blunteshwar wants to merge 8 commits into
mainfrom
rulesTOskills
Open

fix(ai): rules use paths: frontmatter, only task-scoped guidance becomes skills#6613
blunteshwar wants to merge 8 commits into
mainfrom
rulesTOskills

Conversation

@blunteshwar

@blunteshwar blunteshwar commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Description

Claude Code inlines every rule file under .claude/rules into every session unless that file's frontmatter tells it not to — but the key it reads for that is paths: (a YAML list), not Cursor's globs:. None of this repo's .ai/rules/*.md files used paths:, so all 14 loaded unconditionally on every Claude Code session (~35K tokens), regardless of alwaysApply or globs. Cursor was unaffected the whole time — it reads globs/alwaysApply live via its own per-file .mdc symlinks.

This PR's first commits (mis-)diagnosed that as "Claude Code has no conditional rule loading at all" and moved every non-alwaysApply rule into .ai/skills/. That overcorrected: skills have no glob/path auto-trigger in either tool, so file-scoped guidance like stories-format or component-readme would only surface if the agent happened to match the task's intent to the skill's description — a real regression from Cursor's previous guaranteed-fire-on-matching-file behavior.

The actual fix, once paths: was confirmed against the Claude Code docs (including that path-scoping is honored through a symlinked .claude/rules directory, since v2.1.198): give every rule that has a Cursor globs: value an equivalent Claude paths: value too, and keep it a rule, not a skill. Only guidance with no natural file-path scope — task/intent-driven work like drafting a Jira ticket or running a consistency pass — belongs in .ai/skills/.

Motivation and context

Raised internally (Slack) after profiling Claude Code session token usage on this repo. The skills-only approach was revised mid-PR after a reviewer pointed out that Claude Code does support path-scoped rules via paths: frontmatter, and that routing genuinely file-scoped standards through skills makes them depend on model-triggered discovery instead of a deterministic trigger.

Changes

Stay/become path-scoped rules (both globs: for Cursor and paths: for Claude Code, so both tools load them only when a matching file is in context):

  • text-formatting, stories-documentation, stories-format, component-readme, contributor-doc-update, storybook-mdx-conversion
  • Restored their .cursor/rules/*.mdc symlinks
  • contributor-docs-nav skill reverted to its pre-PR state now that contributor-doc-update exists again as the path-scoped rule pointing to it

Stay skills (no natural file-path scope — task/intent-triggered in Cursor too, so this part of the original migration was correct):

  • jira-ticket, github-description, code-conformance, consistency-pass, migration-phase-awareness, deep-understanding
  • Each now documents its own "when to use this skill" / "how to invoke" section, since skills need an explicit description-match or invocation instead of a file-path trigger

Stay rules, unaffected: branch-naming, styles (genuinely alwaysApply: true, no paths: needed — they load unconditionally in both tools by design)

Also fixed along the way (found during self-review, unrelated to the rule/skill split but same root cause — YAML frontmatter that was never actually valid):

  • globs: **/*.md,**/*.mdx and similar unquoted values starting with * parse as an invalid YAML alias, not a literal string (verified with js-yaml). Quoted every globs:/paths: value that starts with * — this affected storybook-mdx-conversion, text-formatting, and (found in this second pass) styles.md's globs: *.css.

Documentation: rewrote .ai/README.md and AGENTS.md to describe the corrected mechanism (globs vs paths, which key each tool reads, symlink support) and the rule-vs-skill decision rule (file-path scope → path-scoped rule; task/intent scope → skill). Fixed every cross-reference to the files that moved back from .ai/skills/ to .ai/rules/.

Related issue(s)

  • No linked GitHub issue; internal tooling/token-efficiency cleanup from a Slack discussion

Screenshots (if appropriate)

N/A — no UI change.

Author's checklist

  • I have read the CONTRIBUTING and PULL_REQUESTS documents.
  • I have reviewed the Accessibility Practices for this feature.
  • I have added automated tests to cover my changes.
  • I have included a well-written changeset if my change needs to be published.
  • I have included updated documentation if my change required it.

No changeset: this only touches repo-internal AI tooling docs; nothing is published to npm.

Reviewer's checklist

  • Includes a Github Issue with appropriate flag or Jira ticket number without a link
  • Includes thoughtfully written changeset if changes suggested include patch, minor, or major features
  • Automated tests cover all use cases and follow best practices for writing
  • Validated on all supported browsers
  • All VRTs are approved before the author can update Golden Hash

Manual review test cases

  • Verify .ai/rules/ frontmatter is valid YAML and Claude-conditional

    1. Confirm every globs:/paths: value starting with * is quoted in .ai/rules/*.md (storybook-mdx-conversion.md, text-formatting.md, stories-format.md, stories-documentation.md, styles.md)
    2. Confirm component-readme.md, contributor-doc-update.md, storybook-mdx-conversion.md, stories-documentation.md, stories-format.md, text-formatting.md each have a paths: list matching their globs: value
    3. Confirm branch-naming.md and styles.md have no paths: field (always-active, unconditional in both tools)
  • Verify yarn lint:ai passes

    1. Run node .ai/scripts/validate.js (or yarn lint:ai)
    2. Expect all 5 checks (story tags, AGENTS.md paths, config schema, symlinks, docs pages) to pass with no errors
  • Verify Cursor and Claude Code symlinks are consistent

    1. .cursor/rules/ has one .mdc symlink per file in .ai/rules/ (8 total: branch-naming, styles, and the 6 path-scoped rules)
    2. .claude/rules still resolves to .ai/rules/ via the existing directory symlink
    3. Skills catalog in .ai/README.md no longer lists component-readme, storybook-mdx-conversion, stories-documentation, stories-format, or text-formatting as skills

Device review

  • Did it pass in Desktop?
  • Did it pass in (emulated) Mobile?
  • Did it pass in (emulated) iPad?

Accessibility testing checklist

Tooling/docs-only change; no component, DOM, or runtime behavior is affected.

  • Keyboard — N/A: no focusable UI is added or changed by this PR.
  • Screen reader — N/A: no rendered output changes; only agent instruction files (.ai/rules/, .ai/skills/) and their cross-references are affected.

Claude Code inlines every file under the .claude/rules directory symlink
regardless of alwaysApply/globs frontmatter, defeating the on-demand design
of .ai/rules (~35K tokens/session). Only branch-naming and styles are
genuinely alwaysApply: true, so they stay as rules; every other rule is
converted to a .ai/skills/*/SKILL.md entry, which is already loaded on
demand via the existing .cursor/skills and .claude/skills symlinks.

- Move jira-ticket, github-description, code-conformance, consistency-pass,
  migration-phase-awareness, component-readme, storybook-mdx-conversion,
  stories-documentation, stories-format, and text-formatting to skills
- Fold contributor-doc-update into the existing contributor-docs-nav skill
- Fold the deep-understanding rule into its existing skill
- Remove the corresponding .cursor/rules/*.mdc symlinks
- Update all cross-references and the .ai/README.md rules/skills catalog
@blunteshwar
blunteshwar requested a review from a team as a code owner August 13, 2026 06:18
@changeset-bot

changeset-bot Bot commented Aug 13, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 2a1fbbe

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

@github-actions

Copy link
Copy Markdown
Contributor

📚 Branch Preview Links

🔍 Gen1 Visual Regression Test Results

When a visual regression test fails (or has previously failed while working on this branch), its results can be found in the following URLs:

Deployed to Azure Blob Storage: pr-6613

If the changes are expected, update the current_golden_images_cache hash in the circleci config to accept the new images. Instructions are included in that file.
If the changes are unexpected, you can investigate the cause of the differences and update the code accordingly.

@coveralls

coveralls commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Coverage Report for CI Build 31788372534

Warning

No base build found for commit 56fd6ef on main.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 96.241%

Details

  • Patch coverage: No coverable lines changed in this PR.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 39268
Covered Lines: 37993
Line Coverage: 96.75%
Relevant Branches: 6465
Covered Branches: 6021
Branch Coverage: 93.13%
Branches in Coverage %: Yes
Coverage Strength: 460.61 hits per line

💛 - Coveralls

pvashish_adobe added 2 commits August 13, 2026 11:59
…de-off

Self-review of PR #6613 found two skills with an unquoted `globs:` value
starting with `**`, which YAML parses as an invalid alias reference
(verified with js-yaml) rather than a literal string:
storybook-mdx-conversion (regressed by the rename) and text-formatting
(pre-existing, carried forward). Quote both.

Also documents that a skill's `globs:` field is relevance metadata, not
a guaranteed auto-trigger the way Cursor's rule glob was — call this out
in .ai/README.md and refresh the stale "glob-triggered rules" wording in
AGENTS.md now that only two rules remain.
The rules-to-skills conversion moved content over without adding explicit
invocation guidance, since Cursor rules applied automatically via globs and
never needed it. Skills require an agent to match intent or a glob hint to
the skill's purpose, so every migrated skill now states when it applies and
how to invoke it.

Glob-scoped skills (component-readme, storybook-mdx-conversion,
stories-documentation, stories-format, text-formatting) call out that a
matching file being in context is itself a trigger, not just an explicit
ask. Task-scoped skills (jira-ticket, github-description, code-conformance,
consistency-pass, migration-phase-awareness) list the natural-language
phrases that should invoke them, reusing existing "when to run"/"when to
apply" content where present rather than duplicating it.
@blunteshwar blunteshwar added the Status:WIP PR is a work in progress or draft label Aug 13, 2026
@blunteshwar blunteshwar added Status:Ready for review PR ready for review or re-review. and removed Status:WIP PR is a work in progress or draft labels Aug 13, 2026
pvashish_adobe added 2 commits August 13, 2026 19:06
…tter

The rules-to-skills migration assumed Claude Code has no mechanism for
conditional rule loading. It does: a `paths:` YAML frontmatter field
(distinct from Cursor's `globs:`) on files under `.claude/rules/`, honored
even through the `.claude/rules -> ../.ai/rules` directory symlink. A rule
without `paths:` loads unconditionally; that's why the whole `.ai/rules/`
directory was inlining every session, since none of those files used the
key Claude actually reads.

Move component-readme, contributor-doc-update, storybook-mdx-conversion,
stories-documentation, stories-format, and text-formatting back from
`.ai/skills/` to `.ai/rules/` as path-scoped rules, adding a `paths:` list
alongside the existing Cursor `globs:` so both tools load them
deterministically when a matching file is in context. Restore their
`.cursor/rules/*.mdc` symlinks, and revert contributor-docs-nav to its
pre-fold state now that contributor-doc-update exists again as its own
path-scoped rule pointing to it.

Guidance with no natural file-path scope (jira-ticket, github-description,
code-conformance, consistency-pass, migration-phase-awareness,
deep-understanding) stays as skills — that part of the original migration
was correct, since Cursor never glob-triggered those either.

Also quote `globs: '*.css'` in styles.md, which had the same unquoted
leading-glob YAML bug found in the earlier self-review, just never
triggered because it was never parsed as strict YAML until now.

Rewrites .ai/README.md and AGENTS.md to describe the corrected mechanism
and the rule-vs-skill decision (file-path scope -> path-scoped rule;
task/intent scope -> skill), and fixes every cross-reference to the
restored rule paths.
@blunteshwar blunteshwar changed the title chore(ai): convert on-demand and glob-scoped rules to skills fix(ai): rules use paths: frontmatter, only task-scoped guidance becomes skills Aug 13, 2026

@rise-erpelding rise-erpelding left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The "Deep understanding" docs in .ai/README.md could use an update now that it's a skill and not a rule, I think that's the only really necessary change here, which is really minor, so I don't think it needs to block approval.

I flagged a few other .ai/-related things that I thought were a little confusing but will leave it to your discretion about whether to address or not since this was meant to be a quick fix and not a total refactor of the whole directory.

Happy to take another look if you think it needs one at any point!

Comment thread .ai/README.md Outdated
Comment on lines 349 to 350

@rise-erpelding rise-erpelding Aug 13, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This will need an update now that it's a skill and not a rule, we probably can remove "enforced by an always-applied rule" and adjust some other parts that talk about usage like "no need to ask" and "every session"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'm questioning if we still need this? Or if it should/could be a skill? I think this might possibly have some overlap with generate-contributor-docs.mjs?

But I also think looking into it and making adjustments would increase the scope of this work; I feel ok with leaving it as it is right now and re-evaluating later.

Comment thread .ai/README.md Outdated
2. Add one per-file symlink for Cursor (required — Cursor needs `.mdc` extension):

```sh
ln -s “../../.ai/rules/rule-name.md” “.cursor/rules/rule-name.mdc”

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

not introduced here but these look like curly quotes

Comment thread .ai/README.md
Comment on lines 38 to 51
```json
{
"version": 1,
"rules": {
"category": {
"rule_name": {
"enabled": true,
"pattern": "regex_pattern",
"message": "Error message"
}
}
}
}
```

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

We don't have to address it in this PR but this schema doesn't really reflect anything we currently have in config.json as far as I can tell?

- Fix stale "Deep understanding" catalog entry: it was never enforced by
  an always-applied rule (deep-understanding was alwaysApply: false even
  before this PR, and the rule file is now fully merged into the skill).
  Reword to match the skill's actual "apply intelligently" behavior.
- Clarify storybook-mdx-conversion's relationship to
  generate-contributor-docs.mjs: the automated `yarn generate:contributor-docs`
  already converts all of CONTRIBUTOR-DOCS/ to Storybook MDX and shouldn't be
  hand-duplicated; this rule is for standalone manual conversions outside
  that pipeline.
- Replace the config.json schema example in .ai/README.md with one that
  matches its actual structure (flat git/jira_tickets/text_formatting
  sections) instead of a generic rules.category.rule_name shape that
  doesn't exist in the file.
- Straighten a pre-existing pair of curly quotes in a shell command example.

@rise-erpelding rise-erpelding left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Just peeked at these changes, they look great! 🤩

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

Labels

Status:Ready for review PR ready for review or re-review.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants