mcpField
S
sanity-studio-upgrade

sanity-studio-upgrade

github.com/sanity-io开发194556 次安装1 天前更新
代码仓库

关于 sanity-studio-upgrade

为 Sanity Studio v3 及更高版本的升级生成计划,适用于维护 Sanity 项目的开发者。它根据仓库实际情况筛选变更,并要求只读检查、核实版本与区分已确认事项和待答问题。

主要功能

  1. 01按仓库情况筛选升级变更
  2. 02从锁文件和注册表核实版本
  3. 03只读检查,不修改项目文件
  4. 04区分已确认事项与人工问题
  5. 05检测 v2 项目并停止规划

适用场景

  1. 01准备 Sanity Studio v3 及后续版本升级
  2. 02检查升级建议是否适用于当前代码库
  3. 03识别需要人工确认的迁移问题

安装

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

$npx skills add https://github.com/sanity-io/agent-toolkit --skill sanity-studio-upgrade

安装后在 Claude Code 中输入/sanity-studio-upgrade确认已加载。

包含的文件

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

references/
boundaries.md
boundary.v4.md
boundary.v5.md
boundary.v6.md
deprecations.md
detect.md
package-coupling.md
plugins.md
report-template.md
version-lookup.md

详细介绍

Sanity Studio 升级规划器

为当前仓库中的 Sanity Studio 生成升级计划。

这份计划的价值在于删减。两个版本之间的所有破坏性变更已经列在变更日志中,而这对正在升级的用户并无帮助。此技能会生成一份精简得多的清单,只包含适用于此仓库的变更,以及只有人类才能回答的问题。

决定输出是否可信的三条规则

1. 绝不要凭记忆写出版本号。先查证,并确认该版本确实存在。

软件包版本每周都会变化。报告中的每个版本都必须来自仓库的锁定文件(当前状态)或实时注册表查询(目标版本)。如果无法查询,请在报告中说明,不要猜测。报告中写出过时的“最新”版本,比不提供计划更糟,因为读者会据此采取行动。

还有一种更糟糕的情况:假设某个软件包的版本号与另一个软件包同步,结果写出了从未发布过的版本号。这种版本无法安装。凡是要描述为“同步版本”或“与核心包版本一致”的版本,都必须先确认其确实存在。

API 名称也一样。凭记忆写出的导出项、导入子路径或函数签名都是猜测,而读者会把这些内容直接粘贴到编辑器中。请从软件包的 README 或 exports 映射中查证,或者在代码片段本身加上行内 // VERIFY: 注释。请参阅 plugins.md 的第 6 节和 report-template.md 的第 8 节。

2. 只读和报告,绝不修改。

检查文件,运行只读 Shell 命令,查询注册表。不要编辑 package.json、配置文件或源代码。由读者决定要改什么;如果规划器修改代码,就会被停用。如果用户之后明确要求你执行升级,那是另一项他们已同意的任务。

实际界限如下,因为对这条规则含糊其辞,会让 Agent 对本可安全运行的命令犹豫不决:

  • 绝不允许:写入仓库中的任何文件、向仓库安装内容,或修改锁定文件。pnpm install、npm install、npm ci 和不带 --no-install 的 npx 都不允许。
  • 可以:读取文件,以及进行网络只读操作,例如运行 npm view、获取变更日志,或在仓库外的临时目录中运行 npm pack,之后再删除该目录。
  • 建议读者执行,但不要由你执行:pnpm install --lockfile-only 可以用来确认依赖预测。应将它作为供读者运行的命令写入报告,并说明预期结果。不要自行运行,因为它会改写读者的锁定文件。

此技能唯一会写入内容的操作,是解包 tarball 以检查类型声明;plugins.md 的第 6 节说明了如何在项目外完成此操作。

3. 区分已查证的内容和推断。

每项发现都归入以下三类之一:已确认适用(你在仓库中找到了相应条件)、需要人工回答(无法从代码中判断),或不适用(完全省略)。绝不要用无法查证的内容凑数。诚实而简短的报告,胜过看似面面俱到的报告。

有一点很容易忽略,值得明确说明:**只读规划器没有依赖解析器,因此无法知道变更后依赖树会包含什么。**关于去重的预测,应作为预期写入报告,并附上验证命令,而不能作为已确认的发现。请参阅 package-coupling.md。

验证规则,一处说明

参考文件中会按编号引用这些规则,因此在此统一说明,不再在各处重复。以上内容对应 R1 至 R4;其余规则则针对这些规则可能出错的具体情况。

规则适用位置
R1绝不凭记忆陈述版本。当前状态以锁文件为准,目标版本通过实时查询注册表获取。version-lookup.md §1
R2读取并报告。不得更改仓库中的任何内容,不得安装任何内容,也不得修改锁文件。以上,以及 plugins.md §6
R3区分已验证内容与推断内容。绝不声称变更后依赖树会包含什么;规划器没有解析器。package-coupling.md §6、plugins.md §5
R4每个推荐版本在写入报告前,都必须确认它已实际发布。version-lookup.md §3
R5每个“X 要求 Y”都必须注明所读取的清单,以及该清单对应的安装版本。要求不会跨主版本沿用。version-lookup.md §6
R6评估版本范围,绝不直接读取。凡包含 ||、< 或单个子句中有两个比较运算符的内容,都必须先交给 semver.satisfies 处理。version-lookup.md §6
R7导出列表中的名称不代表导出可用。检查其声明类型和任何 @deprecated 标记;never 表示已移除。plugins.md §6

R6 和 R7 之所以存在,是因为它们都曾导致自信却错误的具体建议:把实际兼容的 Node 版本报告为不受支持,以及将必须进行的代码修改归入“已满足”。执行这些检查成本很低;跳过时,错误却不会显现。

范围:v3 及更高版本

此技能用于规划从 Studio v3 开始的升级。Studio v2 不在适用范围内,必须立即停止处理。

原因并不是 v2 很难,而是从 v2 升级到 v3 属于 Studio 配置和插件层的重写,而非依赖升级:配置格式发生了变化,v2 插件和覆盖项所依赖的“parts”系统已不复存在,软件包经过了整合,而且 v2 时代的许多插件生态从未迁移。针对这个升级边界生成计划,只会列出听起来很有把握、但此技能无法验证的具体内容,然后交给即将为此投入数周时间的人。这是最糟糕的结果。

如果检测到 v2,请停止并报告,而不是继续规划。第 1 步会说明如何检测以及该怎么说。不要为 v2 项目编写计划文件。

流程

步骤 1:确认事实依据,并检查版本下限

阅读 references/detect.md 并按其中说明操作。该文件列出了要读取的文件、要运行的命令,以及要记录的事实。

最常见的错误是从 package.json 读取版本。插入符范围不等于已安装版本。请从锁文件中获取解析后的版本。

第二常见的错误是从错误的锁文件读取版本。一个代码库可能包含多个安装树,且它们的版本可能不一致。因此,请先确定计划针对哪个依赖树,从该依赖树中获取所有版本信息,并在报告标题中注明它。

如果此代码库中没有 Sanity Studio,请说明这一点并停止。

然后,在做任何其他事情之前检查版本下限。 如果解析后的 sanity 主版本低于 3,或者没有 sanity 包且项目依赖 @sanity/base 或 @sanity/desk-tool 等 v2 时代的包,或者存在 sanity.json 但不存在 sanity.config.*,则这是一个 v2 项目。请在此处停止,并告知读者:

  1. 你检测到了什么,以及相应证据
  2. 此技能适用于 v3 及更高版本,并说明为什么从 v2 迁移到 v3 属于不同类型的项目:需要重写配置和插件层,而不是升级版本
  3. 合适的起点是官方 v2 到 v3 迁移指南;读者应前往 Sanity 文档网站查找,而不是听你转述
  4. 每个 v2 时代的插件都需要单独检查兼容性,因为许多插件从未移植
  5. 升级到 v3 后,再次运行此技能即可规划剩余的升级跨度,这项工作会小得多

请提供有用的信息。说明原因并指明下一步的明确终止是好的回答;拒绝回答则不是。但不要把它软化成部分计划,也不要估算从 v2 到 v3 的工作量。

如果同时存在 sanity.json 和 sanity.config.*,则以解析后的 sanity 版本为准。如果一个除此之外为 v3 及更高版本的项目中遗留了 sanity.json,值得将其作为清理事项提及,但不应因此停止。

步骤 2:确定升级跨度

你需要两个版本:起始版本(解析后、已安装)和目标版本。

阅读 references/version-lookup.md,了解如何权威地查询当前版本和变更日志。

目标版本为 latest。 请推荐该版本并说明理由。只升级一小段意味着做完全部工作后仍然落后;更重要的是,当前插件版本会跟随当前核心版本,因此,使用较旧的核心版本搭配当前插件,通常会导致比最新版本更差的依赖树。报告目标版本的发布日期,并给出一条备用方案,让读者在应用你无法获知的约束时参考;这是信息披露,不是保留意见,也不会改变推荐。只有在读者明确提出约束时才偏离此建议,并为固定的版本指定复查日期。

在报告中明确写出升级跨度。v3 项目和从 v5.31 升级的项目完全不同,读者需要知道自己属于哪种情况。

步骤 3:只加载你会跨越的边界

先阅读 references/boundaries.md。这是一个简短索引:其中包含覆盖范围、两端边界的读取规则,以及标明跨度需要哪些边界文件的表格。

然后只读取这些文件。 边界内容按主版本拆分,每个版本对应一个文件,因此,跨越一个边界的跨度只需加载一个文件,而不是全部文件。从 5.31 升级到 v6 的项目需要读取索引、boundary.v6.md 和 deprecations.md,除此之外不需要读取其他内容:v4 和 v5 文件会占用上下文,并引入不适用的检查结果。

每个 boundary.v*.md 都包含进入该主版本时的变更,以及该主版本系列内部未声明的变更,因为跨越边界的跨度会落在上一系列版本中,需要同时了解这两类变更。

然后阅读 references/package-coupling.md。它适用于所有跨度。

第 4 步:获取参考资料未涵盖的内容

references/boundaries.md 声明了其范围内覆盖上下限的两项限制,必须同时遵守。

对于跨度中高于上限或低于下限的部分,获取相应的变更日志。项目起始版本低于下限时,需要获取两段内容:从当前版本到该下限,以及从上限到目标版本。经过筛选的中间部分直接使用。

下限和上限同样重要,而且下限更容易被忽略。没有下限,你就会把文件当作依据,用于它从未检查过的范围,并报告其中没有适用内容;这看起来像是经过核实的结论,实际上却是未经检查的空白。除非某个范围位于声明的上下限之内,或你亲自获取了该范围并得到实际内容,否则绝不要声称该范围没有问题。

这最后一条绝非赘言。低于下限的部分根本没有上游变更日志,因此获取结果几乎为空,获取结果为空不代表该范围没有问题。 boundaries.md 会说明这会影响哪些范围,以及应如何报告。在这种情况下,把沉默报告成“没有适用内容”,是这项技能最容易产生自信谎言的方式。

尤其要留意在 minor 版本中发布、却未标记为重大变更的破坏性变更。它们最容易让人措手不及,因为没人会逐一阅读跨越 40 个版本的 minor 版本说明。参考资料列出了已知示例;请假定还有更多。

第 5 步:测试适用性

对于每项候选变更,在仓库中查找其适用条件。如果无法从代码中确定,就将它放入人工确认问题部分,而不是调查结果中。

以下示例说明了两者的区别:

  • “自定义身份验证提供程序现在会替换内置提供程序,而不是追加” → 用 grep 检查配置中是否有 auth 块。存在或不存在。可以确定。
  • “默认搜索策略已更改,结果会有所变化” → 这是否重要取决于编辑器如何搜索。无法确定。请提出问题。

优先选择你确实能够评估的条件。grep -r "data-slate" 是一项真实测试。“你们有复杂的自定义组件吗?”则不是。

第 6 步:解析依赖关系图

应用 references/package-coupling.md 中的说明。大多数升级问题都发生在这里,而变更日志无法告知你这些问题,因为它们取决于该项目直接依赖哪些包。

最重要的规则:对于项目直接依赖的任何 @sanity/* 包,检查目标 sanity 版本依赖的版本,并与之匹配,而不是使用该包自己的 latest。对于 @sanity/ui 这类共享包使用 latest,会让同一依赖树中出现两个主版本,从而导致重复上下文错误和样式缺失的组件,看起来像是彼此无关的 bug。

第 6b 步:评估插件

阅读 references/plugins.md,并在项目含有任何插件时遵循其中的说明;这种情况几乎总是存在。

相比 Studio 本身,插件更容易阻碍升级,因此需要单独检查,并在报告中单独列出。请牢记以下三点:逐一核实每个插件的兼容性,不要仅凭发布者是谁就假定其兼容;当插件不兼容时,让维护归属决定路径,而不是决定结论;并且,对你准备建议的任何代码片段,除了核实版本之外,还要单独核实其 API 结构,因为兼容版本仍可能已经重命名了你准备推荐的导出项。

第 7 步:撰写报告

严格遵循 references/report-template.md。除非用户指定其他路径,否则将报告写入仓库根目录下的 SANITY-UPGRADE-PLAN.md。

请写入文件,不要只打印到终端。升级计划通常需要传达给不在这台设备前的人:负责人、审查者、支持工程师。文件可以加入拉取请求,也可以粘贴到讨论串中;终端输出则不行。

值得明确说明的判断

建议按顺序升级,而不是一步到位。 在一次提交中跨越多个主版本,会让人无法确定故障的来源。建议在每个主版本的最后一个发行版处设置中间停靠点,并说明原因:这样可以隔离每一组变更。

但只有能够到达的停靠点才算数。每个停靠点都需要解析好对应的插件版本,因为如果某个插件只兼容较新的主版本,就可能导致无法安装某个中间版本。如果无法解析某个停靠点,应将其标记为暂定,而不要把整个序列说成已经验证。经过验证的停靠点宁少勿假。

跳过停靠点时,要说明代价。 跳过某个停靠点通常是正确的:如果某个边界唯一相关的变更只是提高 Node 版本下限,就不值得单独为它提交一次;如果某个停靠点只有强制引入重复主版本才能到达,那还不如不设停靠点。但这样一来,接下来的升级就会一次跨过两个边界,而这正是设置升级序列要避免的情况。只展示跳过的依据,却不说明后果的计划,会让人觉得这笔取舍没有代价。

所以要把两方面都说清楚:为什么跳过这个停靠点,以及合并后的升级若失败,问题可能来自任一边界,因此调试时需要二分定位,而不能只看计划。这一句就够了。读者看清这笔取舍后,才能决定是否接受。

如实评估工作量。 如果项目只有两个文件导入了 @sanity/ui,且没有自定义身份验证,就说明这次升级工作量很小。为了显得周全而夸大范围,只会浪费读者一周时间。同样,如果项目从 sanity/_internal 导入内容,或有大量自定义组件,就应说明这次升级工作量很大,而不是写出一份把难事说得轻而易举的计划。

让计划经得起快速浏览。 读者一定会快速浏览。一份跨越多个边界的计划可能长达几千字,而读者即将用一周时间完成这项工作,不会花一个下午仔细研读文档。因此,计划开头应让读者在一屏内掌握全貌,后续内容则作为参考,等工作推进到相应阶段再查阅;发现的问题应按读者需要采取的行动分组,而不是按变更来自哪个发行版分组。要特别避免这种情况:一项会悄无声息地导致故障的变更,夹在两个外观方面的变更之间,表格中视觉权重完全相同。长度不是问题,权重一视同仁才是。

为实际执行工作的工程师撰写,描述代码库,而不是团队。 这类计划通常由客户方的人员阅读,而他们往往不是当初做出当前决策的人。证据、细节和严重程度都应与事实所支持的程度完全一致:淡化真实的阻碍或真实的成本无济于事,工程师也看得出来。应删除的是暗含的评判。“部署流水线根据 caret 版本范围构建,而不是依据锁文件构建”和“当初配置这一切的人搞错了”表达的是同一项发现,但只有前者会促成行动。只在说明下一步该做什么时使用“你”。内容也应始终围绕升级:未使用的依赖不属于升级发现,而偏离主题、变成泛泛代码审查的计划,会把读者的注意力耗费在不会阻碍升级的事情上。

说明你无法查明的内容。 单体仓库中常有隐藏信息:例如,tsconfig.json 继承了仓库外的基础文件、工作区根目录提升了 React,或 CI 配置位于其他目录。如果某项必要事实无法查明,就在“需要人工确认的问题”一节中点名说明。“我无法读取 moduleResolution,因为你的 tsconfig 继承了仓库外的文件”很有用。默默略过则不可取。

不要对路线图作出承诺。 如果有人问某个已弃用的 API 会否恢复或移除,只需描述它当前有文档说明的状态,然后就此打住。切勿推测未来发行版的情况。

参考文件

文件何时阅读
references/detect.md始终在第 1 步阅读
references/version-lookup.md始终在第 2 步和第 4 步阅读
references/boundaries.md始终在第 3 步阅读。索引:覆盖范围边界以及需要阅读哪些边界文件
references/boundary.v4.md第 3 步中,如果范围跨入 v4 或位于 v4 中,则阅读
references/boundary.v5.md第 3 步中,如果范围跨入 v5 或位于 v5 中,则阅读
references/boundary.v6.md第 3 步中,如果范围跨入 v6 或位于 v6 中,则阅读
references/deprecations.md第 3 步中始终阅读。内容简短,且不与任何边界关联
references/package-coupling.md始终在第 6 步阅读
references/plugins.md第 6b 步中,项目含有插件时阅读
references/report-template.md阅读第 7 步

评论

支持 Markdown