AEM as a Cloud Service — Code Assessment
Single skill for detecting and fixing AEM CS code-quality issues, entirely against the local workspace — no external services or network calls. Findings reach the runbook from one of two sources; everything downstream is identical.
Findings sources
| Source |
When |
Target versions (deps) |
| User-named |
the user names files or coordinates |
user-supplied |
| Discover |
the user asks to scan, or names no files |
user-supplied (per the pattern's resolution contract) |
Discovery runs through the deterministic analyzer (scripts/analyze.sh):
it parses the workspace once and runs the enabled detectors, emitting the shared findings shape.
Every ready pattern has an analyzer detector. One detector — remove-deprecated-api — loads
its rules dynamically from a preflight-produced cache
(remove-deprecated-api/scripts/detect.sh runs the
AEM Analyser Maven Plugin and writes the cache TSV before the analyzer is invoked); the
detector's shape and integration are otherwise identical. Patterns without a detector are
planned only — not yet detectable and not yet built; there is no LLM-scan fallback in this
version (see Scope & limitations) — the scan value on planned rows in
references/patterns.md marks the intended future detection method,
not an active code path.
Routing
- User named files / coordinates → run the runbook in
with_findings mode against those paths.
- "Scan my repo" / no files named → run the runbook in
discover mode (per-pattern Discovery, workspace roots only).
Then follow the runbook: references/runbook.md.
Manual Pattern Hints (classification → expert skill)
Route the request to one expert skill. Two pattern families share this skill:
Mechanical fixes (analyzer-driven detection, deterministic edits — follow the runbook flow):
| User said / saw |
Expert skill |
"update aem sdk", "upgrade mockito", stale <version> or ${property} in pom |
outdated-dependencies/ |
"fix @Inject", "modernize Sling Models", javax.inject.Inject on @Model fields |
inject-in-sling-model/ |
"add HTTP timeouts", "outbound/external call has no timeout", HttpClient / HttpClients / OkHttpClient built without a timeout |
outbound-call-timeouts/ |
"bound my query", "unbounded query", "query causing OOM", p.limit=-1, setLimit(-1) |
unbounded-query/ |
"remove deprecated API", "fix deprecated imports", "Cloud Manager deprecated API failure", region-deprecated-api / api-regions-check / Import-Package not satisfied pipeline failures, log4j migration, commons-lang/collections upgrades, deprecated Maven deps, unmodifiable OSGi configs |
remove-deprecated-api/ (analyzer detector with dynamic rules — preflight runs aemanalyser-maven-plugin; hint-driven fixes; see recipe.md) |
Architectural migration patterns (guided remediation — full before/after, troubleshooting, modern alternatives; invoked directly or via migration for BPA/CAM-driven discovery):
| User said / saw |
Expert skill |
BPA pattern ID |
org.apache.sling.commons.scheduler.Scheduler or scheduler.schedule( with Runnable |
scheduler/ |
scheduler |
implements ResourceChangeListener, lightweight listener + JobConsumer |
resource-change-listener/ |
resourceChangeListener |
com.day.cq.replication.Replicator, org.apache.sling.replication.*, "publish/preview activation" |
replication/ |
replication |
javax.jcr.observation.EventListener, org.osgi.service.event.EventHandler on non-resource topics (replication, workflow, custom) |
event-migration/ |
eventListener / eventHandler |
com.day.cq.dam.api.AssetManager create/upload/delete APIs, createAssetForBinary, removeAssetForBinary |
asset-manager/ |
assetApi |
HTL build warning data-sly-test: redundant constant value comparison |
references/data-sly-test-redundant-constant.md |
htlLint (reference, no expert skill subdirectory) |
Broad / correctness-review asks ("check my Sling Models are implemented correctly", "review my code", "is my AEM project healthy", "assess this project") are not a single pattern: run the runbook in discover mode with intent report — the analyzer runs every detector and the report covers all built patterns, explicitly noting aspects not yet supported. Only narrow to one pattern when the user targets a specific fix.
If nothing matches, say the issue is not yet supported and offer to file a request for a new expert skill.
Full catalog (built + planned patterns, with severity / detection / fix): references/patterns.md.
Invocation from the migration skill
migration performs BPA/CAM/MCP discovery and handles batching + one-pattern-per-session workflow. After it has identified (pattern, file) pairs from BPA findings, it hands off here for the actual transformation. When invoked with (pattern, file) from migration:
- Skip HA/analyzer discovery (caller already identified the pattern + file)
- Open the pattern's expert skill directly (per the Manual Pattern Hints table above)
- Apply the steps in the expert skill against the named file(s)
- Return the result;
migration continues with the next finding in its batch
The pattern guides themselves are agnostic about who invoked them — they apply identically whether reached from migration (BPA/CAM) or from the runbook in this skill (HA / analyzer).
Runbook
All detection, planning, edits, verification, git/in-place handling, and the run log live in
references/runbook.md. The runbook is the sole owner of repo-environment
detection (edit_mode, git snapshot) — this control plane does not duplicate it.
One pattern per session
Report may span every pattern found; apply touches one pattern per session (atomic revert,
single-story diff). Refuse "fix everything" for the apply phase. Rationale:
references/shared-principles.md.
Critical rules
- Local only — no network calls or external services; operate solely on the workspace.
Documented exception:
remove-deprecated-api is plugin-driven and needs Maven Central
(to resolve aemanalyser-maven-plugin and, transitively, the AEM SDK's api-regions data) plus
optionally Adobe Experience League as a fallback source for successor guidance. If offline,
that one pattern is skipped with a clear message; all other patterns remain local-only.
- Requires a local JDK (Java 11+) for detection — the analyzer compiles/runs in memory; no
install beyond the JDK, no network. If absent, detection stops with a clear message.
- The analyzer is detection — never substitute external tooling. Do not run
mvn versions:display-dependency-updates / mvn versions:display-property-updates,
npm outdated, or Maven Central / registry lookups in place of analyzer discovery. Those answer
"what is the latest on the network" — outside this skill's local-only contract. If the user
explicitly wants a live registry comparison, say it needs network and offer it as a separate step
after delivering the skill report. remove-deprecated-api's preflight
(remove-deprecated-api/scripts/detect.sh) is the one documented exception: it invokes the AEM
Analyser Maven Plugin against the project to populate its rules cache, then hands off to the
shared analyzer.
- Never commit, push, or open a PR — branch (git) or in-place edits only; the developer reviews and commits.
- Surgical edits — no reformatting / re-serialization.
- Skip with a reason — record un-applicable findings as
skipped with an exact reason; never silently drop.
- One pattern per session for apply.
Full rationale: references/shared-principles.md.
Scope & limitations
Local static detection and remediation only — no external services, no network, no live AEM instance. Issues that require runtime or live-repository state, telemetry, or history across runs are out of scope for this skill.
Detection requires a local JDK (Java 11+); there is no remote or LLM-scan fallback in this version.
A large apply (e.g. an @Inject migration across 100+ files) is processed in resumable batches: the run checkpoints each file to .autofix/last-run.json and pauses at a per-pass cap, so it survives context limits — reply apply <pattern> to continue (see references/git-workflow.md).
Adding a new pattern
Full end-to-end procedure — detector → fixtures/tests → catalog + routing → expert skill → verify:
references/adding-a-pattern.md. The [wiring] test keeps the
detector, catalog row, and expert-skill directory in sync.
Triggering scales without touching the description. The description above is intentionally
broad (intent verbs + AEM domain), so it already fires on "check / review / fix my <AEM thing>";
a new pattern is reached by its Manual Pattern Hints + patterns.md rows, not by editing the
description. Update the description only if the new pattern introduces a domain keyword it does
not already cover (a new subsystem or file type). The [wiring] test keeps the detector, catalog
row, and expert-skill directory in sync.
Related skills
migration — drives BPA/CAM/MCP-based legacy-AEM migration workflow. Discovers findings, batches them, enforces one-pattern-per-session, and hands off (pattern, file) pairs to this skill for transformation. See the "Invocation from the migration skill" section above.
1---2name: code-assessment-23description: Detect, review, and fix code-quality and correctness issues in an AEM as a Cloud Service project — locally, with no external services or network calls. Use whenever a user wants to check, review, assess, audit, scan, modernize, upgrade, or fix AEM Java, Sling Models, OSGi, or Maven code — for example: "check my Sling Models are implemented correctly", "review my @Inject usage", "are my Maven dependencies up to date", "scan this AEM project for issues", "modernize my Sling Models", or "fix code-quality problems". Name the files to assess, or ask it to scan the repo; it detects issues, plans, and — only when you ask — applies surgical edits on a branch or in place, then verifies with mvn compile. It recognises the intent and handles each issue type itself, reporting anything it cannot yet fix.4license: Apache-2.05---67# AEM as a Cloud Service — Code Assessment89Single skill for detecting and fixing AEM CS code-quality issues, **entirely against the local workspace** — no external services or network calls. Findings reach the runbook from one of two sources; everything downstream is identical.1011## Findings sources1213| Source | When | Target versions (deps) |14|---|---|---|15| **User-named** | the user names files or coordinates | user-supplied |16| **Discover** | the user asks to scan, or names no files | user-supplied (per the pattern's resolution contract) |1718Discovery runs through the deterministic **analyzer** ([`scripts/analyze.sh`](scripts/README.md)):19it parses the workspace once and runs the enabled detectors, emitting the shared findings shape.20Every `ready` pattern has an analyzer detector. One detector — `remove-deprecated-api` — loads21its rules dynamically from a preflight-produced cache22([`remove-deprecated-api/scripts/detect.sh`](remove-deprecated-api/scripts/detect.sh) runs the23AEM Analyser Maven Plugin and writes the cache TSV before the analyzer is invoked); the24detector's shape and integration are otherwise identical. Patterns without a detector are25`planned` only — not yet detectable and not yet built; there is **no LLM-scan fallback** in this26version (see Scope & limitations) — the `scan` value on `planned` rows in27[`references/patterns.md`](references/patterns.md) marks the intended future detection method,28not an active code path.2930## Routing31321. **User named files / coordinates** → run the runbook in `with_findings` mode against those paths.332. **"Scan my repo" / no files named** → run the runbook in `discover` mode (per-pattern Discovery, workspace roots only).3435Then follow the runbook: [`references/runbook.md`](references/runbook.md).3637## Manual Pattern Hints (classification → expert skill)3839Route the request to one expert skill. Two pattern families share this skill:4041**Mechanical fixes** (analyzer-driven detection, deterministic edits — follow the runbook flow):4243| User said / saw | Expert skill |44|---|---|45| "update aem sdk", "upgrade mockito", stale `<version>` or `${property}` in pom | [`outdated-dependencies/`](outdated-dependencies/SKILL.md) |46| "fix @Inject", "modernize Sling Models", `javax.inject.Inject` on `@Model` fields | [`inject-in-sling-model/`](inject-in-sling-model/SKILL.md) |47| "add HTTP timeouts", "outbound/external call has no timeout", `HttpClient` / `HttpClients` / `OkHttpClient` built without a timeout | [`outbound-call-timeouts/`](outbound-call-timeouts/SKILL.md) |48| "bound my query", "unbounded query", "query causing OOM", `p.limit=-1`, `setLimit(-1)` | [`unbounded-query/`](unbounded-query/SKILL.md) |49| "remove deprecated API", "fix deprecated imports", "Cloud Manager deprecated API failure", `region-deprecated-api` / `api-regions-check` / `Import-Package not satisfied` pipeline failures, log4j migration, commons-lang/collections upgrades, deprecated Maven deps, unmodifiable OSGi configs | [`remove-deprecated-api/`](remove-deprecated-api/SKILL.md) _(analyzer detector with dynamic rules — preflight runs `aemanalyser-maven-plugin`; hint-driven fixes; see recipe.md)_ |5051**Architectural migration patterns** (guided remediation — full before/after, troubleshooting, modern alternatives; invoked directly or via `migration` for BPA/CAM-driven discovery):5253| User said / saw | Expert skill | BPA pattern ID |54|---|---|---|55| `org.apache.sling.commons.scheduler.Scheduler` or `scheduler.schedule(` with `Runnable` | [`scheduler/`](scheduler/SKILL.md) | `scheduler` |56| `implements ResourceChangeListener`, lightweight listener + JobConsumer | [`resource-change-listener/`](resource-change-listener/SKILL.md) | `resourceChangeListener` |57| `com.day.cq.replication.Replicator`, `org.apache.sling.replication.*`, "publish/preview activation" | [`replication/`](replication/SKILL.md) | `replication` |58| `javax.jcr.observation.EventListener`, `org.osgi.service.event.EventHandler` on non-resource topics (replication, workflow, custom) | [`event-migration/`](event-migration/SKILL.md) | `eventListener` / `eventHandler` |59| `com.day.cq.dam.api.AssetManager` create/upload/delete APIs, `createAssetForBinary`, `removeAssetForBinary` | [`asset-manager/`](asset-manager/SKILL.md) | `assetApi` |60| HTL build warning `data-sly-test: redundant constant value comparison` | [`references/data-sly-test-redundant-constant.md`](references/data-sly-test-redundant-constant.md) | `htlLint` (reference, no expert skill subdirectory) |6162**Broad / correctness-review asks** ("check my Sling Models are implemented correctly", "review my code", "is my AEM project healthy", "assess this project") are not a single pattern: run the runbook in `discover` mode with intent `report` — the analyzer runs every detector and the report covers all built patterns, explicitly noting aspects not yet supported. Only narrow to one pattern when the user targets a specific fix.6364If nothing matches, say the issue is not yet supported and offer to file a request for a new expert skill.6566**Full catalog** (built + `planned` patterns, with severity / detection / fix): [`references/patterns.md`](references/patterns.md).6768## Invocation from the `migration` skill6970`migration` performs BPA/CAM/MCP discovery and handles batching + one-pattern-per-session workflow. After it has identified `(pattern, file)` pairs from BPA findings, it hands off here for the actual transformation. When invoked with `(pattern, file)` from `migration`:7172- **Skip** HA/analyzer discovery (caller already identified the pattern + file)73- Open the pattern's expert skill directly (per the Manual Pattern Hints table above)74- Apply the steps in the expert skill against the named file(s)75- Return the result; `migration` continues with the next finding in its batch7677The pattern guides themselves are agnostic about who invoked them — they apply identically whether reached from `migration` (BPA/CAM) or from the runbook in this skill (HA / analyzer).7879## Runbook8081All detection, planning, edits, verification, git/in-place handling, and the run log live in82[`references/runbook.md`](references/runbook.md). The runbook is the **sole owner** of repo-environment83detection (`edit_mode`, git snapshot) — this control plane does not duplicate it.8485## One pattern per session8687Report may span every pattern found; **apply touches one pattern per session** (atomic revert,88single-story diff). Refuse "fix everything" for the apply phase. Rationale:89[`references/shared-principles.md`](references/shared-principles.md#one-pattern-per-session).9091## Critical rules9293- **Local only** — no network calls or external services; operate solely on the workspace.94 **Documented exception:** `remove-deprecated-api` is plugin-driven and needs Maven Central95 (to resolve `aemanalyser-maven-plugin` and, transitively, the AEM SDK's api-regions data) plus96 optionally Adobe Experience League as a fallback source for successor guidance. If offline,97 that one pattern is skipped with a clear message; all other patterns remain local-only.98- **Requires a local JDK** (Java 11+) for detection — the analyzer compiles/runs in memory; no99 install beyond the JDK, no network. If absent, detection stops with a clear message.100- **The analyzer is detection — never substitute external tooling.** Do not run101 `mvn versions:display-dependency-updates` / `mvn versions:display-property-updates`,102 `npm outdated`, or Maven Central / registry lookups in place of analyzer discovery. Those answer103 "what is the latest on the network" — outside this skill's local-only contract. If the user104 explicitly wants a live registry comparison, say it needs network and offer it as a separate step105 **after** delivering the skill report. `remove-deprecated-api`'s preflight106 (`remove-deprecated-api/scripts/detect.sh`) is the one documented exception: it invokes the AEM107 Analyser Maven Plugin against the project to populate its rules cache, then hands off to the108 shared analyzer.109- **Never commit, push, or open a PR** — branch (git) or in-place edits only; the developer reviews and commits.110- **Surgical edits** — no reformatting / re-serialization.111- **Skip with a reason** — record un-applicable findings as `skipped` with an exact reason; never silently drop.112- **One pattern per session** for apply.113114Full rationale: [`references/shared-principles.md`](references/shared-principles.md).115116## Scope & limitations117118Local static detection and remediation only — no external services, no network, no live AEM instance. Issues that require runtime or live-repository state, telemetry, or history across runs are out of scope for this skill.119Detection requires a local JDK (Java 11+); there is no remote or LLM-scan fallback in this version.120A large apply (e.g. an `@Inject` migration across 100+ files) is processed in **resumable batches**: the run checkpoints each file to `.autofix/last-run.json` and pauses at a per-pass cap, so it survives context limits — reply **apply `<pattern>`** to continue (see [`references/git-workflow.md`](references/git-workflow.md)).121122## Adding a new pattern123124Full end-to-end procedure — detector → fixtures/tests → catalog + routing → expert skill → verify:125**[`references/adding-a-pattern.md`](references/adding-a-pattern.md)**. The `[wiring]` test keeps the126detector, catalog row, and expert-skill directory in sync.127128**Triggering scales without touching the description.** The `description` above is intentionally129broad (intent verbs + AEM domain), so it already fires on "check / review / fix my <AEM thing>";130a new pattern is reached by its **Manual Pattern Hints + `patterns.md` rows**, not by editing the131description. Update the description **only** if the new pattern introduces a domain keyword it does132not already cover (a new subsystem or file type). The `[wiring]` test keeps the detector, catalog133row, and expert-skill directory in sync.134135## Related skills136137- **`migration`** — drives BPA/CAM/MCP-based legacy-AEM migration workflow. Discovers findings, batches them, enforces one-pattern-per-session, and hands off `(pattern, file)` pairs to this skill for transformation. See the "Invocation from the `migration` skill" section above.