mcpField
S
sb-inventory

sb-inventory

github.com/strongeron测试与质量3983 次安装4 周前更新
代码仓库

关于 sb-inventory

sb-inventory 是一项技能,通过生成的清单数据检查项目组件、设计信号和 Storybook 覆盖情况。它帮助团队区分自有组件与供应商、支持文件,并追踪组件在页面中的使用。

主要功能

  1. 01生成项目清单 JSON
  2. 02区分自有、供应商和支持组件
  3. 03提取组件属性与调用位置
  4. 04构建组件到页面的使用关系图
  5. 05追踪故事覆盖及待补故事

适用场景

  1. 01识别规划故事所需的自有组件
  2. 02检查应用中未使用的已声明属性
  3. 03查找使用某组件的页面及父组件
  4. 04检查令牌使用和故事覆盖情况

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/strongeron/storybook-workbench --skill sb-inventory

安装后在 Claude Code 中输入/sb-inventory确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

CONTEXT.md
agents/
openai.yaml
decorators/
withLayoutFrame.tsx
references/
field-learnings.md
scripts/
build-component-pages.py
extract-component-usage.sh
inventory-project.sh
refresh-usage.sh
scaffold-usage-mdx.py
scaffold-wrapper.sh
token-usage.py
templates/
usage-profile.mdx
wrappers/
ComponentUsage.tsx
icons.tsx
ProjectInventory.tsx
ReportIntro.tsx
resolve-paint.ts
usage-index.tsx
usage-stamp.tsx

详细介绍

sb-inventory — 事实为准,而非盲目信任

氛围编程的应用会带着约 30% 的粗制滥造代码上线。此技能将“相信 AGENTS.md / CLAUDE.md / DESIGN.md”替换为“查看实际导入的内容”。阅读 CONTEXT.md,了解 real/vendor/dead/kind 这些术语的含义。 (这里的主导设计系统来自代码信号,而非文档。如果存在 DESIGN.md 设计说明,sb-health 会将其中声称的颜色与代码进行交叉核对——它和 AGENTS.md 一样,可能会过时或说错。)

运行

SKILL=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}
CORE=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}
"$SKILL/scripts/inventory-project.sh"   # writes .storybook/project-inventory.json (atomic)

脚本才是事实依据——切勿手动重新计算。阅读 JSON 并引用其中的字段。 有关已知的检测器陷阱(在验证运行中,发现脚本哪些地方做对了、哪些地方做错了),只有在某个计数看起来意外时(例如 0、异常值或疑似误报的孤立项),才加载 references/field-learnings.md。如果首次盘点结果正常、数字看起来合理,不要加载它——JSON 字段本身就足以说明情况。

报告(按以下顺序读取字段)

  1. 技术栈 — libraries(react/vite/tailwind v4|v3/shadcn/radix/baseui/r3f)。
  2. 主导设计系统 — designSystem.dominant(取值为 tailwind-v4/shadcn/dtcg/css-vars/none 之一)以及 mixed 标记。如果 mixed 为 true → 告诉用户项目正处于迁移中;建议使用 sb-health。
  3. 用户自己的组件 — components.realCount / deadCount 仅统计领域组件。引用 components.real[](按导入次数从多到少排列),作为编写故事的优先清单。
  4. 供应商组件 — components.vendorCount + byKind.vendor = shadcn components/ui/ 基础组件。 请单独指出这些组件:“你还安装了 N 个 shadcn 基础组件——它们不是你的代码,也不是粗制滥造代码,先别急着为它们写故事。”
  5. 模块 / 支持文件 / 脚手架 — moduleCount(byKind.module = 类型/辅助函数/钩子/工具函数/lib/api——非组件源码),supportCount(byKind.scaffold|support = 测试/工厂/模拟 + SB 初始化教程)。这些都不计入总览数字,也不计入 real[] 导入次数最多的列表,因此该列表展示的是生产环境中的组件,而不是被到处导入的 types.ts。如果计数非零,请说明。
  6. 设计令牌 — 已使用与孤立的令牌。故事 — orphanStories(导入了已不存在组件的故事)以及 components.storyCoverage — 自有组件的故事覆盖情况:{real, storyFiles, withColocatedStory, withStory, needsCount, needsStory[]}。请根据 withColocatedStory(拥有其自身 <name>.stories.* 文件的自有组件)和 storyFiles(实际存在的不同故事文件)读取覆盖情况——这两个才是准确计数。withStory 是宽松的上限:它也会将任何被故事导入的组件计为已覆盖(例如,为了模拟表单而导入表单的对话框故事),因此会高估;应将 withColocatedStory ≤ real_coverage ≤ withStory 作为判断范围。needsStory[] 是“需要编写故事”的待办清单(与 orphanStories 相反);refresh-usage.sh 会使其保持最新,以便 sb-stories 按清单逐项处理。

此处最重要的修正:“真实组件”清单和总览数字只包含用户编写的组件——不包含 40 个 shadcn 基础组件、类型或辅助函数。这是盘点反馈中最常见的问题;vendor / support / scaffold 分类正是为了让总览保持准确。

将其呈现为故事

搭建 ProjectInventory 封装组件,让 Agent 和设计师看到同一视图:

"$CORE/scripts/scaffold-wrapper.sh" ProjectInventory   # → .storybook/wrappers/ (+ icons.tsx)

标题设为 Foundations/Inventory。封装组件读取相同的 JSON;不要使用表情符号(使用共享图标集)。

真实属性使用情况(不只是判断真实与灌水)

importers 会告诉你某个组件已被使用;但它不会告诉你应用实际渲染了哪些属性/变体。shadcn Button 可能声明了 6 种变体,但生产环境中只发布了 2 种——其余的只是目录填充项。完成清单盘点后,运行使用情况提取器:

"$CORE/scripts/extract-component-usage.sh"   # → .storybook/component-usage.json (atomic)

对于每个组件(自身组件和 shadcn 基础组件,以 PascalCase 导出项为键),它会从 JSX 调用点记录:props.<name>.{count, values{value:n}, exprCount}、callSites、files[] 和 declaredButUnused——从未传入的已声明属性/字符串联合值(属性级灌水)。此外还有 pages 汇总。引用这些字段;不要再次 grep。sb-stories 会读取这些数据,为真实状态确定优先级,并标记从未使用的状态。

组件工作列表——按导入审计整个系统(ComponentUsage)

要查看整个系统——所有真实 UI 组件按调用点数量排名、了解它们嵌套在什么组件中(parents)/渲染什么组件(children),以及它们最终出现在哪些路由页面上(直接或传递)——请生成组件↔页面导入图。它会组合这 3 个发现阶段的 JSON 文件(不进行新的扫描):

"$CORE/scripts/build-component-pages.py"   # project-inventory + component-usage + flows → component-pages.json
# (or just run "$CORE/scripts/refresh-usage.sh" — it writes all four together)

build-component-pages.py 会读取 component-usage.json(callSites/props/declaredButUnused 以及每个组件的 files)、project-inventory.json(每个组件的 file/kind)和 flows.json(路由 path + access 角色),然后写入 .storybook/component-pages.json: 每个组件包含 {callSites, props, declaredButUnused, parents[], children[], pages[{path, title, role, storyId}]};此外,如果组件自身文件就是路由页面表面,则包含 isPage:true + route(该文件提供服务的路径)。路由器会将页面作为配置值挂载({ component: X }),而非 JSX,因此按设计就是 0 个调用点/0 个属性(这是准确结果,并非缺失)——route 能让文档写出“提供 /scheduler 服务”,而不是容易误导人的“0”。route 是页面提供服务的路由,与 pages[] 分开存放(把页面列在“它出现在哪些页面上”中会显得循环)。 这与双向使用关系配套,因此一个文件就能从任意方向回答“X 在哪里使用”: fileIndex(<src file> → {component, kind, pages[]})、tokens(<--token> → {category, count, components[], pages[]}——正向),以及每个组件的 tokens[] 数组(反向——该组件使用的内容)。tokens 会列出所有已声明的令牌(已使用、仅基础组件使用或孤立的令牌)——即使某个令牌只被设计系统基础组件(src/components/ui/*.tsx,清单会将其归入 vendor/module,而非受跟踪组件)使用,它也会解析到该基础组件作为使用方,而不会被悄然丢弃,因此浏览器会展示完整调色板,而不只是能追溯到应用组件的令牌。usage-index 辅助工具(resolveUsage/UsageDetail/UsageDisclosure)会读取 fileIndex,让 TokenMatrix 和 Foundations 色板将原始路径转换为可点击的组件/页面名称;UsageExplorer 封装组件会读取完整关系图,作为一个可搜索的“此项在哪里使用?”界面(令牌 ⇄ 组件 ⇄ 页面)。这样一来,旧的每应用 audit-map.json(一个平行的组件↔页面关系图)就不再需要了。 ComponentUsage 封装组件会将其渲染为工作列表——使用 "$CORE/scripts/scaffold-wrapper.sh" ComponentUsage 来搭建。页面会通过渲染关系图解析(嵌套在 /dashboard 上 CourseCard 中的 Rating 会显示 /dashboard),因此它能回答*“我们有哪些组件、使用频率如何、嵌套在哪里、出现在哪些屏幕上,还有哪些仍需要 story?”* 这是一份静态草稿——barrel/动态/别名导入可能导致关系链接不完整;请对照源码验证关键关系。

呈现用法(对齐后的流程——在 Storybook 中与此一致)

用法就在你查看内容的地方——嵌入各个部分的 Docs 中,无需单独的“用法”页面/部分。

  1. 每个 Docs 页面都有一个文档区块(默认启用,无需新增文件)。 提供 UsageSection 包装器,并将其添加到 .storybook/preview.ts 中的全局 autodocs 布局。它会为每个部分的 Docs 添加真实用法区块,并读取对应的审计输出文件(因此 foundations 需要 tags: ['autodocs']):

    • Components → component-pages.json — ComponentContext 的“使用位置”映射(组件出现在哪些页面中、哪些内容会嵌套它、它会渲染什么、会读取哪些 tokens),以及从 src/ 导入并独立渲染的真实组件。默认折叠,便于快速浏览:始终显示简洁的“使用位置”眉题 + 自适应元信息(仅显示非零计数——不显示多余的大号 <h2>,因为 Docs 标题已包含组件名称);映射按需展开(使用原生 <details>,在独立审计页面上默认展开)。元信息会根据页面类型调整:真实组件显示“5 处调用 · 2 个 props · 有 story”,而路由页面(isPage)不显示调用次数/props,并优先显示其服务的路由——“服务 /scheduler · 5 次渲染 · 有 story”。元信息上方会显示“这是什么 + 来源”的溯源栏,默认不在 Docs 页面中显示(它会在每个组件中重复出现;使用 setProvenance(true) 可启用)。复用 Usage-explorer 印章。
    • Pages/* → 从 src/ 导入的真实应用页面,通过 provider/Inertia mocks(sb-setup)渲染——是真实页面,而非模型图。其“这是什么?”溯源栏默认不在 Docs 页面中显示(页面 story 已包含相关内容;使用 setProvenance(true) 可重新显示溯源栏)。
    • Foundations → UsageSection 不提供任何内容。每个 Foundation 都有自己的独立 story:Colors → TokenMatrix(值 · 映射 · 采用情况——不是健康状态;不传入 health prop,它默认值为 false),Health → DesignSystemHealth(完整发现结果),Icons → IconMatrix,Typography/Scales → tokens 展示。旧版每个 Foundation 中的“此应用中的真实用法”区块已移除:Health 区块会重复展示 DesignSystemHealth story,而每个 token 的“使用位置”无法解析类型/比例(声明名称 ≠ 引用名称)——这部分由 Usage explorer 和 Colors 的采用情况列展示。

    不占用侧边栏;不创建单独的页面。

    import { Title, Subtitle, Description, Primary, Controls, Stories } from '@storybook/addon-docs/blocks';
    import { UsageSection } from './wrappers/UsageSection';
    // parameters.docs.page = () => (<><Title/><Subtitle/><UsageSection/><Description/><Primary/><Controls/><Stories/></>)
    // ↑ order is yours — UsageSection here puts the real-usage status band at the TOP; move it last for the bottom.
    

    refresh-usage.sh 会更新 JSON 文件;重新构建 Storybook 即可反映这些更改。生成器默认不会生成任何内容——scripts/scaffold-usage-mdx.py --per-component 是一个可选的备用方案,可从 templates/usage-profile.mdx 渲染出独立的 <Name>.usage.mdx 页面(很少需要)。

  2. 可视化用法网格是组件自身 CSF 中的独立 story——绝不单独创建文件(新文件 = 新的侧边栏文件夹)。在其他导出项旁边添加一个导出,并使用 usage prop: <StateGrid component={X} usage={usageJson.components.X} states={…} />(或 StateMatrix);对于 tokens,使用 <TokenUsageGrid>。

限制:{...spread}/动态值会计入 exprCount(“从变量设置”),不会被解析(静态分析)。

完整 Setup 扫描

本技能负责清单。其余发现工作请运行同级技能(每个技能管理自己的脚本、原子化写入 JSON,无需子 Agent):sb-flows(路由/边/导航 → flows.json),然后 sb-stories 会在需要时生成 component-states.json + prop-shapes.json。 读取 JSON 文件;不要重新 grep 源码。

切勿(以及不那么显而易见的原因)

  • 切勿根据文档判断主导设计系统——应读取代码信号(导入、调用位置)。 DESIGN.md/AGENTS.md 是一种说法,会逐渐过时;真正生效的是导入。
  • 切勿手动重新计数或重新搜索源代码——发现脚本已将结果写入 .storybook/*.json。请引用字段。目测重新推算的结果会与封装器实际呈现的内容不一致,还会浪费 JSON 已经消耗过的上下文。
  • 切勿盲目信任边界情况的计数——遇到 0、异常值或疑似误判为孤立项的情况?此时请加载 references/field-learnings.md(BSD-sed 的 \s、Tailwind 工具类令牌消耗、组件与页面混淆)。静态扫描存在已知盲点;实地记录会说明这些盲点。
  • 切勿将用法网格单独放在一个文件中——它是组件自身 CSF 中的扁平故事。新文件意味着新的侧边栏文件夹;网格应放在它所概述的状态旁边。

下一步

在 .storybook/audit/findings.md 中追加一行发现,然后询问 hub(/sb-hub)——通常是 sb-flows(记录应用映射)或 sb-stories <TopComponent>。

评论

支持 Markdown