关于 migration
面向 AEM 开发者的迁移技能,协助将 AEM 6.x、AMS 或本地部署项目迁移到 AEM as a Cloud Service。它按单一迁移模式组织工作,并可先生成只读迁移运行手册。
主要功能
- 01按迁移模式逐项处理
- 02读取 BPA CSV 或从 CAM 获取发现项
- 03生成只读迁移运行手册
- 04支持手动文件迁移
- 05扫描并验证迁移改动
适用场景
- 01评估整个项目的云服务迁移工作
- 02根据 BPA 报告修复指定模式
- 03将 OSGi 配置转换为 Cloud Manager 变量
- 04迁移 Dispatcher 配置或旧版对话框
MCP 相关
可通过 MCP 从 CAM 获取项目和迁移发现项;验证流程也可借助 AEM Quickstart MCP 检查本地 SDK 状态。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ adobe/ skills --skill migration安装后在 Claude Code 中输入/migration确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.mdreferences/cam-mcp.mdguava-cache.mdinput-stream.mdoak-index.mdosgi-cfg-json-cloud-manager.mdvault-package-dependencies.mdreferences/dispatcher/config-generation.mdcontext.mdconversion-patterns.mdcross-boundary.mdcurrent-sdk-conventions.mdoutput-verification.mdvalidation.mdreferences/legacy-ui/cdw/context.mdconversion.mdvalidation.mdreferences/legacy-ui/dialog/context.mdcoral2-to-coral3.mdextjs-to-coral3.mdvalidation.mdreferences/template-modernization/aem-modernization.mdeditable-template-creation.mdtemplate-modernization-context.mdtemplate-modernization-validation.mdreferences/validation/custom-templates.mdvalidate-migration.mdresources/tika/config.xmlscripts/.gitignoreanalyzer-runner.js详细介绍
AEM as a Cloud Service — 代码迁移
来源 → 目标: Legacy AEM 6.x / AMS / on-prem → AEM as a Cloud Service。范围限定在 skills/aem/cloud-service/skills/migration/ 下,以免与 Edge Delivery 或 6.5 LTS 混淆。
此技能负责迁移工作流:BPA 数据、CAM/MCP、每次会话处理一种模式以及目标发现。转换规则和步骤位于 code-assessment 技能中——识别出某项发现所属的模式后,将任务交给 {code-assessment}/<pattern>/SKILL.md(或 {code-assessment}/references/ 下的相关共享参考资料)。
设置: 使用 aem-cloud-service 安装方式(参见仓库根目录中的 README),以便使用 migration 和 code-assessment 路径。如果你已经打开了 monorepo,且 {code-assessment} 路径可以解析,则无需单独安装。
快速入门(适用于负责驱动 Agent 的人员)
每次聊天/会话处理一种模式——如果你要求“修复所有问题”,此技能会先要求你选择(例如,scheduler、replication 或 htlLint)。
| 你有…… | 可以这样说…… | 会发生什么 |
|---|---|---|
| 需要评估整个项目 | "Review my code for AEMaaCS migration" | 生成只读的 migration-runbook.md — 包含所有迁移模式(Java 级联 + htlLint + osgiConfig)、受影响的文件和示例提示词。不会修改文件。 |
| BPA CSV | "Fix scheduler findings using ./path/to/bpa.csv" | 最快的方式:CSV → 缓存的集合 → 文件 |
| 仅有 CAM + MCP | "Get scheduler findings from CAM; I'll pick the project when you list them." | Agent 列出项目 → 你确认 → MCP 获取 (cam-mcp.md) |
| 只有几个文件 | "Migrate scheduler in core/.../MyJob.java" | 手动流程:无需 BPA |
| OSGi → Cloud Manager | "Scan my config files and create Cloud Manager environment secrets or variables." | Agent 自动读取 references/osgi-cfg-json-cloud-manager.md(其中内联了完整的 Adobe 对齐规则);无需 BPA 模式 ID |
| HTL lint 警告 | "Fix htlLint issues in ui.apps" | 通过 rg 主动发现 → 按照 HTL lint 参考文档修复 |
| Vault 包依赖项 | "Fix vault-package-dependencies findings" / "Package install fails on AEMaaCS." | Agent 读取 references/vault-package-dependencies.md — 使用启发式方法扫描 pom.xml(无 BPA 子类型,无分析器),查找 content-package-maven-plugin 中 day/cq60/product:* 安装时依赖项;移除整个 <dependencies> 块。这不是 code-assessment 模式 — 这种依赖结构不会出现在原生 AEMaaCS 代码中。 |
| Oak 索引问题(OID) [BETA] | "Fix oakIndex findings using ./path/to/bpa.csv" — 涵盖 index.rule.violation 和 standard.index.modification | 按照 references/oak-index.md 调用 Adobe 的 @adobe/aem-cs-source-migration-index-converter;计算下一个可用的 -custom-N,而非默认使用 -custom-1;在 IDE 中显示差异并检查类型兼容性;使用 mvn 和 aemanalyser 验证。分支 F。 |
| 模板现代化 | "Migrate my static templates to editable templates and generate Modernize Tools rules." / "Create editable templates from my static templates." / "Generate AEM Modernize Tools structure/component/policy rules." | Agent 自动读取 references/template-modernization/template-modernization-context.md(共享的发现与结构化上下文),生成逐模板计划表,然后使用 editable-template-creation.md 和 aem-modernization.md 执行计划,并通过 template-modernization-validation.md 验证。无需 BPA 模式 ID。 |
| 对话框迁移 | "Convert my Classic UI / ExtJS dialogs to Touch UI." / "Upgrade Coral 2 dialogs to Coral 3." / "Fix LUI dialog findings." | Agent 读取 references/legacy-ui/dialog/context.md — 筛选 BPA LUI 中的对话框子类型,通过 extjs-to-coral3.md 或 coral2-to-coral3.md 进行转换,并通过 validation.md 验证。BPA 模式 ID:lui。 |
| 自定义组件迁移 | "Fix my CDW findings." / "Migrate custom ExtJS widgets to Coral 3." | Agent 读取 references/legacy-ui/cdw/context.md — 清点 xtype,通过 conversion.md 映射或搭建 Granite UI 组件框架,并通过 validation.md 验证。BPA 模式 ID:cdw。如果两种迁移都需要,先运行 CDW,再迁移对话框。 |
| Guava 缓存警告 | "Fix guavaCache findings using BPA CSV." / "Swap Guava cache for Caffeine." | Agent 读取 references/guava-cache.md — BPA 是事实来源(子类型 custom.guava.cache);每个包对应一个问题,而不是每个 Guava 内部类行对应一个问题。BPA 模式 ID:guavaCache。这不是 code-assessment 模式 — Guava 缓存用法只会出现在迁移前的代码中,不会出现在原生 AEMaaCS 代码中。 |
| InputStream 提示 | "Fix inputStream findings." / "Triage the java.io.InputStream warnings in my BPA report." | Agent 读取 references/input-stream.md,并运行确定性扫描器 scripts/input-stream-runner.js(纯 Node)。Adobe 将风险描述为通过 JVM 流式传输二进制数据,解决方法是直接上传二进制数据并通过 CDN 交付。扫描器按风险排序,为每个文件生成一个问题,并为每个流使用点预先分类(F 反序列化 / E 在 JVM 中流式传输或处理二进制数据 / D 本地文件系统 / C 无界读取 / B 流未关闭或 Binary 未释放 / A 无害),并标注修复类型(decision / review / auto)。与其他 BPA 模式采用相同的优先顺序:先处理 BPA 问题(CAM,然后是 BPA CSV,子类型 java.io.inputstream);扫描器会将其中的类解析为工作区文件,以定位到行级位置;工作区之外的类则合并为每个包一条信息提示(客户代码保存在其他位置、平台提供的 AEM Forms 附加组件或第三方代码);只有在 BPA 没有 inputStream 问题时,才扫描整个工作区。Agent 针对 D/E/F 提出分级修复方案,修复未关闭的流,并通过 --files 扫描重新验证每项修改。BPA 模式 ID:inputStream。这不是 code-assessment 模式,因为 BPA 只会针对从旧版 AEM 延续而来的代码报告该问题。 |
| Dispatcher 转换 | "Convert my AMS / on-prem Dispatcher config to AEM as a Cloud Service." | Agent 读取 references/dispatcher/context.md — 检测配置模式、生成工具配置、运行 Adobe 的 dispatcher-converter、验证输出(filter/ACL 为硬性门槛),并进行验证。分支 E。 Runbook 模式 ID:dispatcherConversion(启发式)。 |
| 验证迁移 [BETA] | "Validate my migration on the local Cloud SDK." / "Verify the scheduler fix before I raise a PR." | Agent 读取 references/validation/validate-migration.md — 构建项目,将其部署到正在运行的本地 SDK,通过 AEM Quickstart MCP 检查包和组件状态,并在关联了项目时向 CAM 报告结果。分支 G。 |
| 入门提示词(复制粘贴) — 上方的快速入门表分别介绍了每种模式;以下提示词补充了整个项目的入口、针对特定来源的调用(CSV / CAM / 手动),以及多步骤组合: |
- “审查我的代码是否适合迁移到 AEMaaCS” — 进行任何更改前,完整执行手册请从这里开始。
- “使用迁移技能:仅迁移 scheduler,BPA CSV 位于
./reports/bpa.csv。” - “仅从 CAM 迁移 Replication;先列出项目,我来选一个。”
- *“**手动:*迁移
.../Listener.java的 event listener。” - “使用位于
./reports/bpa.csv的 BPA CSV 修复 oakIndex 发现的问题。” - “修复所有 Classic UI 和自定义 widget 发现的问题——先处理 CDW,再处理 dialogs。”
- “使用位于
./reports/bpa.csv的 BPA CSV 修复 guavaCache 发现的问题。” - “使用位于
./reports/bpa.csv的 BPA CSV 修复 inputStream 发现的问题。”
路径约定(Adobe Skills 单体仓库)
从仓库根目录(skills/ 目录的父目录)开始:
| 符号 | 路径 |
|---|---|
{code-assessment} | skills/aem/cloud-service/skills/code-assessment/ |
示例:{code-assessment}/SKILL.md、{code-assessment}/scheduler/SKILL.md、{code-assessment}/references/scr-to-osgi-ds.md。
工作区范围(IDE)— 仅用户代码
适用于查找和编辑用户的 AEM 项目(Java、bundles、配置、HTL),不适用于读取 {code-assessment} 下已安装的技能文件。
- 将当前 IDE 工作区根文件夹(单根或多根)视为搜索、glob、
grep以及迁移目标文件读写的唯一边界。 - 除非用户明确指定这些路径,或要求将其纳入范围,否则不要搜索父目录、磁盘上的同级文件夹、
~、其他克隆或任意绝对路径来“发现”源文件。 - **BPA CSV / CAM 目标:**如果
filePath或类到文件的映射无法解析到工作区根目录下,请停止并告知用户缺失的路径——不要在文件系统的其他位置寻找。请用户在 IDE 中打开正确的项目,或调整路径。 - **手动流程:**仅迁移用户指定且位于工作区内的文件(或用户明确提供路径的文件)。不要通过搜索工作区之外的内容来扩大范围。
必须委派(首先执行)
分支 A — OSGi 配置 → Cloud Manager(本次会话没有 Java BPA 模式):如果用户要求扫描配置文件、创建 / 设置 Cloud Manager 环境密钥或变量、将密码或密钥从 OSGi / .cfg.json / ui.config 中移出,或提到 AEM CS 的 $[secret:] / $[env:],则立即阅读 references/osgi-cfg-json-cloud-manager.md,并遵循该文件中定义的产品规则和工作流(文件中重现了 Adobe AEM as a Cloud Service OSGi + Cloud Manager 的行为——无需外部文档 URL)。简洁的提示词即可,无需提及参考文件。处理此类工作时,跳过分支 B。
分支 B — Java / HTL / BPA 模式迁移:
- 阅读
{code-assessment}/SKILL.md——关键规则、Java 基线链接、模式指南表格、手动模式提示。 - 阅读单个当前模式的模式指南(或参考文档):
scheduler→{code-assessment}/scheduler/SKILL.md(模式指南)resourceChangeListener→{code-assessment}/resource-change-listener/SKILL.md(模式指南)replication→{code-assessment}/replication/SKILL.md(模式指南)eventListener/eventHandler→{code-assessment}/event-migration/SKILL.md(模式指南——包含 JCR 和 OSGi Event Admin 两种路径)assetApi→{code-assessment}/asset-manager/SKILL.md(模式指南)htlLint→{code-assessment}/references/data-sly-test-redundant-constant.md(参考文档——HTL lint 使用单个共享参考文档,而非专用模式指南)vault-package-dependencies→ references/vault-package-dependencies.md (参考文档——启发式 pom.xml 扫描;仅位于migration下,不在code-assessment下,因为这种依赖形式不会出现在原生 AEMaaCS 代码中)guavaCache→ references/guava-cache.md (参考文档——将 Guava 缓存替换为 Caffeine;仅位于migration下,不在code-assessment下,因为原生 AEMaaCS 代码中不会使用 Guava 缓存,只会在从旧版 AEM 迁移的代码中出现)inputStream→ references/input-stream.md (参考文档——针对DG/java.io.inputstream公告的java.io.InputStream分类与修复;仅位于migration下,不在code-assessment下,因为 BPA 仅会针对从旧版 AEM 迁移的代码报告此项。检测由 migration 内的扫描器scripts/input-stream-runner.js执行,而非由 code-assessment 分析器执行)
- 如果代码使用 SCR、
ResourceResolver或控制台日志记录,请阅读{code-assessment}/references/scr-to-osgi-ds.md和{code-assessment}/references/resource-resolver-logging.md(或中心文档{code-assessment}/references/aem-cloud-service-pattern-prerequisites.md)。
在阅读模式指南(或参考文档)之前,不要转换 Java 或 HTL(分支 B)。分支 A 不需要 {code-assessment} 模式指导。
分支 C——模板现代化(无 BPA):静态模板 → 可编辑模板,和/或 AEM Modernize Tools 规则(结构/组件/策略)。分三个阶段:上下文 → 逐个模板执行 → 验证。从 references/template-modernization/template-modernization-context.md 开始;生成器位于 editable-template-creation.md 和 aem-modernization.md;生成后的检查见 template-modernization-validation.md。跳过分支 B。
分支 D——旧版 UI 迁移(legacy-ui/ 子文件夹):如果用户要求转换 Classic UI / ExtJS 对话框、升级 Coral 2 对话框、迁移自定义 ExtJS 组件、修复 LUI 或 CDW BPA 发现项,或提及 cq:Dialog / xtype / cq:Widget:
- 对于对话框发现项(仅限
lui模式、legacy.dialog.classic或legacy.dialog.coral2):- 阅读 references/legacy-ui/dialog/context.md——使用
getBpaFindings('lui', …),筛选对话框子类型,并附注跳过所有其他项。 convert-extjs→ references/legacy-ui/dialog/extjs-to-coral3.md。upgrade-coral2→ references/legacy-ui/dialog/coral2-to-coral3.md。- 验证:references/legacy-ui/dialog/validation.md。
- 阅读 references/legacy-ui/dialog/context.md——使用
- 对于自定义组件发现项(
cdw模式):- 阅读 references/legacy-ui/cdw/context.md —
getBpaFindings('cdw', …),盘点 xtypes。 - 针对每个 xtype:阅读 references/legacy-ui/cdw/conversion.md(应用映射或搭建 Granite UI 组件脚手架)。
- 验证:阅读 references/legacy-ui/cdw/validation.md。
- 如果相同组件也有 LUI
legacy.dialog.classic发现项,请在此后运行对话框迁移 — 现在所有 xtype 都已解决。
- 阅读 references/legacy-ui/cdw/context.md —
两者都需要时的运行顺序:先 CDW,再对话框。 CDW 会解决自定义 xtype,让对话框转换能够顺利进行。跳过分支 B。跳过分支 C。
分支 E — Dispatcher 转换(AMS / 本地部署的 Apache httpd + Dispatcher → AEMaaCS;本次会话没有 Java BPA 模式):
如果用户要求将 Dispatcher 配置转换 / 迁移到 AEM as a Cloud Service,请遵循六阶段流程。该流程将 Adobe 维护的 @adobe/aem-cs-source-migration-dispatcher-converter 用作转换引擎,并在此基础上添加检测、配置生成、输出验证、判断和校验。首先阅读 references/dispatcher/context.md。跳过分支 B。
- 盘点 — 运行
scripts/dispatcher-inventory.js(buildInventory),检测模式(standard/flexible/ams/already-cloud/not-dispatcher/v1/unknown),并统计过滤器 / 重写 / 缓存规则。(ams是单体 AMS 本地部署配置——使用与flexible相同的本地执行器进行转换,只是如实标注。)模式和信号定义见 references/dispatcher/context.md。如果模式为already-cloud、not-dispatcher或unknown,则在此处停止并说明发现:前两种无需转换,而unknown表示布局有歧义或不完整,应先向用户确认,再运行不检查内容的工具(resolveExecutor会将unknown传递给本地执行器,因此这里由 Agent 把关)。 - 规划并生成
config.yaml— 按照 references/dispatcher/config-generation.md 构建转换器配置(按模式映射;variablesToReplace是扁平映射,portsToMap是列表,appendToVhosts是文件路径)。 - 执行 — 运行
ensureToolInstalled(首次使用时会将 Adobe 工具自动安装到被 git 忽略的scripts/dispatcher-tool/node_modules/),然后运行runConverter(scripts/dispatcher-run.js);按模式选择执行器(standard→main.js,flexible/ 本地部署 →singleFileMain.js)。 - 验证并规范化 — 运行
scripts/dispatcher-verify.js,并按照 references/dispatcher/output-verification.md 处理。遇到filter-acl-loss(基线中有过滤器规则,但filters.any为空)时,必须停止:解决此问题后,转换结果才能使用。 - 判断并处理跨边界事项 — 按照 references/dispatcher/conversion-patterns.md 中的决策目录处理;将所有 Cloud Manager 环境变量交给分支 A(OSGi → Cloud Manager);标记 CDN 候选规则。目标最终状态的约定见 references/dispatcher/current-sdk-conventions.md。为落实交接,运行
scripts/dispatcher-crossboundary.js,以生成 Cloud Manager 变量交接产物,然后按照 references/dispatcher/cross-boundary.md 分流各项事宜——CM 变量 → 分支 A;不可变新鲜度 →dispatcher技能的sdk(diff-baseline);安全标头 / 边缘 →security-hardening;验证 →config-authoring。 - 验证 — 按照 references/dispatcher/validation.md 验证转换后的
src(委托给dispatcher技能的 SDK 验证器和防护规则);持续迭代,直到验证通过。验证失败时,不得将结果称为已完成。验证通过后,运行scripts/dispatcher-report.js(renderReport→writeReport)生成汇总报告conversion-report.md,其中包含覆盖率统计、CM 交接事项和委托的后续检查清单。
分支 F — Oak 索引迁移(旧版 _oak_index/*.xml → 与 AEM as a Cloud Service 兼容的 Oak 索引定义;BPA 模式 ID oakIndex,类别 OID):
Beta:Oak 索引迁移(分支 F)目前处于 beta 阶段,仍在积极开发中。使用其处理生产环境中的索引定义前,请仔细检查输出结果,尤其是第 4 步中的类型 / 数据类型兼容性检查。
如果用户要求修复 Oak 索引问题 / 转换 _oak_index 定义,使其适用于 AEM as a Cloud Service,请遵循 references/oak-index.md 中的 6 步流程。该流程以 Adobe 维护的 @adobe/aem-cs-source-migration-index-converter 作为转换引擎,并在此基础上增加检测、动态 -custom-N 命名覆盖、类型兼容性检查和验证。跳过分支 B。
- 检测 — 查找
_oak_index/目录;根据项目的pom.xml确定aemVersion(63/64/65/Cloud_Services)。 - 确定下一个
-custom-N— 在使用工具的默认值-custom-1之前,扫描目标状态中是否已有<baseName>-custom-<n>同级索引;之前的迁移或客户自有的-custom-N索引会导致重用-custom-1时发生冲突,而不是生成新名称。 - 执行 — 通过
npx解析 Index Converter,并按 references/oak-index.md 调用。 - 差异 + 类型兼容性检查 — 显示转换后的输出与输入之间的差异;验证
oak:isOakIndexDefinition/type完整无损,并确认旧定义与转换后的定义中每个属性的 JCR 值类型一致。发现任何不匹配时,标记为needs_manual_review: datatype mismatch on <propertyName>— 不要默默应用。 - 应用(经用户确认后)— 将工具输出复制到仓库中,并应用步骤 2 中计算出的名称覆盖值(如有)。
- 验证 — 执行
mvn -pl ui.apps clean install,然后在已配置的情况下执行mvn -pl all aem-analyser:project-analyse。提供带有文件:行号证据的 PASS/FAIL 结果。
分支 G — 验证迁移(迁移分支之后,或按需执行;本次会话没有 BPA 模式):
Beta:迁移验证(分支 G)仍处于 beta 阶段,且正在积极开发中。PASS 表示强烈的正向信号,但并非保证 — 在创建 PR 或部署到 Cloud Manager 环境之前,请检查报告。
如果用户要求在本地 Cloud SDK 上验证 / 核验 / 冒烟测试迁移后的代码,请阅读 references/validation/validate-migration.md 并按其中步骤执行。它绝不会编辑客户源代码;失败项应交回负责该模式的分支。跳过分支 B。
何时使用此技能
- 将旧版 AEM Java 迁移为符合 Cloud Service 兼容模式(scheduler、ResourceChangeListener、replication、EventListener/EventHandler、AssetManager)
- 修复 HTL (Sightly) lint 警告(
data-sly-test: redundant constant value comparison) - 修复阻碍 AEMaaCS 安装软件包的 Vault 软件包安装时依赖项(
day/cq60/product:*) - 将 Guava 缓存(
com.google.common.cache.*)替换为 Caffeine(guavaCache) - 排查并修复
java.io.InputStream安全提示(inputStream、BPADG/java.io.inputstream) - OSGi → Cloud Manager 密钥/变量外部化(分支 A)、模板现代化(分支 C)、旧版 UI 对话框/CDW 迁移(分支 D)
- 基于 BPA(CSV 或缓存集合)或通过 MCP 使用 CAM 推进工作,每个会话处理一种模式
- Dispatcher 转换: 分支 E — 通过 Adobe 的
dispatcher-converter,将 AMS / 本地部署的 Apache+Dispatcher 配置转换为 AEMaaCS 配置,包括模式检测、配置生成、输出验证(过滤器/ACL 硬性门槛)、跨边界移交和 SDK 验证。参考:references/dispatcher/。 - Oak 索引迁移: 分支 F(beta)— 通过 Adobe 的
index-converter转换旧版_oak_index/*.xml定义,包括动态-custom-N命名覆盖、类型/数据类型兼容性检查和验证。BPA 模式 ID:oakIndex。参考:references/oak-index.md。 - 验证迁移后的代码: 分支 G(beta)— 构建、部署到本地 Cloud SDK,并检查迁移契约和 bundle/组件状态。参考:references/validation/validate-migration.md。
上面各项的分支路由和先读后委派要求均在 Required delegation 中统一定义 — 此列表仅说明“何时使用”。
先决条件
- 项目源代码和 Maven/Gradle 构建
- BPA CSV 或 MCP 访问权限为可选,但建议提供
- 对于 htlLint:包含
.htmlHTL 模板的ui.apps或等效内容包
BPA findings — 流程
通过 getBpaFindings 运行脚本(参见 调用辅助程序);除非辅助程序不可用,否则不要手动重新实现收集逻辑。
辅助程序有 两条彼此独立的路径,具体使用哪条取决于调用方的配置:
- 已配置 MCP(传入
mcpFetcher+projectId)→ 首次调用会从 MCP 获取所有发现项, 并将其缓存到<collectionsDir>/mcp/<projectId>/<pattern>.json。 每次调用(首次及后续调用)都会从 MCP 缓存读取并返回一批。 - 未配置 MCP,已提供 BPA CSV → 首次调用会解析 CSV,并将统一集合 JSON 写入
<collectionsDir>/unified-collection.json。 每次调用都会从 CSV 缓存读取并返回一批。
这两种缓存互不相关——MCP 会话和 CSV 会话不会相互覆盖。如果两者都未配置,辅助程序会报告 no-source,Agent 会请求提供其中一种来源。
所有路径都必须分批处理:getBpaFindings 会返回一批 5 条(result.targets)以及 result.paging 封装对象 { total, returned, offset, limit, nextOffset, hasMore }。处理一批、汇报,然后停止;只有在用户同意后才继续处理——完整规则见下文的 分批处理(每批 5 条)。
注意: BPA CSV 中不会出现 htlLint——它使用主动式 rg 发现。参见下文的 htlLint 流程。
通过 MCP 获取 CAM(摘要)
对代码转换器模式流程(scheduler、
assetApi、eventListener、resourceChangeListener、eventHandler、guavaCache、inputStream、lui、cdw),使用 fetch-cam-bpa-findings-by-pattern;如果用户问的是“有哪些 critical/major/advisory/info 级别的发现项?”,则使用 fetch-cam-bpa-findings-by-importance(该工具会返回最新 BPA 报告中权威的 _COUNT_<code> 行,这些行对应单个重要性级别,并按数量降序排列)。调用任一工具前,都必须获得用户对项目的明确确认——询问用户提供其 CAM 项目名称或 ID;工具会在内部解析项目(已知时优先使用 projectId)。不要传入未经确认的项目名称字符串。完整工具架构、REST 说明、重试和错误处理:
references/cam-mcp.md。
调用辅助程序
脚本位于 ./scripts/ 下(与此 SKILL.md 同级)。
const { getBpaFindings } = require('./scripts/bpa-findings-helper.js');
// First batch (defaults: limit=5, offset=0)
const result = await getBpaFindings(pattern, {
bpaFilePath: './cleaned_file6.csv',
collectionsDir: './unified-collections',
projectId: '...',
mcpFetcher: mcpFunction
// limit: 5, // implicit default
// offset: 0, // implicit default
});
// Next batch — only after the user says to continue
if (result.paging?.hasMore) {
const next = await getBpaFindings(pattern, {
bpaFilePath: './cleaned_file6.csv',
collectionsDir: './unified-collections',
projectId: '...',
mcpFetcher: mcpFunction,
offset: result.paging.nextOffset
});
}
result:
success、source('unified-collection' | 'bpa-file' | 'mcp-server' | …)message(包含易于理解的批次状态)targets—— 当前批次(长度<= limit)paging: { total, returned, offset, limit, nextOffset, hasMore }—— 成功调用时始终存在
如需在一次性编程调用方中禁用分批处理,请传入 limit: null。技能工作流本身绝不会这样做。
集合缓存
集合存放在 ./unified-collections/ 下。如果集合已存在,而用户又提供了一个新的 CSV,请询问用户是复用还是重新处理。如果集合是在支持所请求的模式之前写入的,则会自动根据 CSV 重建(解析器会将其提取的子类型记录在 meta.parsedSubtypes 中);如果没有 CSV,对该模式的请求会返回错误,而不是报告该模式不存在;all 仍会返回集合所覆盖的模式,并列出无法回答的模式(staleCache.missingPatterns)。
读取 BPA CSV
筛选 pattern 与会话模式匹配的行。典型列包括:pattern、filePath、message。
MCP 错误与回退
重要: MCP 失败时,立即停止工作流,并向用户提供原样的工具错误消息,包括“未找到”/404 类项目错误。不要继续执行迁移步骤、根据工作区推断其他 CAM 项目,也不要擅自切换为手动/本地迁移。
例外: 启用限制错误(前缀见 references/cam-mcp.md)必须原样显示,不得改述,也不得自动回退,直到用户解决这些限制。
停止后,你可以用通俗语言概述失败原因;如有帮助,可以重新显示 list-projects 中的项目。只有用户明确指示下一步后,才能继续(例如,提供列表中的正确项目 ID/名称、BPA CSV 路径,或指定用于手动流程的 Java 文件)。
有关重试、错误类别以及允许用户指定 CSV/手动路径的时机,请遵循 references/cam-mcp.md;仍然不得静默回退。绝不要向用户隐瞒工具错误。
停止后可选提示(用户必须回复): “请回复要使用的 CAM 项目(列表中的 ID 或名称)、BPA CSV 路径,或用于手动迁移的 Java 文件。”
模式指南
不要在此处重复模式表。请使用 {code-assessment}/SKILL.md → 模式指南 —— 五种模式各有一份模式指南({code-assessment}/<pattern>/SKILL.md);共享主题(SCR→DS、ResourceResolver/SLF4J、HTL lint、先决条件索引)保留为参考资料({code-assessment}/references/<file>.md);vault-package-dependencies 是仅供 migration 使用的参考资料(references/vault-package-dependencies.md),而不是 {code-assessment} 模式指南。有关各模式的路由表,请参阅上文分支 B 步骤 2。
工作流
步骤 0:迁移运行手册(审查 / 扫描入口)
当用户以全面审查/扫描请求开场——例如 “审查我的代码以进行 AEMaaCS 迁移”、“扫描我的项目以查找 AEM 迁移相关内容” 或类似请求——且未指定单一模式时,请在任何应用工作开始前生成一份只读迁移运行手册。
运行手册涵盖迁移技能可以处理的所有模式。每种模式都会声明一种检测策略——符合 CSV 条件的模式运行优先级级联;其他模式沿用现有的发现行为:
| 模式 | 策略 | 检测方式 |
|---|---|---|
scheduler、resourceChangeListener、event-migration、assetApi | cascade | BPA/CAM → CSV → analyzer → LLM 扫描(优先级列表) |
replication | cascade | analyzer → LLM 扫描(无 BPA/CSV 子类型映射) |
htlLint | html-scan | 对 .html 进行启发式正则扫描(纯 Node,无需 rg 二进制文件) |
osgiConfig | config-scan | 启发式扫描 OSGi 配置文件,查找看起来像密钥的键 / $[secret:]/$[env:] 占位符——仅显示键名和位置,绝不显示密钥值 |
vault-package-dependencies | pom-scan | 优先使用 Maven 的有效 POM(mvn help:effective-pom,每个 reactor 根目录调用一次——<pluginManagement> 继承以及每次执行级与插件级的 <configuration> 都是 Maven 的问题,而不是我们的问题)。当 Maven 无法解析某个模块时(父仓库失效、离线——常见于旧版 AEM 6.x / AMS 代码库),则回退到对原始 pom.xml 进行文本扫描。没有 BPA 子类型,也没有 analyzer——pom.xml 中安装时的依赖声明对已部署工件的 BPA 扫描不可见,也没有针对它的已编译检测器。每次有效 POM 解析失败都会显示为警告,因此降级扫描绝不会被静默报告为干净。 |
lui、cdw、templateModernization | BPA cascade → content-scan 回退 | 有 BPA CSV/CAM 源时,这些模式来自 BPA(子类型为 custom.classic.widget;legacy.dialog.classic/.coral2;legacy.static.template + custom.static.template)。没有 BPA 源时,则回退到启发式 .content.xml 扫描——对于 templateModernization,它会在任意深度遍历 apps/<appId>/templates/**(包括嵌套 / 分组模板),并根据页面组件资源类型,将每个静态模板分类为 custom.static.template 或 legacy.static.template,因此即使没有 BPA 报告,也能保留自定义与旧版的区分。示例提示词会路由到分支 D(legacy-ui)/ 分支 C(templates),而非 code-assessment |
guavaCache | bpa-only(无 analyzer、无 content-scan) | BPA 是唯一事实来源(子类型 custom.guava.cache),每个捆绑包生成一个发现项——此子类型上的 identifier 是 Guava 内部类,而非客户类,因此原始行会按消息中指定的捆绑包去重,而不是逐行显示。没有 BPA 源时,guavaCache 没有确定性回退方案,会显示在第 4 层 — LLM 扫描中:Agent 会按模块 grep .java 文件中的 import com.google.common.cache,详见 references/guava-cache.md,并将结果标记为 confidence: llm。此模式刻意不设已编译的 analyzer 检测器——它不会在 code-assessment 自身的发现过程中运行。 |
inputStream | java-scan(优先 BPA,本地扫描作为回退) | 优先级与 cascade 相同:BPA/CAM → CSV(子类型 java.io.inputstream)→ 本地扫描。有 BPA 行时,仅扫描报告中的类:input-stream-runner.js 会将这些类解析为工作区文件,并按风险排序,为每个文件生成一个发现项,包含行级位置;工作区外的类则合并为每个捆绑包一条信息行(CAM 行没有捆绑包名称,因此按包合并):对于保存在其他仓库或模块中的客户代码,标记为 missing-source(并附带警告);对于 Adobe 在 AEM as a Cloud Service 上提供的 AEM Forms 附加组件代码,标记为 platform-provided;对于需要升级或替换的第三方代码,标记为 not-in-workspace。没有 BPA 行时,会扫描每个 src/main/java 文件。每个流位置都会预先分类(A–F),并标注修复类型(decision / review / auto);仅含无害位置的文件会显示为信息项。本地扫描始终可用,因此此模式无需 LLM 层。 |
dispatcherConversion | content-scan | 启发式扫描 AMS / 本地 Dispatcher 配置布局(单体 dispatcher.any + conf.vhost.d/,或 conf.dispatcher.d/ AMS 目录树)。由 dispatcher-inventory.js 检测;示例提示词会路由到分支 E。 |
oakIndex | bpa-only(无 analyzer、无 content-scan) | BPA 是唯一事实来源(子类型 index.rule.violation / standard.index.modification),每个 Oak 索引路径生成一个发现项。没有 BPA 源时,oakIndex 没有确定性回退方案,会显示在第 4 层 — LLM 扫描中:Agent 会直接定位 _oak_index/*.xml,详见 references/oak-index.md。示例提示词会路由到分支 F(beta)。 |
htlLint、osgiConfig、vault-package-dependencies、inputStream,以及针对 lui/cdw/templateModernization 的内容扫描回退方案均为启发式(在缓存中标记为 confidence: heuristic)——这些是候选匹配项,并未经过编译器验证。来自 BPA 的 lui/cdw/templateModernization/replication/guavaCache/oakIndex 发现结果具有权威性。不在范围内:inject-in-sling-model 和 outdated-dependencies(它们属于 code-assessment 自己的运行手册,与迁移无关)。 |
有报告时,以 BPA 为准。 lui/cdw/templateModernization/replication 从 BPA CSV/CAM 中读取(解析器现在会提取这些子类型,并排除 _COUNT_*/_STAT 汇总行),因此运行手册中的计数与 BPA 报告中的 LUI 对话框 / CDW / 静态模板 / REP 统计相符。lui 仅保留对话框子类型(legacy.custom.component → create-component;legacy.static.template 计入 templateModernization)。只有在不存在 BPA 数据源时,才会回退到 .content.xml 扫描;如果被标记的旧版节点位于项目源码中未包含的软件包(例如 acs-commons)内,扫描结果可能会少于 BPA 的统计。replication:有报告时使用 BPA 的 replication.agent 发现结果,否则分析器会从源码中检测 Replicator 的用法。
用一条命令运行(照做——不要阅读生成器源码)
运行手册由一条 CLI 命令生成。该命令会自行运行本地分析器和每个扫描器,写入 migration-runbook.md 和旁路缓存,并打印摘要行。你不需要 require() 生成器、了解其内部机制,或编写进程内 MCP 桥接程序。
-
基础(始终执行):
node scripts/runbook-generator.js <workspaceRoot> --out ./migration-runbook.md --cache ./migration-runbook.json仅此步骤便涵盖本地分析器(Java 级联模式)、
html-scan、config-scan、pom-scan和content-scan模式。 -
**如果你有 BPA CSV 文件:**添加
--csv ./reports/bpa.csv。 -
如果已配置 CAM/MCP:照常进行一次 BPA 获取——对每个相关 slug(
scheduler、resourceChangeListener、eventListener、eventHandler、assetApi、replication、lui、cdw、templateModernization、guavaCache、inputStream、urc)调用 CAM MCP 工具,将原始目标写入一个以 slug 为键的 JSON 文件,然后传入该文件:# bpa.json shape: { "<slug>": [ <raw BPA target>, ... ], ... } (a slug you omit = "not in report", treated as clean) node scripts/runbook-generator.js <workspaceRoot> --bpa-json ./bpa.json --project-id <projectId> --project-name "<confirmed name>" --out ./migration-runbook.md --cache ./migration-runbook.json传入 CAM 工具响应中的已解析
projectId,以及用户确认的项目名称。它们会记录在migration-runbook.json的project下,以便validate-migration将结果报告给同一个 CAM 项目。本地 CSV 运行时省略两者;缓存会记录project: null。
分析器结果始终会与 BPA 合并——当 BPA 来源报告某个级联模式无问题,但实际源代码存在时,仍会添加本地分析器的发现结果(按类名去重,显示为 Detected via: BPA / CAM + analyzer)。因此,你无需手动对照源代码核查“BPA 无问题”的结果——脚本会自动处理。
**Tier 4 — LLM 扫描(仅当命令输出 ⚠️ Needs LLM scan: … 时)。**如果某个 cascade/bpa-only 模式没有任何确定性扫描器可扫描,就会出现这种情况(例如,没有 BPA 来源且没有 JDK 时的 guavaCache)。请按照模式指南中 {code-assessment}/<pattern>/ 下的提示进行 grep(对于 guavaCache,请查找 import com.google.common.cache——参见 references/guava-cache.md),将命中结果写入 JSON 文件,然后使用 --llm-findings 重新运行同一条命令:
# llm.json shape: { "<pattern>": [ { "file": "...", "line": 42, "snippet": "..." }, ... ] }
node scripts/runbook-generator.js <workspaceRoot> --bpa-json ./bpa.json --llm-findings ./llm.json --out ./migration-runbook.md --cache ./migration-runbook.json
生成器会在这一轮中合并并重新渲染结果,同时重写缓存——无需手动编辑内部对象。
命令完成后,告知用户(数字取自打印的摘要行):
"已写入
migration-runbook.md——共 {totalFindings} 条发现,涉及 {N} 个模式(检测来源:{sources})。该文件为只读。请回复你想优先迁移的模式(例如scheduler),我会复用该模式已发现的结果——无需重新扫描——并运行每个会话处理一个模式的应用工作流。"
该命令还会在 Markdown 文件旁写入旁路发现缓存(默认为 ./migration-runbook.json),其中保存每个模式的原始发现结果及其来源。下面的步骤 3 会先读取此缓存,再回退到实时 BPA/分析器/扫描器查询。
如果用户一开始就指定了某个模式(例如 “修复 scheduler 的发现结果”、“修复 ui.apps 中的 htlLint”、“扫描我的配置文件,查找 Cloud Manager 密钥”),请跳过步骤 0,直接进入相关应用流程。步骤 0 仅用于没有指定单一模式的宽泛审查/扫描请求。
**高级(编程方式)。**同样的功能也可通过 API 使用——
generateRunbook({ workspaceRoot, bpaFilePath, preFetchedBpa, llmByPattern, outputPath, cachePath })和mergeLlmFindings(gathered, llmByPattern),位于./scripts/runbook-generator.js——适用于需要在进程内驱动该功能的调用方(例如使用会话内的mcpFetcher,而不是--bpa-json)。优先使用上面的 CLI;仅当 CLI 无法满足需求时才使用 API。
每个会话处理一个模式
如果用户要求修复所有问题,或 BPA 混合了多个模式,先询问要处理哪个模式。尽量每个模式的会话提交一个 commit。
步骤 1:模式 ID
首先检查非 Java 分支(已在必须委派中完整路由),这些分支不需要 BPA 模式 ID:
- OSGi 配置 → Cloud Manager → 分支 A。
- 模板现代化(“创建可编辑模板”、“生成
/conf模板”、“静态模板转可编辑模板”、“结构/组件/策略重写规则”、“parsys 转容器”、“AEM Modernize Tools”)→ 分支 C。 - 旧版 UI(Classic UI/Coral 2 对话框、自定义 ExtJS 控件、LUI/CDW 检查结果)→ 分支 D(
lui→ 对话框,cdw→ cdw)。
如果请求是Dispatcher 转换——将 AMS 或本地部署的 Dispatcher 配置转换或迁移到 AEM as a Cloud Service——请遵循分支 E。不需要 Java 模式模块。跳过分支 B。
如果请求是oak 索引迁移——修复 oakIndex 检查结果,或将 _oak_index 定义转换到 AEM as a Cloud Service——请遵循分支 F(测试版)。不需要 Java 模式模块。跳过分支 B。
如果请求是验证 / 核验已迁移的代码在本地 Cloud SDK 上是否正常,请遵循分支 G(测试版)。跳过分支 B。
否则,将请求映射到一个模式 ID:scheduler、resourceChangeListener、replication、eventListener、eventHandler、assetApi、htlLint、lui、cdw、inputStream。如果不明确,请使用 {code-assessment}/SKILL.md 中的手动模式提示,或请用户从中选择一个。
步骤 2:可用性
如果该 ID 不在 code-assessment 目录({code-assessment}/references/patterns.md)中,请说明该模式尚不受支持。**例外:**分支 B 第 2 步中路由的仅用于迁移的参考项(vault-package-dependencies、guavaCache、inputStream)即使不在该目录中也受支持。
步骤 3:目标
**先检查是否有缓存的运行手册。**如果 ./migration-runbook.json(或传递给
generateRunbook 的 cachePath 选项的路径)存在,且其 findingsByPattern[<active pattern>] 数组
非空,则复用它,而不要重新推导检查结果:
- 从缓存文件加载
{ generatedAt, workspaceRoot, sourceByPattern, findingsByPattern }。 - 取
allFindings = findingsByPattern[<active pattern>]。每个条目为{ pattern, file, line, snippet }—file相对于缓存的workspaceRoot(使用path.join(workspaceRoot, file)解析);当该模式的来源为mcp/csv时,line/snippet为null(BPA 来源的发现项永远不包含 line/snippet;只有analyzer、html-scan和config-scan来源会包含)。osgiConfig发现项还包含kind,对于already-placeholdered行,还包含informational: true— 构建修复工作列表时跳过这些行。inputStream的信息性行也同样处理(仅包含良性内容的文件、bpa-unmatched、missing-source、platform-provided、not-in-workspace);其文件发现项 包含line/snippet以及sites数组,因此无需重新检测。 - 使用本文件其他位置相同的分页辅助函数对批次进行切片:
这样可以保持完全相同的const { paginate } = require('./scripts/unified-collection-reader.js'); const { targets, paging } = paginate(allFindings, { offset, limit: 5 });{ targets, paging }封装、默认每批 5 项,以及与下方实时getBpaFindings路径相同的paging.nextOffset语义 — 区别仅在于数据来源不同。即使整个数组 已在内存中,也不要绕过每批 5 项的限制。 - 告知用户:"正在从现有运行手册中复用
<pattern>的 N 项发现(生成时间:<generatedAt>)。" - 将该批次交给 code-assessment,作为
with_findings (pre-resolved)调用处理(参见{code-assessment}/references/runbook.md)。已填充line/snippet的发现项会完全跳过分析器重新运行; 仅填充file的发现项(BPA 来源)仍会在 code-assessment 内触发一次analyze.sh --files <paths>调用,以便在构建编辑计划前解析line/snippet。 - 如果缓存缺失、没有当前模式的条目,或用户明确要求“重新扫描”/“刷新”,则不作更改地转入下方实时流程。
对于 BPA 模式(scheduler、resourceChangeListener、replication、eventListener、eventHandler、assetApi、lui、cdw),若没有可用缓存:运行 getBpaFindings(如果提供了 bpaFilePath,则一并传入)。内部流程:缓存 → CSV → MCP → 手动,仅在每个步骤适用且成功时继续;如果 MCP 失败,遵循 MCP 错误和回退规则(停止;不得静默继续链式回退)。有关 MCP 的详情,请参阅 references/cam-mcp.md。
对于 lui 发现项,每个目标中的 identifier 是 JCR 组件路径(例如 /apps/myapp/components/content/mycomp),而不是 Java 类名。打开文件前,使用 JCR → 文件系统映射将其解析为文件系统路径。注意:luiCoral2 不是独立的 BPA 模式 ID — Coral 2 对话框会作为 lui 结果中的 legacy.dialog.coral2 子类型出现。不要单独调用 getBpaFindings('luiCoral2', …);应调用 getBpaFindings('lui', …),并在分支 D 中按子类型筛选。
对于 dispatcherConversion,目标是 dispatcher-inventory.js 扫描所检测到的 Dispatcher 配置根目录及模式(在步骤 0 的运行手册中显示),而非来自 BPA — 直接进入 分支 E。
对于 inputStream,优先级与其他 BPA 模式相同:运行手册缓存(见上文),然后是 BPA 发现结果 — 通过 fetch-cam-bpa-findings-by-pattern 获取 CAM 结果,参数为 pattern: "inputStream",然后是 BPA CSV — 仅当 BPA 没有 inputStream 发现结果时才进行本地扫描。BPA 提供的是类名,而非行号,因此始终运行一次扫描器来解析这些类:将 CAM 目标写入 JSON 文件,然后运行 node scripts/input-stream-runner.js <workspaceRoot> --bpa-json <cam-targets.json> [--csv <bpa.csv>] --json(CAM 目标优先于 CSV;两者都没有时,则扫描整个工作区)。不要将 BPA 行传给 analyze.sh。有 BPA 行时,仅将报告中的类纳入范围:扫描器会将这些类解析为工作区文件并定位到具体行,同时按包合并工作区之外的类(对于不包含 bundle 名称的 CAM 行,按 package 合并)。一个批次包含按扫描器(风险)顺序排列的 5 个非信息性文件发现结果。编辑一个批次后,使用 --files <touched files> 验证(路径缺失或无法读取会导致重新扫描失败)。完整流程:references/input-stream.md。
getBpaFindings 会返回一批 5 个发现结果(默认 limit=5)以及一个 paging
封套。Agent 仅处理这一批;在用户表示继续之前,不会请求下一批。请参阅下文的分批处理(批次大小为 5)。
对于 htlLint:跳过 BPA/CSV/MCP。如果缓存的运行手册条目中已有 htlLint 发现结果
(这些结果带有 "confidence": "heuristic" — 即正则表达式匹配,未经编译器验证),则按照上述优先使用缓存的规则复用,但编辑前必须根据 {code-assessment}/references/data-sly-test-redundant-constant.md 中的模式重新打开并确认每个匹配项。如果没有
缓存,则通过主动 rg 发现目标。请参阅下文的 htlLint 流程。
对于 osgiConfig(OSGi → Cloud Manager):缓存中保存的是启发式、仅供审查的发现结果
("confidence": "heuristic",仅包含键名和位置 — 不包含机密值)。将它们用作初步检查清单,然后遵循分支 A和 references/osgi-cfg-json-cloud-manager.md
对每个值进行分类(是真正的机密吗?是否为 Adobe 所有的 PID → needs_user_review)— 切勿在未确认的情况下相信启发式的 plaintext-secret 标签。
步骤 4:编辑前阅读
停止。 阅读 {code-assessment}/SKILL.md 和当前模式对应的模式指南(或参考文档)— 模式到文件的路由表见上文分支 B 步骤 2。
步骤 5:处理批次
对于返回批次中的每项发现结果(最多 5 项):
- 在 IDE 工作区内解析目标(参阅 工作区范围(IDE))。
- 阅读源代码 → 根据模式指南(或参考文档)分类 → 按顺序应用步骤 → 检查 lint → 处理下一个文件。
步骤 6:报告批次并等待
完成批次后,仅汇总本批次的情况:已处理的 paging.returned 项(总计 paging.total 项),并列出类名、已修改文件以及任何跳过项或失败项。如果 paging.hasMore,告知用户 "已处理 N 项批次(offset {offset}–{offset + returned − 1},共 {total} 项)。回复 continue 处理下一批,或指定具体类名。";否则说明该模式已完成,并转到会话报告。
然后停止并等待 — 仅在用户明确提出请求后再继续,遵循分批处理规则。
手动流程(无 BPA)
用户指定文件 → 分类(使用 code-assessment 手动模式提示,或询问用户)→ 确认模式指南或参考文档存在 → 阅读 {code-assessment}/SKILL.md + 模式指南(或参考文档)— 路由方式见分支 B 步骤 2 — → 转换 → 报告。
OSGi → Cloud Manager 流程
收集过程中不使用 BPA CSV、CAM/MCP 或 code-assessment 模式指南。遵循必需委派中的分支 A以及 references/osgi-cfg-json-cloud-manager.md 中的单提示词工作流。
模板现代化流程(分支 C)
不使用 BPA / MCP。三个阶段——上下文 → 逐个模板执行 → 验证——已在 references/template-modernization/template-modernization-context.md 中完整定义。先使用已确认的上下文和逐个模板的计划表,再通过 references/template-modernization/editable-template-creation.md 和 references/template-modernization/aem-modernization.md 执行生成器,随后运行 references/template-modernization/template-modernization-validation.md。验证失败时不要提交。
htlLint 流程
htlLint 不使用 BPA CSV 或 CAM/MCP。具体流程如下:
- 阅读
{code-assessment}/references/data-sly-test-redundant-constant.md——其中包含工作流、主动发现rg模式,以及全部 4 种修复模式。(HTL lint 是共享参考资料,而非专用模式指南。) - 发现目标:使用参考资料中主动发现表格里的
rg命令(范围:ui.apps/**/jcr_root/**/*.html或用户提供的内容包路径)。 - 分组按文件归类命中项,并按模式分类(布尔字面量、原始字符串、数值、拆分表达式)。
- 修复根据参考资料中匹配的模式章节修复每个命中项。
- 报告并建议用户运行
mvn clean install或 HTL validate,以确认不再有警告。
批量处理(批次大小为 5)
无论来源如何(MCP 或 CSV),默认每批向 Agent 提供 5 条发现结果。批处理在客户端进行——较重的数据获取(MCP 调用或 CSV 解析)仅执行一次,并写入本地 JSON 缓存;后续每批只需从该缓存中切片,开销很小。
规则
- 默认
limit为 5,每次调用处理一个批次——处理、报告、停止。内存中不得保留超过一个批次,也不得预取或跨批次合并。技能流程中不得传入limit: null(此选项供需要完整列表的程序化调用方使用)。 - 偏移量从 0 开始,并根据上一次调用返回的
result.paging.nextOffset递增——读取nextOffset,不要自行计算offset + limit。 - **顺序稳定。**每个缓存文件只写入一次,并按确定性顺序排列,因此切片稳定且连续。
- **恢复处理不保留状态。**不使用进度文件——恢复时使用
offset: previous.paging.nextOffset再次调用;之后的会话使用相同的pattern+offset,会获得相同批次。当paging.hasMore === false(或nextOffset === null)时,处理完成。 - 首次调用时写入缓存,后续批次读取缓存——MCP 获取或 CSV 解析总共只需一次,而非每批一次。要刷新缓存,请删除缓存文件:CSV
<collectionsDir>/unified-collection.json;MCP<collectionsDir>/mcp/<projectId>/<pattern>.json。
Agent 可见流程
[User] "Fix scheduler findings using ./reports/bpa.csv" (MCP path: pass { mcpFetcher, projectId } instead of bpaFilePath)
[Agent] getBpaFindings('scheduler', { bpaFilePath, limit: 5, offset: 0 })
// first call parses CSV (or fetches MCP once) → writes cache → slices
→ paging: { total: 137, returned: 5, offset: 0, nextOffset: 5, hasMore: true }
Processes 5 findings, reports: "Processed 5 of 137 (offset 0–4). Reply `continue`."
[User] "continue"
[Agent] getBpaFindings('scheduler', { bpaFilePath, limit: 5, offset: 5 }) // reads cache — no re-parse / no new MCP call
→ paging: { ..., offset: 5, nextOffset: 10, hasMore: true }
...
快速参考
来源优先级(BPA 模式):统一集合 → BPA CSV → MCP → 手动路径——MCP 出错后不会自动按顺序回退(如果 MCP 失败,请停止;参见 MCP 错误与回退)。所有 BPA 来源的批次大小均为 5。htlLint、OSGi→Cloud Manager、模板现代化(C)和旧版 UI(D)不使用 BPA/MCP——请参见必要委派中的对应分支。
面向用户的简短提示: "Using existing BPA collection (N findings)…" / "Processing your BPA report…" / "Fetched findings from CAM." / "Scanning HTL templates for data-sly-test lint issues…" / 可选提示:参见上文 MCP 停止后的说明。
CLI(仅用于开发)
在此技能的目录中:
# First batch (default offset=0, limit=5)
node scripts/bpa-findings-helper.js scheduler ./unified-collections
node scripts/bpa-findings-helper.js scheduler ./unified-collections ./cleaned_file6.csv
# Next batch: offset=5, limit=5
node scripts/bpa-findings-helper.js scheduler ./unified-collections ./cleaned_file6.csv 5 5
# Full unbounded listing (development / debugging only — skill never does this)
node scripts/bpa-findings-helper.js scheduler ./unified-collections ./cleaned_file6.csv 0 all
# Same batching on the low-level reader
node scripts/unified-collection-reader.js all ./unified-collections 0 5