Skip to content

feat(aem-cloud-service): add guava-cache analyzer detector + expert skill - #331

Open
bharat941 wants to merge 4 commits into
mainfrom
feat/guava-cache-code-assessment
Open

feat(aem-cloud-service): add guava-cache analyzer detector + expert skill#331
bharat941 wants to merge 4 commits into
mainfrom
feat/guava-cache-code-assessment

Conversation

@bharat941

Copy link
Copy Markdown
Contributor

Adds the guava-cache code-assessment pattern — Guava cache (com.google.common.cache.*) → Caffeine (com.github.benmanes.caffeine.cache.*) on AEM as a Cloud Service. Follows the references/adding-a-pattern.md procedure; the slug guava-cache is wired into all four required places so the [wiring] test stays green.

Changes

  • Detector — scripts/analyzer/detectors/GuavaCache.java, registered in Registry.all(). Import-anchored on com.google.common.cache.* (Java-only). Exact package prefix means the io.micrometer…GuavaCacheMetrics BPA false positive is not flagged.
  • Expert skill — guava-cache/SKILL.md (control plane) + guava-cache/recipe.md (C1 pom swap, C2 imports, C3 builder/API mapping incl. getUncheckedget, CallableFunction, RemovalNotification→3-arg; test generation).
  • Catalog + routing — references/patterns.md row (low | ready | analyzer | guided) and Manual Pattern Hints row in code-assessment/SKILL.md.
  • Fixtures + test — test/code-assessment/fixtures/guava-cache/ (legacy guava / clean caffeine / micrometer guard) + a block in run-tests.sh.

Test Plan

run-tests.sh — 109 PASS / 0 FAIL (incl. [wiring] and the new [guava-cache] block). Detector flags com.google.common.cache.* imports; does not flag Caffeine or GuavaCacheMetrics. End-to-end on a real legacy AEM project: analyzer detects → recipe transform applied → analyzer re-scan clean → mvn compile BUILD SUCCESS.


Supersedes #326 — re-raised from a branch on adobe/skills now that write access is available (identical commits).

…kill

Adds the guava-cache code-assessment pattern (Guava cache -> Caffeine on AEM CS):

- GuavaCache detector: import-anchored on com.google.common.cache.* (Java-only),
  registered in Registry.all(); exact prefix avoids the micrometer GuavaCacheMetrics
  false positive.
- guava-cache/ expert skill: SKILL.md (control plane) + recipe.md (C1 pom swap,
  C2 imports, C3 builder/API mapping, test generation).
- Catalog row in patterns.md (low | ready | analyzer | guided) + Manual Pattern Hints
  routing row in code-assessment SKILL.md.
- Fixtures (legacy guava / clean caffeine / micrometer guard) + run-tests.sh block.

Analyzer suite: 109 PASS / 0 FAIL (incl. [wiring] + guava block).
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Tessl Plugin Lint

⚠️ edge-delivery-services — 2 warning(s)
⚠ Skill 'code-review': SKILL.md is approximately 10352 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.
⚠ Skill 'figma-to-content': SKILL.md is approximately 14744 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.

✔ Plugin adobe/aem-edge-delivery-services@0.1.0 is valid
⚠️ app-management — 1 warning(s)
⚠ Skill 'commerce-app-admin-ui': SKILL.md is approximately 5265 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.

✔ Plugin adobe/commerce-app-management@1.3.2 is valid

app-migration — clean

app-review — clean

run-workflow — clean

⚠️ stardust — 9 warning(s)
⚠ Skill 'extract': SKILL.md is approximately 9459 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.
⚠ Skill 'direct': SKILL.md is approximately 11694 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.
⚠ Skill 'prototype': SKILL.md is approximately 17875 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.
⚠ Skill 'migrate': SKILL.md is approximately 6375 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.
⚠ Skill 'uplift': SKILL.md is approximately 6515 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.
⚠ Skill 'audit': SKILL.md is approximately 5269 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.
⚠ Skill 'reskin': SKILL.md is approximately 5906 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.
⚠ Skill 'deploy': SKILL.md is approximately 38193 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.
⚠ Skill 'rollout': SKILL.md is approximately 6779 tokens (recommended maximum: 5000). Consider moving detailed content to separate reference files.

✔ Plugin adobe/stardust@0.18.1 is valid

✅ All 6 plugin(s) lint passed with 12 warning(s) total.

Updated by tessl-lint for commit cfaaf71.

| [`asset-manager`](../asset-manager/SKILL.md) | migrate DAM `AssetManager` create/upload via Direct Binary Access (`@adobe/aem-upload`) and delete via in-JVM `resolver.delete()` + `commit()` or HTTP Assets API; removes `createAssetForBinary` / `getAssetForBinary` / `removeAssetForBinary` (not available on CS) | high | ready | analyzer | guided |
| [`outbound-call-timeouts`](../outbound-call-timeouts/SKILL.md) | add connect/read/socket timeouts to outbound HTTP client construction (Apache HttpClient, OkHttp, JDK HttpClient) | high | ready | analyzer | mechanical |
| [`unbounded-query`](../unbounded-query/SKILL.md) | bound or escalate an explicitly-unbounded query (`p.limit=-1` predicate / `setLimit(-1)`) — safe-cap where provable, else flag for pagination | high | ready | analyzer | guided |
| [`guava-cache`](../guava-cache/SKILL.md) | swap Guava cache (`com.google.common.cache.*`) for Caffeine (`com.github.benmanes.caffeine.cache.*`) — pom dependency + imports + API call sites | low | ready | analyzer | guided |

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix: guided contradicts this pattern's self-evident contract (SKILL.md:37) and "mechanical" Overview (SKILL.md:13). Every other pattern keeps fix and contract aligned — guided↔guided, mechanical↔self-evident. Runbook.md:199 renders guided as apply (guided), mis-dispositioning these deterministic edits. Make it mechanical (like outbound-call-timeouts), or switch the contract to guided.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, severity: low (patterns.md:42) is the only low in the catalog — every other pattern is medium/high.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, follow the lui/cdw/htlLint precedent: drop it from Registry.java, patterns.md, and Hints; add a routing row in migration/SKILL.md with the recipe under migration/references/, discovered via BPA.


## Resolution contract

**self-evident** — the Guava → Caffeine API mapping is fixed (see [recipe.md](recipe.md)); no user input is required to plan the edit. The only judgment is the Caffeine version: pin it to the AEM CS SDK BOM (default `3.1.8`).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self-evident conflicts with fix: guided in patterns.md:42 — reconcile the two.


## Discovery

Detection is performed by the analyzer ([`../scripts/analyze.sh`](../scripts/README.md)), run by the runbook:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This finding already comes from BPA, so discovery should match the other migration patterns: BPA report (MCP or local CSV) first → local scan only as fallback. As wired (analyzer detector + ready|analyzer row), the sole path is a local scan that ignores the existing BPA finding. Source it via getBpaFindings first, local scan as fallback.

…ation

Guava cache usage doesn't occur in native AEMaaCS code, only in code carried
over from legacy AEM — so per review feedback this belongs to the migration
skill's domain, not code-assessment's.

- Remove the guava-cache expert skill, analyzer detector, and fixtures from
  code-assessment; revert its Registry/SKILL.md/patterns.md/run-tests.sh hooks.
- Add migration/references/guava-cache.md (BPA-driven reference, no dedicated
  pattern guide — same shape as htlLint).
- Wire guavaCache as a BPA-only pattern (subtype com.google.common.cache) into
  bpa-local-parser.js, unified-collection-reader.js, and runbook-generator.js's
  PATTERN_META — one finding per file, not per import, since BPA already
  reports at file granularity. No analyzer/content-scan fallback is added;
  with no BPA source the pattern surfaces via the existing LLM-scan tier.
- Drop internal "avoids the known BPA false positive" language; BPA is now
  the stated source of truth for this pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ummary

fetch-cam-bpa-findings-by-pattern's pattern enum already includes guavaCache
server-side; the migration skill's own summary of that tool's patterns was
missing it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Verified against a real customer BPA report (64k rows): the actual subtype
is `custom.guava.cache`, not `com.google.common.cache` as assumed from the
reference doc alone. More importantly, `identifier` on this subtype is a
Guava-internal class (e.g. com.google.common.cache.AbstractCache) reachable
on a bundle's classpath, not the customer's own class — BPA bytecode-scans
Guava's own cache implementation wherever it's embedded, so one real bundle
produced 1591 raw rows for two actual bundles.

- Group by bundle name (extracted from the message text), not by
  `identifier` — dedupes to one finding per bundle instead of ~800/bundle.
- Fix the subtype string everywhere it's checked/mapped.
- Update the reference doc and migration/SKILL.md to describe bundle-level
  discovery instead of file-level, and to explain why `identifier` can't be
  used directly.

Confirmed end-to-end against the real 64k-row report: getBpaFindings('guavaCache', ...)
now correctly returns exactly the 2 real bundles instead of ~1591 bogus entries.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants