Storybook 仓库 PR 的 Lint 与 TypeScript 修复 Skill:从 gh pr checkout 到 CI 全绿的完整工作流
Storybook 主仓库维护了一套面向 AI Agent 的技能(Skill)定义,其中 fix-linting-types-on-pr 技能专门解决一个高频维护场景:当一个 Pull Request 的 CI 因 lint 或 TypeScript 类型错误而失败时,如何以最小侵入的方式检出 PR、批量修复错误并推送回去。本文完整还原该技能定义的八步工作流,并结合仓库中 nx.json、check-package.ts、code/package.json 等真实配置与源码,解释每一步命令背后的实际作用,读完即可在 Storybook 仓库(或同构的 Nx + Yarn Workspaces 大型 monorepo)中复现这一修复流程。
技能定位:它是什么、何时触发
技能的实际定义位于 .agents/skills/fix-linting-types-on-pr/SKILL.md,而 .claude/skills/fix-linting-types-on-pr/SKILL.md 仅包含一行指向该定义文件的引用,从文件结构看这是一种将技能定义放在共享 .agents 目录、再由 .claude 目录别名引用来复用的组织方式。
技能文件采用带 YAML frontmatter 的 Markdown 格式:
---
name: fix-linting-types-on-pr
description: Checks out a PR (including fork PRs), fixes all linting and TypeScript errors, then pushes the changes back. Use when asked to fix lint, types, or TS errors on a PR.
---
name是技能的唯一标识;description同时承担了触发条件说明——只有当用户请求"修复 PR 上的 lint / types / TS 错误"时才应启用该技能。
技能覆盖的目标仓库是 Storybook 主仓库本身:一个基于 Nx 任务编排、Yarn 4 workspaces、oxlint 与原生 TypeScript 编译器的大型 monorepo。这决定了工作流中大量命令不是通用模板,而是与仓库脚本精确对齐的。
第一步:确定 PR 编号
技能要求:如果用户已给出 PR 编号则直接使用,否则主动向用户索取。这是整个流程的输入锚点,后续所有 gh 操作都围绕它展开。
第二步:用 gh pr checkout 检出 PR
gh pr checkout <PR_NUMBER>
技能中明确指出选用 gh pr checkout 而非手动 git fetch + git checkout 的原因:它对 fork PR 和非 fork PR 同样有效。该命令会自动建立正确的 remote tracking 并切换到 PR 分支——对于来自 fork 的贡献者 PR,普通 git checkout 往往找不到对应分支,而 gh pr checkout 会处理 pull/N/head 引用并配置好上游跟踪关系。这一点直接服务于第八步的 git push:因为跟踪关系已在检出时配好,推送时无需再指定 remote 和分支名。
第三步:安装依赖
yarn
Storybook 仓库根目录 package.json 声明了 "packageManager": "yarn@4.18.0",并通过 workspaces 字段纳入了 code/addons/*、code/frameworks/*、code/lib/*、code/renderers/* 等全部子包。检出 PR 分支后依赖树可能已变更,先执行 yarn 保证本地 node_modules 与 PR 分支的 yarn.lock 一致,是后续编译与检查任务可复现的前提。
第四步:先编译整个仓库
yarn nx run-many -t compile
技能文档特别强调了这一步的必要性:"先编译,确保 linter 所引用的 TS 声明文件已经存在"。在仓库的 nx.json 中可以找到 compile target 的完整定义:
"compile": {
"dependsOn": ["^compile"],
"command": "node ... ./scripts/build/build-package.ts --cwd {projectRoot}",
"configurations": { "production": { "args": "--prod" } },
"cache": true,
"inputs": ["production", "^production"],
"outputs": [
"{projectRoot}/dist",
"{workspaceRoot}/code/bench/esbuild-metafiles/{projectName}"
]
}
这里有几个要点:
"dependsOn": ["^compile"]表示各包按依赖顺序先编译上游包,保证子包编译时能解析到依赖包的dist产物(含类型声明);- 产物落到
{projectRoot}/dist,并且任务开启了 Nx 缓存("cache": true),重复执行时未变更的包会被缓存命中; - 正是这些
dist中的.d.ts声明文件,成为后续 lint 与类型检查阶段跨包类型解析的基础——跳过编译直接跑 lint/类型检查,会出现大量"找不到模块声明"的假性错误。
第五步:修复 Lint 错误
yarn lint
顺着仓库脚本链路看这条命令的真实内容:根 package.json 中 "lint": "cd code; yarn lint",转到 code/package.json 后是 "lint": "yarn lint:js" → "lint:js": "yarn lint:js:cmd . --quiet",最终执行的命令是:
"lint:js:cmd": "oxlint --report-unused-disable-directives-severity=error"
也就是说 Storybook 仓库的 lint 引擎是 oxlint,并且把"未被使用的 eslint-disable 指令"提升为 error——这意味着在修复过程中如果删除了某条规则报错的代码,配套的 eslint-disable 注释也会被要求一并清理,否则 lint 仍会失败。这也是该技能适合"批量修复"的原因:oxlint 本身速度快且支持 autofix,大部分格式、未使用变量等问题可以先自动修复,剩余问题再手工处理。
第六步:修复 TypeScript 错误
yarn nx run-many -t check
check target 的定义同样在 nx.json 中:
"check": {
"dependsOn": [{ "projects": ["*"], "target": "compile" }],
"command": "yarn exec jiti ./scripts/check/check-package.ts --cwd {projectRoot}",
"cache": true,
"inputs": ["default", "^production"]
}
其命令最终落到 scripts/check/check-package.ts。阅读该脚本可以看到检查的真实机制:
- 它调用的是 typescript-native 的原生 tsc(
require.resolve('typescript-native/package.json')下的bin/tsc),以--project tsconfig.json --noEmit --pretty false运行,即只做类型检查、不产出文件,且输出为可解析的纯文本; - 每个包的 tsc 设有
TSC_TIMEOUT_MS = 10 * 60 * 1000的超时上限,源码注释说明其意图是"卡死的原生编译器应让单个包快速失败,而不是拖到整个 check 任务阻塞到 CI 超时"; - 检查完原始输出后,会调用 filterToPackageDiagnostics 过滤诊断结果——该函数只保留路径没有越过包目录(
!rel.startsWith('..'))的诊断,从而把"本包引入的报错"与"上游包的问题"区分开,避免修复者在错误的包里找问题。
严格模式也是理解报错密度的一把钥匙:code/tsconfig.json 中显式启用了 "strict": true 与 "strictBindCallApply": true。
技能文档给出的常见修复类型包括:
- 添加或纠正类型标注;
- 修正错误的泛型实参;
- 解决违反 strict 模式的
any赋值; - 补齐缺失的 import 或 re-export。
并要求每修完一批就重跑一次 yarn nx run-many -t check 确认错误已消除,形成"编辑 → 验证"的小步循环,而不是攒到最后一次性面对整屏报错。
第七步:提交修复
git add <files-you-modified>
git commit -m "Maintenance: Fix linting and TypeScript errors"
技能对提交方式有两条明确约束:
- 只暂存自己改动的文件(
git add <具体文件>),并明确禁止git add -A——检出 PR 分支时工作区可能带有其他改动,全量暂存会把无关文件一并推上去; - 提交信息采用仓库可识别的维护类前缀
Maintenance:,与功能提交区分开,便于 PR 描述与 changelog 生成时归类。
第八步:推送并确认 CI
git push
对 fork PR,gh pr checkout 已在检出时配置好 upstream tracking,因此直接 git push 即可把修复提交叠加到 PR 之上,无需额外指定远端。
边界约束:技能 Notes 里的四条纪律
技能文档末尾的 Notes 定义了该流程的行为边界,这些约束与命令本身同等重要:
- 只修"明确属于 lint 或 TypeScript 问题"的错误,不做逻辑重构。这保证了修复提交可审计:diff 中不应出现行为变更;
- 遇到需要非平凡代码改动的类型错误时,先向用户(维护者)暴露并确认,再继续——类型错误有时暗示接口设计问题,自动"修掉"可能掩盖真实缺陷;
- 如果
gh pr checkout因 fork 权限失败,如实告知用户:贡献者可能需要授予 fork 写权限,或由维护者直接推送; - 推送后必须与用户确认 CI 已全绿,而不是把"push 成功"当成任务终点。
小结与证据索引
这套技能的价值在于把"修 CI 中 lint/类型错误"这件重复性劳动固化成了一条与 Storybook 仓库工程结构精确对齐的流水线:gh pr checkout 处理 fork 场景、nx run-many -t compile 保证声明文件就位、oxlint 完成快速 lint、基于 typescript-native tsc 的分包 check 任务配合诊断过滤精确定位类型错误,最后以最小化提交推回。所有命令均能在仓库中逐一验证:
| 环节 | 命令 | 仓库证据 |
|---|---|---|
| 编译 | yarn nx run-many -t compile |
nx.json 中 compile target、scripts/build/build-package.ts 构建脚本 |
| Lint | yarn lint |
package.json 与 code/package.json 中的 oxlint 脚本链 |
| 类型检查 | yarn nx run-many -t check |
scripts/check/check-package.ts、scripts/check/utils/typescript.ts |
| 严格模式 | — | code/tsconfig.json 的 strict 配置 |
需要注意适用前提:该工作流依赖 Storybook 仓库的 Nx 目标命名(compile / check)、Yarn 4 包管理器与 gh CLI 环境,移植到其他 monorepo 时需按其脚本体系做相应替换。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00