adobe/skills

migration

Migrates legacy AEM (6.x, AMS, on-prem) to AEM as a Cloud Service using BPA CSV/cache, CAM/MCP discovery, and a one-pattern-per-session workflow.

ソースを見る
リポジトリの原文

見出し、例、コード、表、リンク、参照画像を含む原文を表示しています。

AEM as a Cloud Service — Code Migration

Source → target: Legacy AEM 6.x / AMS / on-premAEM as a Cloud Service. Scoped under skills/aem/cloud-service/skills/migration/ so this is not confused with Edge Delivery or 6.5 LTS.

This skill drives the migration workflow: BPA data, CAM/MCP, one pattern per session, and target discovery. Transformation rules and steps live in the `code-assessment` skill — once a finding's pattern is identified, hand off to {code-assessment}/<pattern>/SKILL.md (or the relevant shared reference under {code-assessment}/references/).

Setup: Use the `aem-cloud-service` install (see repository root README) so both migration and code-assessment paths are available. If you already have the monorepo open with resolvable {code-assessment} paths, no separate install step is required.

Quick start (for the person driving the agent)

One pattern per chat/session — if you ask to "fix everything," the skill will ask you to pick first (e.g. scheduler vs replication vs htlLint).

You have…Say something like…What happens
A whole project to assess"Review my code for AEMaaCS migration"Generates read-only migration-runbook.mdall migration patterns (Java cascade + htlLint + osgiConfig), affected files, sample prompts. No edits.
A BPA CSV"Fix scheduler findings using `./path/to/bpa.csv`"Fastest path: CSV → cached collection → files
CAM + MCP only"Get scheduler findings from CAM; I'll pick the project when you list them."Agent lists projects → you confirm → MCP fetch (cam-mcp.md)
Just a few files"Migrate scheduler in `core/.../MyJob.java`"Manual flow: no BPA required
OSGi → Cloud Manager"Scan my config files and create Cloud Manager environment secrets or variables."Agent auto-reads references/osgi-cfg-json-cloud-manager.md (full Adobe-aligned rules inlined there); no BPA pattern id
HTL lint warnings"Fix htlLint issues in `ui.apps`"Proactive discovery via rg → fix per the HTL lint reference
Template modernization"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 auto-reads references/template-modernization/template-modernization-context.md (shared discovery + structured context), produces a per-template plan table, then executes the plan using editable-template-creation.md and aem-modernization.md, and validates via template-modernization-validation.md. No BPA pattern id.
Dialog migration"Convert my Classic UI / ExtJS dialogs to Touch UI." / "Upgrade Coral 2 dialogs to Coral 3." / "Fix LUI dialog findings."Agent reads references/legacy-ui/dialog/context.md — filters BPA LUI to dialog sub-types, converts via extjs-to-coral3.md or coral2-to-coral3.md, validates via validation.md. BPA pattern id: lui.
Custom widget migration"Fix my CDW findings." / "Migrate custom ExtJS widgets to Coral 3."Agent reads references/legacy-ui/cdw/context.md — inventories xtypes, maps or scaffolds Granite UI components via conversion.md, validates via validation.md. BPA pattern id: cdw. Run CDW before dialog migration when both are needed.
Guava cache warnings"Fix guavaCache findings using BPA CSV." / "Swap Guava cache for Caffeine."Agent reads references/guava-cache.md — BPA is the source of truth (subtype custom.guava.cache); one finding per bundle, not per Guava-internal class row. BPA pattern id: guavaCache. Not a code-assessment pattern — Guava cache usage only occurs in pre-migration code, never native AEMaaCS code.
Dispatcher conversion (beta)"Convert my AMS / on-prem Dispatcher config to AEM as a Cloud Service."Agent reads references/dispatcher/context.md — detects the config mode, generates the tool config, runs Adobe's dispatcher-converter, verifies output (filter/ACL hard-gate), and validates. Branch E. Runbook pattern id: dispatcherConversion (heuristic).

Starter prompts (copy-paste):

  • "Review my code for AEMaaCS migration"start here for a full runbook before changing anything.
  • "Use the migration skill: scheduler only, BPA CSV at `./reports/bpa.csv`, then apply the code-assessment pattern guide before editing."
  • "Replication only from CAM; list projects first, I'll pick one."
  • "Manual: event listener migration for `.../Listener.java` — read the code-assessment pattern guide first."
  • "Scan my config files and create Cloud Manager environment secrets or variables."
  • "Fix htlLint in `ui.apps` — scan for `data-sly-test` redundant constant warnings and fix them."
  • "Migrate my static templates to editable templates and generate the Modernize Tools rewrite rules."
  • "Fix LUI dialog findings using BPA CSV at `./reports/bpa.csv`."
  • "Migrate custom ExtJS widgets (CDW findings) from CAM."
  • "Fix all Classic UI and custom widget findings — CDW first, then dialogs."
  • "Fix guavaCache findings using BPA CSV at `./reports/bpa.csv`."

Path convention (Adobe Skills monorepo)

From the repository root (parent of the skills/ directory):

SymbolPath
`{code-assessment}`skills/aem/cloud-service/skills/code-assessment/

Examples: {code-assessment}/SKILL.md, {code-assessment}/scheduler/SKILL.md, {code-assessment}/references/scr-to-osgi-ds.md.

Workspace scope (IDE) — user code only

Applies to finding and editing the user's AEM project (Java, bundles, config, HTL), not to reading installed skill files under {code-assessment}.

  • Treat the current IDE workspace root folder(s) (single- or multi-root) as the only boundary for searches, globs, grep, and file reads/writes for migration targets.
  • Do not search parent directories, sibling folders on disk, ~, other clones, or arbitrary absolute paths to "discover" sources unless the user explicitly names those paths or asks you to include them.
  • BPA CSV / CAM targets: If a filePath or class-to-file mapping does not resolve under a workspace root, stop and tell the user which paths are missing — do not hunt elsewhere on the filesystem. Ask them to open the correct project in the IDE or adjust paths.
  • Manual flow: Only migrate files the user named that live under the workspace (or paths they explicitly provided). Do not expand scope by searching outside the workspace.

Required delegation (do this first)

Branch A — OSGi configs → Cloud Manager (no Java BPA pattern this session): If the user asks to scan config files, create / set up Cloud Manager environment secrets or variables, move passwords or secrets out of OSGi / `.cfg.json` / `ui.config`, or mentions `$[secret:]` / `$[env:]` for AEM CS, then read [references/osgi-cfg-json-cloud-manager.md](references/osgi-cfg-json-cloud-manager.md) immediately and follow the product rules and workflow defined in that file (Adobe AEM as a Cloud Service OSGi + Cloud Manager behavior is reproduced there—no external doc URL required). Sleek prompts are enough — no need to name the reference file. Skip branch B for that work.

Branch B — Java / HTL / BPA pattern migration:

  1. Read `{code-assessment}/SKILL.md` — critical rules, Java baseline links, Pattern Guides table, Manual Pattern Hints.
  2. Read the pattern guide (or reference) for the single active pattern:
  • scheduler`{code-assessment}/scheduler/SKILL.md` (pattern guide)
  • resourceChangeListener`{code-assessment}/resource-change-listener/SKILL.md` (pattern guide)
  • replication`{code-assessment}/replication/SKILL.md` (pattern guide)
  • eventListener / eventHandler`{code-assessment}/event-migration/SKILL.md` (pattern guide — both JCR and OSGi Event Admin paths)
  • assetApi`{code-assessment}/asset-manager/SKILL.md` (pattern guide)
  • htlLint`{code-assessment}/references/data-sly-test-redundant-constant.md` (reference — HTL lint is a single shared reference, not a dedicated pattern guide)
  • guavaCache[references/guava-cache.md](references/guava-cache.md) (reference — Guava cache → Caffeine swap; lives under `migration` only, not `code-assessment`, since Guava cache usage does not occur in native AEMaaCS code, only in code carried over from legacy AEM)
  1. When code uses SCR, ResourceResolver, or console logging, read `{code-assessment}/references/scr-to-osgi-ds.md` and `{code-assessment}/references/resource-resolver-logging.md` (or the hub `{code-assessment}/references/aem-cloud-service-pattern-prerequisites.md`).

Do not transform Java or HTL until the pattern guide (or reference) is read (branch B). Branch A does not require {code-assessment} pattern guidance.

Branch C — Template Modernization (no BPA): static → editable templates and/or AEM Modernize Tools rules (structure/component/policy). Three phases: context → per-template execute → validate. Start at references/template-modernization/template-modernization-context.md; generators are editable-template-creation.md and aem-modernization.md; post-gen checks in template-modernization-validation.md. Skip branch B.

Branch D — Legacy UI Migration (legacy-ui/ sub-folders): If the user asks to convert Classic UI / ExtJS dialogs, upgrade Coral 2 dialogs, migrate custom ExtJS widgets, fix LUI or CDW BPA findings, or mentions cq:Dialog / xtype / cq:Widget:

  • For dialog findings (lui pattern, legacy.dialog.classic or legacy.dialog.coral2 only):
  1. Read references/legacy-ui/dialog/context.mdgetBpaFindings('lui', …), filter to dialog sub-types, skip all others with a note.
  2. convert-extjsreferences/legacy-ui/dialog/extjs-to-coral3.md.
  3. upgrade-coral2references/legacy-ui/dialog/coral2-to-coral3.md.
  4. Validate: references/legacy-ui/dialog/validation.md.
  • For custom widget findings (cdw pattern):
  1. Read references/legacy-ui/cdw/context.mdgetBpaFindings('cdw', …), inventory xtypes.
  2. Per xtype: references/legacy-ui/cdw/conversion.md (apply mapping or scaffold Granite UI component).
  3. Validate: references/legacy-ui/cdw/validation.md.
  4. If the same components also have LUI legacy.dialog.classic findings, run dialog migration afterwards — all xtypes are now resolved.

Run order when both are needed: CDW first, then dialog. CDW resolves custom xtypes so dialog conversion can proceed without stops. Skip Branch B. Skip Branch C.

Branch E — Dispatcher Conversion (AMS / on-premise Apache httpd + Dispatcher → AEMaaCS; no Java BPA pattern this session):

Beta: Dispatcher conversion (Branch E) is in beta and under active development. Review its output carefully before using it on production dispatcher configurations.

If the user asks to convert / migrate a Dispatcher configuration to AEM as a Cloud Service, follow the 6-phase flow. It wraps Adobe's maintained @adobe/aem-cs-source-migration-dispatcher-converter as the conversion engine and adds detection, config generation, output verification, judgment, and validation on top. Start by reading references/dispatcher/context.md. Skip Branch B.

  1. Inventory — run scripts/dispatcher-inventory.js (buildInventory) to detect the mode (standard / flexible / already-cloud / not-dispatcher / v1 / unknown) and count filter / rewrite / cache rules. Modes and signals are defined in references/dispatcher/context.md. If the mode is already-cloud, not-dispatcher, or unknown, STOP with that finding — the first two have nothing to convert, and unknown is an ambiguous/incomplete layout to confirm with the user before running the content-blind tool (resolveExecutor falls unknown through to the on-prem executor, so the agent is the gate here).
  2. Plan + generate `config.yaml` — build the converter config per references/dispatcher/config-generation.md (per-mode mapping; variablesToReplace is a flat mapping, portsToMap is a list, appendToVhosts is a file path).
  3. ExecuteensureToolInstalled (auto-installs the Adobe tool into the gitignored scripts/dispatcher-tool/node_modules/ on first use) then runConverter (scripts/dispatcher-run.js); the executor is selected by mode (standardmain.js, flexible / on-prem → singleFileMain.js).
  4. Verify + normalize — run scripts/dispatcher-verify.js and apply references/dispatcher/output-verification.md. HARD STOP on `filter-acl-loss` (an empty filters.any when the baseline had filter rules): the conversion is not usable until it is resolved.
  5. Judgment + cross-boundary — apply the decision catalog in references/dispatcher/conversion-patterns.md; hand any Cloud Manager environment variables to Branch A (OSGi → Cloud Manager); flag CDN-candidate rules. Target end-state conventions are in references/dispatcher/current-sdk-conventions.md. To operationalize this handoff, run scripts/dispatcher-crossboundary.js to build the Cloud Manager variable handoff artifact, then apply references/dispatcher/cross-boundary.md to route each concern — CM vars → Branch A; immutable freshness → the dispatcher skill's sdk(diff-baseline); security headers / edge → security-hardening; validation → config-authoring.
  6. Validate — validate the converted src per references/dispatcher/validation.md (delegates to the dispatcher skill's SDK validator + guardrails); iterate until clean. Do not present the result as done on validation failure. After validation, render the consolidated report with scripts/dispatcher-report.js (renderReportwriteReport) as conversion-report.md, which includes the coverage counts, the CM handoff, and the delegated next-checks checklist.

When to Use This Skill

  • Migrate legacy AEM Java toward Cloud Service–compatible patterns (scheduler, ResourceChangeListener, replication, EventListener/EventHandler, AssetManager)
  • Fix HTL (Sightly) lint warnings (data-sly-test: redundant constant value comparison)
  • Swap Guava cache (com.google.common.cache.*) for Caffeine (guavaCache)
  • OSGi → Cloud Manager secret/variable externalization (Branch A), Template Modernization (Branch C), Legacy UI dialog/CDW migration (Branch D)
  • Drive work from BPA (CSV or cached collection) or CAM via MCP, one pattern per session
  • Dispatcher Conversion: Branch E (beta) — convert AMS / on-premise Apache+Dispatcher configs to AEMaaCS via Adobe's dispatcher-converter, with mode detection, config generation, output verification (filter/ACL hard-gate), cross-boundary handoff, and SDK validation. References: references/dispatcher/.

Branch routing and the read-first delegation for each entry above are defined once in Required delegation — this list is only the "when."

Prerequisites

  • Project source and Maven/Gradle build
  • BPA CSV or MCP access optional but recommended
  • For htlLint: ui.apps or equivalent content package with .html HTL templates

BPA findings — flow

Scripts run via `getBpaFindings` (see Calling the helper); do not reimplement collection logic by hand unless the helper is unavailable.

The helper has two independent paths, chosen by what the caller configures:

  1. MCP configured (mcpFetcher + projectId passed) → first call fetches all findings

from MCP and caches them to <collectionsDir>/mcp/<projectId>/<pattern>.json. Every call (first and subsequent) reads from the MCP cache and returns one batch.

  1. MCP not configured, BPA CSV provided → first call parses the CSV and writes the

unified-collection JSON to <collectionsDir>/unified-collection.json. Every call reads from the CSV cache and returns one batch.

The two caches are disjoint — MCP sessions and CSV sessions never shadow each other. If neither is configured, the helper reports no-source and the agent asks for one.

Batching is mandatory on every path: getBpaFindings returns a batch of 5 (result.targets) plus a result.paging envelope { total, returned, offset, limit, nextOffset, hasMore }. Process one batch, report, stop, and resume only on the user's go-ahead — full rules in Batched processing (batch size 5) below.

Note: htlLint does not appear in BPA CSV — it uses proactive rg discovery instead. See htlLint flow below.

CAM via MCP (summary)

Use `fetch-cam-bpa-findings-by-pattern` for code-transformer pattern flows (scheduler, assetApi, eventListener, resourceChangeListener, eventHandler, guavaCache, lui, cdw) and `fetch-cam-bpa-findings-by-importance` when the user instead asks "what are the critical/major/advisory/info findings?" (returns the latest BPA report's authoritative _COUNT_<code> rows at one importance level, sorted by descending count). Either tool requires explicit user confirmation of the project before being called — ask the user for their CAM project name or ID; the tools resolve it internally (prefer `projectId` when known). Do not pass an unconfirmed project name string. Full tool schemas, REST notes, retries, and error handling: references/cam-mcp.md.

Calling the helper

Scripts live under `./scripts/` (next to this SKILL.md).

javascript
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 (includes a human-readable batch status)
  • targets — the current batch (length <= limit)
  • paging: { total, returned, offset, limit, nextOffset, hasMore } — always present on

successful calls

To disable batching for a one-off programmatic caller, pass limit: null. The skill workflow itself never does this.

Collection caching

Collections live under `./unified-collections/`. If a collection exists and the user supplies a new CSV, ask whether to reuse or re-process.

Reading a BPA CSV

Filter rows where `pattern` matches the session pattern. Typical columns: pattern, filePath, message.

MCP errors and fallback

Critical: On MCP failure, stop the workflow immediately and give the user the exact tool error message (verbatim), including "not found" / 404-style project errors. Do not continue with migration steps, infer a different CAM project from the workspace, or switch to manual/local migration on your own.

Exception: enablement restriction errors (prefix documented in references/cam-mcp.md) must be shown verbatim with no paraphrase and no automatic fallback until the user addresses them.

After stopping, you may summarize what failed in plain language and, if helpful, re-show projects from `list-projects`. Only continue when the user explicitly directs the next step (e.g. correct project id/name from the list, BPA CSV path, or specific Java files for manual flow).

For retries, error categories, and when user-directed CSV/manual paths are allowed, follow references/cam-mcp.md; still no silent fallback. Never hide tool errors from the user.

Optional prompt after stop (user must reply): "Reply with the CAM project to use (id or name from the list), a path to your BPA CSV, or the Java files for a manual migration."

Pattern guides

Do not duplicate the pattern table here. Use `{code-assessment}/SKILL.md` → Pattern Guides — five patterns each have a pattern guide ({code-assessment}/<pattern>/SKILL.md); shared topics (SCR→DS, ResourceResolver/SLF4J, HTL lint, prerequisites hub) stay as references ({code-assessment}/references/<file>.md). See Branch B step 2 above for the per-pattern routing table.

Workflow

Step 0: Migration runbook (review / scan entry point)

When the user opens with a broad review/scan request — "review my code for AEMaaCS migration", "scan my project for AEM migration", or similar — and does not name a single pattern, generate a read-only migration runbook before any apply work.

The runbook covers every pattern the migration skill can address. Each pattern declares a detection strategy — CSV-eligible patterns run the priority cascade; the others keep their existing discovery behaviour:

Pattern(s)StrategyHow it's detected
scheduler, resourceChangeListener, event-migration, assetApicascadeBPA/CAM → CSV → analyzer → LLM scan (priority list)
replicationcascadeanalyzer → LLM scan (no BPA/CSV subtype mapping)
htlLinthtml-scanheuristic regex scan of .html (pure Node — no rg binary needed)
osgiConfigconfig-scanheuristic scan of OSGi config files for secret-looking keys / $[secret:]/$[env:] placeholders — key names + locations only, never secret values
lui, cdw, templateModernizationBPA cascadecontent-scan fallbackWhen a BPA CSV/CAM source is present, these come from BPA (subtypes custom.classic.widget; legacy.dialog.classic/.coral2; legacy.static.template + custom.static.template). With no BPA source, a heuristic .content.xml scan is the fallback — for templateModernization it walks apps/<appId>/templates/** at any depth (nested/grouped templates included) and classifies each static template as custom.static.template or legacy.static.template from its page-component resource type, so the custom-vs-legacy distinction survives even without a BPA report. Sample prompts route to Branch D (legacy-ui) / Branch C (templates), not code-assessment
guavaCachebpa-only (no analyzer, no content-scan)BPA is the sole source of truth (subtype custom.guava.cache), one finding per bundleidentifier on this subtype is a Guava-internal class, not a customer class, so raw rows are deduped to the bundle named in the message, not surfaced per row. With no BPA source, guavaCache has no deterministic fallback and surfaces under Tier 4 — LLM scan: the agent greps .java files for import com.google.common.cache per module, per references/guava-cache.md, and tags the result confidence: llm. There is deliberately no compiled analyzer detector for this pattern — it does not run inside code-assessment's own discovery.
dispatcherConversioncontent-scanHeuristic scan for an AMS / on-prem Dispatcher config layout (a monolithic dispatcher.any + conf.vhost.d/, or conf.dispatcher.d/ AMS trees). Detected by dispatcher-inventory.js; the sample prompt routes to Branch E (beta).

htlLint, osgiConfig, and the content-scan fallback for lui/cdw/templateModernization are heuristic (tagged confidence: heuristic in the cache) — candidate matches, not compiler-validated. BPA-sourced lui/cdw/templateModernization/replication/guavaCache findings are authoritative. Out of scope: inject-in-sling-model and outdated-dependencies (those belong to code-assessment's own runbook, not migration).

BPA is the source of truth when a report is available. lui/cdw/templateModernization/replication are read from the BPA CSV/CAM (the parser now extracts these subtypes and excludes _COUNT_*/_STAT summary rows), so the runbook counts match your BPA report's LUI-dialog / CDW / static-template / REP tallies. lui keeps only the dialog sub-types (legacy.custom.component → create-component; legacy.static.template is counted under templateModernization). The .content.xml scan is only the fallback when no BPA source is present — and it can undercount relative to BPA when the flagged legacy nodes live in packages (e.g. acs-commons) not in the project source. replication: BPA replication.agent findings when a report is present, else the analyzer detects Replicator usage from source.

The script handles every deterministic strategy (cascade tiers 1–3, html-scan, config-scan); the agent handles only the LLM-scan tier for cascade patterns nothing else could scan.

javascript
const { generateRunbook, renderRunbook, writeRunbookCache } = require('./scripts/runbook-generator.js');

const result = await generateRunbook({
  workspaceRoot: '<IDE workspace root>',     // analyzer + html-scan + config-scan
  bpaFilePath: '<csv path or undefined>',     // cascade tier 2
  collectionsDir: './unified-collections',
  projectId, mcpFetcher,                      // cascade tier 1 (MCP), when configured
  outputPath: './migration-runbook.md',
});
// result.needsLlmScan → cascade patterns no deterministic source could scan

Tier 4 — LLM scan (last resort). If result.needsLlmScan is non-empty (no BPA source and the analyzer could not run — e.g. no JDK), the agent scans those patterns itself: read each pattern guide's detection hints under {code-assessment}/<pattern>/, locate matches inside the IDE workspace (see Workspace scope). For each pattern the agent scans, update result.gathered so the re-render and cache stay consistent:

  • Build display findings in the { location, detail, severity } shape and assign them to result.gathered.findingsByPattern[<pattern>].
  • Build raw findings in the canonical { pattern, file, line, snippet } shape and assign them to result.gathered.rawFindingsByPattern[<pattern>] (use null for line/snippet when a match can't be pinned to a line).
  • Set result.gathered.sourceByPattern[<pattern>] = 'llm'.
  • Remove the pattern from result.gathered.needsLlmScan (otherwise the re-render still shows it as needs LLM scan and a findings table).

Then re-render with renderRunbook(result.gathered, ctx), overwrite the runbook file, and call writeRunbookCache(result.gathered, ctx, result.cachePath) so the sidecar cache reflects the merged findings.

After writing the runbook, tell the user:

"I've written migration-runbook.md{totalFindings} findings across {N} patterns (detected via {sources}). It's read-only. Reply with the pattern you want to migrate first (e.g. scheduler) and I'll reuse the findings already discovered for that pattern — no re-scan needed — and run the one-pattern-per-session apply workflow."

generateRunbook() also writes a sidecar findings cache (default ./migration-runbook.json, see result.cachePath) alongside the markdown, holding each pattern's raw findings and their source. Step 3 below reads this cache first before falling back to a live BPA/analyzer/scan lookup.

Skip Step 0 when the user names a specific pattern up front (e.g. "fix scheduler findings", "fix htlLint in ui.apps", "scan my config files for Cloud Manager secrets") — go straight to the relevant apply flow. Step 0 is only for a broad review/scan request with no single pattern named.

CLI (development):

bash
node scripts/runbook-generator.js <workspaceRoot> [--csv ./reports/bpa.csv] [--out ./migration-runbook.md]

One pattern per session

If the user asks to fix everything or BPA mixes patterns, ask which pattern first. Prefer one commit per pattern session.

Step 1: Pattern id

First check the non-Java branches (routed in full under Required delegation), which take no BPA pattern id:

  • OSGi configs → Cloud Manager → Branch A.
  • Template modernization ("create editable templates", "generate /conf templates", "static to editable", "structure/component/policy rewrite rules", "parsys to container", "AEM Modernize Tools") → Branch C.
  • Legacy UI (Classic UI/Coral 2 dialogs, custom ExtJS widgets, LUI/CDW findings) → Branch D (lui → dialog, cdw → cdw).

If the request is dispatcher conversion — convert or migrate an AMS or on-premise Dispatcher configuration to AEM as a Cloud Service — follow Branch E (beta). No Java pattern module is needed. Skip Branch B.

Otherwise map the request to a pattern id: scheduler, resourceChangeListener, replication, eventListener, eventHandler, assetApi, htlLint, lui, cdw. If unclear, use Manual Pattern Hints in `{code-assessment}/SKILL.md` or ask the user to pick one of those.

Step 2: Availability

If the id is missing from the code-assessment catalog (`{code-assessment}/references/patterns.md`), say the pattern is not supported yet.

Step 3: Targets

Check for a cached runbook first. If ./migration-runbook.json (or the path passed to generateRunbook's cachePath option) exists and its findingsByPattern[<active pattern>] array is non-empty, reuse it instead of re-deriving findings:

  • Load { generatedAt, workspaceRoot, sourceByPattern, findingsByPattern } from the cache file.
  • Take allFindings = findingsByPattern[<active pattern>]. Each entry is

{ pattern, file, line, snippet }file is relative to the cache's `workspaceRoot` (resolve with path.join(workspaceRoot, file)); line/snippet are null when the pattern's source was mcp/csv (BPA-sourced findings never carry line/snippet; only the analyzer, html-scan, and config-scan sources do). osgiConfig findings additionally carry a kind and, for already-placeholdered rows, informational: true — skip those when building the fix work list.

  • Slice the batch with the same paginate helper used elsewhere in this file:
javascript
  const { paginate } = require('./scripts/unified-collection-reader.js');
  const { targets, paging } = paginate(allFindings, { offset, limit: 5 });

This keeps the exact same { targets, paging } envelope, batch-of-5 default, and paging.nextOffset semantics as the live getBpaFindings path below — only the data source differs. Do not bypass the batch-of-5 discipline just because the whole array is already in memory.

  • Tell the user: *"Reusing N findings for <pattern> from the existing runbook (generated at

<generatedAt>)."*

  • Hand the batch to code-assessment as a `with_findings (pre-resolved)` invocation (see

{code-assessment}/references/runbook.md). Findings with line/snippet already populated skip the analyzer re-run entirely; findings with only file populated (BPA-sourced) still trigger one analyze.sh --files <paths> call inside code-assessment to resolve line/snippet before the edit plan is built.

  • If the cache is missing, has no entries for the active pattern, or the user explicitly says

"re-scan" / "refresh", fall through to the live flow below unchanged.

For BPA patterns (scheduler, resourceChangeListener, replication, eventListener, eventHandler, assetApi, lui, cdw) when no usable cache exists: Run `getBpaFindings` (with bpaFilePath when provided). Internally: cache → CSV → MCP → manual only when each step is applicable and succeeds; if MCP fails, obey MCP errors and fallback (stop; no silent chain). For MCP details, references/cam-mcp.md.

For lui findings, the identifier in each target is the JCR component path (e.g. /apps/myapp/components/content/mycomp) — not a Java class name. Resolve it to the filesystem path using the JCR → filesystem mapping before opening files. Note: luiCoral2 is not a standalone BPA pattern id — Coral 2 dialogs appear as the legacy.dialog.coral2 sub-type within lui results. Do not call getBpaFindings('luiCoral2', …) independently; call getBpaFindings('lui', …) and filter by sub-type inside Branch D.

For `dispatcherConversion`, targets are the Dispatcher config root(s) and detected mode from the dispatcher-inventory.js scan (surfaced in the Step 0 runbook), not from BPA — go straight to Branch E.

getBpaFindings returns a batch of 5 findings (default limit=5) along with a paging envelope. The agent processes that batch only; it does not request the next batch until the user says to continue. See Batched processing (batch size 5) below.

For `htlLint`: Skip BPA/CSV/MCP. If a cached runbook entry already has htlLint findings (they carry "confidence": "heuristic" — regex matches, not compiler-validated), reuse them per the cache-first rule above, but re-open and re-confirm each hit against the patterns in {code-assessment}/references/data-sly-test-redundant-constant.md before editing. If there is no cache, targets come from proactive rg discovery. See htlLint flow below.

For `osgiConfig` (OSGi → Cloud Manager): the cache holds heuristic, review-only findings ("confidence": "heuristic", key names + locations only — no secret values). Use them as a starting checklist, then follow Branch A and references/osgi-cfg-json-cloud-manager.md to classify each value (real secret? Adobe-owned PID → needs_user_review) — never trust the heuristic plaintext-secret label without confirming.

Step 4: Read before edits

STOP. Read `{code-assessment}/SKILL.md` and the pattern guide (or reference) for the active pattern — see Branch B step 2 above for the pattern → file routing table.

Step 5: Process the batch

For each finding in the returned batch only (up to 5):

  1. Resolve the target inside the IDE workspace (see Workspace scope (IDE)).
  2. Read source → classify with the pattern guide (or reference) → apply steps in order → check lints → next file.

Step 6: Report batch and wait

After finishing the batch, summarise for this batch only: paging.returned of paging.total processed (with class names), files touched, and any skips/failures. If paging.hasMore, tell the user "Processed batch of N (offset {offset}–{offset + returned − 1} of {total}). Reply `continue` for the next batch, or name specific classes."; otherwise say the pattern is done and move to the session report.

Then stop and wait — resume only when the user explicitly asks, per the Batched-processing rules.

Manual flow (no BPA)

User-named files → classify (code-assessment Manual Pattern Hints or ask) → confirm the pattern guide or reference exists → read `{code-assessment}/SKILL.md` + the pattern guide (or reference) — see Branch B step 2 routing — → transform → report.

OSGi → Cloud Manager flow

Does not use BPA CSV, CAM/MCP, or code-assessment pattern guides for collection. Follow Branch A in Required delegation and the One-prompt workflow in references/osgi-cfg-json-cloud-manager.md.

Template modernization flow (Branch C)

No BPA / MCP. Three phases — context → per-template execute → validate — fully defined in references/template-modernization/template-modernization-context.md. Use the confirmed context and per-template plan table first, execute generators via references/template-modernization/editable-template-creation.md and references/template-modernization/aem-modernization.md, then run references/template-modernization/template-modernization-validation.md. Do not commit on validation failure.

htlLint flow

htlLint does not use BPA CSV or CAM/MCP. Instead:

  1. Read `{code-assessment}/references/data-sly-test-redundant-constant.md` — it contains the Workflow, Proactive Discovery rg patterns, and all 4 fix patterns. (HTL lint lives as a shared reference, not a dedicated pattern guide.)
  2. Discover targets using the rg commands from the reference's Proactive Discovery table (scope: ui.apps/**/jcr_root/**/*.html or the user's content package paths).
  3. Group hits by file, classify each by pattern (boolean literal, raw string, numeric, split expression).
  4. Fix each hit per the matching pattern section in the reference.
  5. Report and recommend the user run mvn clean install or HTL validate to confirm no warnings remain.

Batched processing (batch size 5)

Findings are served to the agent in batches of 5 by default, regardless of source (MCP or CSV). Batching happens client-side — the heavy fetch (MCP call or CSV parse) happens once and is materialized to a local JSON cache; every subsequent batch is a cheap slice of that cache.

Rules

  1. Default `limit` is 5, and one batch per call — process, report, stop. Never hold more

than one batch in memory, pre-fetch, or merge across batches. Never pass limit: null in the skill flow (that option is for programmatic callers wanting the full list).

  1. Offset starts at 0 and advances by result.paging.nextOffset from the previous call —

read nextOffset, never compute offset + limit yourself.

  1. Stable ordering. Each cache file is written once in deterministic order, so slices are

stable and contiguous.

  1. Resume is stateless. No progress file — resuming means re-calling with

offset: previous.paging.nextOffset; a later session with the same pattern + offset gets the same batch. Done when `paging.hasMore === false` (or nextOffset === null).

  1. First call caches, later batches read the cache — one MCP fetch / CSV parse total, not

per batch. To refresh, delete the cache file: CSV <collectionsDir>/unified-collection.json; MCP <collectionsDir>/mcp/<projectId>/<pattern>.json.

Agent-visible flow

[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 }
...

Quick reference

Source priority (BPA patterns): unified collection → BPA CSV → MCP → manual paths — not an automatic cascade after MCP errors (if MCP fails, stop; see MCP errors and fallback). Batch size 5 on every BPA source. htlLint, OSGi→Cloud Manager, Template Modernization (C), and Legacy UI (D) do not use BPA/MCP — see their branches in Required delegation.

User-facing snippets: "Using existing BPA collection (N findings)…" / "Processing your BPA report…" / "Fetched findings from CAM." / "Scanning HTL templates for data-sly-test lint issues…" / optional prompt after MCP stop above.

CLI (development only)

From this skill's directory:

bash
# 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
同じリポジトリから

関連する Skills

すべての Skills
adobe
コミュニティ

aa-conversion-funnel-analysis

Analyzes a multi-step conversion funnel to find where visitors drop off and which steps have the worst leakage. Use this skill when someone describes a journey and asks about conversion rates, drop-off, fallout, or step completion. Trigger for "analyze our checkout funnel," "where are visitors dropping off," "what's our add-to-cart to purchase conversion rate," "funnel analysis," "show me fallout between steps," or "which step loses the most visitors."

導入数
1
GitHub Stars
178
更新日
9月8日
adobe
コミュニティ

analyze-and-plan

Use this when you need to define acceptance criteria, write requirements, scope work, or create a definition of done for AEM Edge Delivery Services (EDS) tasks such as new blocks, variants, behavior modifications, CSS-only changes, or bug fixes. Covers analyzing development requirements, producing task breakdowns, identifying edge cases, and documenting the analysis.

導入数
1
GitHub Stars
178
更新日
9月8日
adobe
コミュニティ

auth

Authenticate with AEM Edge Delivery Services. Opens browser for login and captures token. Works for admin.hlx.page and Config Service APIs regardless of content source (Document Authoring, SharePoint, or Google Drive).

導入数
1
GitHub Stars
178
更新日
9月8日
adobe
コミュニティ

block-collection-and-party

Use this when you are starting AEM Edge Delivery Services (EDS, Franklin, Helix) development and want an existing reference to build from, such as a block, build tool, code snippet, integration pattern, or plugin. Searches the Block Collection and Block Party repositories, matches candidates against the need, and returns a suitable starting point to clone or adapt.

導入数
1
GitHub Stars
178
更新日
9月8日