mcpField
M
migration

migration

github.com/adobe开发316933 次安装今天更新
代码仓库

关于 migration

面向 AEM 开发者的迁移技能,协助将 AEM 6.x、AMS 或本地部署项目迁移到 AEM as a Cloud Service。它按单一迁移模式组织工作,并可先生成只读迁移运行手册。

主要功能

  1. 01按迁移模式逐项处理
  2. 02读取 BPA CSV 或从 CAM 获取发现项
  3. 03生成只读迁移运行手册
  4. 04支持手动文件迁移
  5. 05扫描并验证迁移改动

适用场景

  1. 01评估整个项目的云服务迁移工作
  2. 02根据 BPA 报告修复指定模式
  3. 03将 OSGi 配置转换为 Cloud Manager 变量
  4. 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.md
references/
cam-mcp.md
guava-cache.md
input-stream.md
oak-index.md
osgi-cfg-json-cloud-manager.md
vault-package-dependencies.md
references/dispatcher/
config-generation.md
context.md
conversion-patterns.md
cross-boundary.md
current-sdk-conventions.md
output-verification.md
validation.md
references/legacy-ui/cdw/
context.md
conversion.md
validation.md
references/legacy-ui/dialog/
context.md
coral2-to-coral3.md
extjs-to-coral3.md
validation.md
references/template-modernization/
aem-modernization.md
editable-template-creation.md
template-modernization-context.md
template-modernization-validation.md
references/validation/
custom-templates.md
validate-migration.md
resources/tika/
config.xml
scripts/
.gitignore
analyzer-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 模式迁移:

  1. 阅读 {code-assessment}/SKILL.md——关键规则、Java 基线链接、模式指南表格、手动模式提示。
  2. 阅读单个当前模式的模式指南(或参考文档):
    • 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 分析器执行)
  3. 如果代码使用 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:

两者都需要时的运行顺序:先 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。

  1. 盘点 — 运行 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 把关)。
  2. 规划并生成 config.yaml — 按照 references/dispatcher/config-generation.md 构建转换器配置(按模式映射;variablesToReplace 是扁平映射,portsToMap 是列表,appendToVhosts 是文件路径)。
  3. 执行 — 运行 ensureToolInstalled(首次使用时会将 Adobe 工具自动安装到被 git 忽略的 scripts/dispatcher-tool/node_modules/),然后运行 runConverter(scripts/dispatcher-run.js);按模式选择执行器(standard → main.js,flexible / 本地部署 → singleFileMain.js)。
  4. 验证并规范化 — 运行 scripts/dispatcher-verify.js,并按照 references/dispatcher/output-verification.md 处理。遇到 filter-acl-loss(基线中有过滤器规则,但 filters.any 为空)时,必须停止:解决此问题后,转换结果才能使用。
  5. 判断并处理跨边界事项 — 按照 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。
  6. 验证 — 按照 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。

  1. 检测 — 查找 _oak_index/ 目录;根据项目的 pom.xml 确定 aemVersion(63/64/65/Cloud_Services)。
  2. 确定下一个 -custom-N — 在使用工具的默认值 -custom-1 之前,扫描目标状态中是否已有 <baseName>-custom-<n> 同级索引;之前的迁移或客户自有的 -custom-N 索引会导致重用 -custom-1 时发生冲突,而不是生成新名称。
  3. 执行 — 通过 npx 解析 Index Converter,并按 references/oak-index.md 调用。
  4. 差异 + 类型兼容性检查 — 显示转换后的输出与输入之间的差异;验证 oak:isOakIndexDefinition/type 完整无损,并确认旧定义与转换后的定义中每个属性的 JCR 值类型一致。发现任何不匹配时,标记为 needs_manual_review: datatype mismatch on <propertyName> — 不要默默应用。
  5. 应用(经用户确认后)— 将工具输出复制到仓库中,并应用步骤 2 中计算出的名称覆盖值(如有)。
  6. 验证 — 执行 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、BPA DG / 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:包含 .html HTL 模板的 ui.apps 或等效内容包

BPA findings — 流程

通过 getBpaFindings 运行脚本(参见 调用辅助程序);除非辅助程序不可用,否则不要手动重新实现收集逻辑。

辅助程序有 两条彼此独立的路径,具体使用哪条取决于调用方的配置:

  1. 已配置 MCP(传入 mcpFetcher + projectId)→ 首次调用会从 MCP 获取所有发现项, 并将其缓存到 <collectionsDir>/mcp/<projectId>/<pattern>.json。 每次调用(首次及后续调用)都会从 MCP 缓存读取并返回一批。
  2. 未配置 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、assetApicascadeBPA/CAM → CSV → analyzer → LLM 扫描(优先级列表)
replicationcascadeanalyzer → LLM 扫描(无 BPA/CSV 子类型映射)
htlLinthtml-scan对 .html 进行启发式正则扫描(纯 Node,无需 rg 二进制文件)
osgiConfigconfig-scan启发式扫描 OSGi 配置文件,查找看起来像密钥的键 / $[secret:]/$[env:] 占位符——仅显示键名和位置,绝不显示密钥值
vault-package-dependenciespom-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、templateModernizationBPA 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
guavaCachebpa-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 自身的发现过程中运行。
inputStreamjava-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 层。
dispatcherConversioncontent-scan启发式扫描 AMS / 本地 Dispatcher 配置布局(单体 dispatcher.any + conf.vhost.d/,或 conf.dispatcher.d/ AMS 目录树)。由 dispatcher-inventory.js 检测;示例提示词会路由到分支 E。
oakIndexbpa-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 桥接程序。

  1. 基础(始终执行):

    node scripts/runbook-generator.js <workspaceRoot> --out ./migration-runbook.md --cache ./migration-runbook.json
    

    仅此步骤便涵盖本地分析器(Java 级联模式)、html-scan、config-scan、pom-scan 和 content-scan 模式。

  2. **如果你有 BPA CSV 文件:**添加 --csv ./reports/bpa.csv。

  3. 如果已配置 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 项):

  1. 在 IDE 工作区内解析目标(参阅 工作区范围(IDE))。
  2. 阅读源代码 → 根据模式指南(或参考文档)分类 → 按顺序应用步骤 → 检查 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。具体流程如下:

  1. 阅读 {code-assessment}/references/data-sly-test-redundant-constant.md——其中包含工作流、主动发现 rg 模式,以及全部 4 种修复模式。(HTL lint 是共享参考资料,而非专用模式指南。)
  2. 发现目标:使用参考资料中主动发现表格里的 rg 命令(范围:ui.apps/**/jcr_root/**/*.html 或用户提供的内容包路径)。
  3. 分组按文件归类命中项,并按模式分类(布尔字面量、原始字符串、数值、拆分表达式)。
  4. 修复根据参考资料中匹配的模式章节修复每个命中项。
  5. 报告并建议用户运行 mvn clean install 或 HTL validate,以确认不再有警告。

批量处理(批次大小为 5)

无论来源如何(MCP 或 CSV),默认每批向 Agent 提供 5 条发现结果。批处理在客户端进行——较重的数据获取(MCP 调用或 CSV 解析)仅执行一次,并写入本地 JSON 缓存;后续每批只需从该缓存中切片,开销很小。

规则
  1. 默认 limit 为 5,每次调用处理一个批次——处理、报告、停止。内存中不得保留超过一个批次,也不得预取或跨批次合并。技能流程中不得传入 limit: null(此选项供需要完整列表的程序化调用方使用)。
  2. 偏移量从 0 开始,并根据上一次调用返回的 result.paging.nextOffset 递增——读取 nextOffset,不要自行计算 offset + limit。
  3. **顺序稳定。**每个缓存文件只写入一次,并按确定性顺序排列,因此切片稳定且连续。
  4. **恢复处理不保留状态。**不使用进度文件——恢复时使用 offset: previous.paging.nextOffset 再次调用;之后的会话使用相同的 pattern + offset,会获得相同批次。当 paging.hasMore === false(或 nextOffset === null)时,处理完成。
  5. 首次调用时写入缓存,后续批次读取缓存——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

评论

支持 Markdown