Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tessl-eval.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ jobs:
echo "::group::Evaluating $TILE_NAME ($tile_dir)"

EXIT_CODE=0
OUTPUT=$(tessl eval run "$tile_dir" --workspace adobe 2>&1) || EXIT_CODE=$?
OUTPUT=$(tessl eval run "$tile_dir" 2>&1) || EXIT_CODE=$?
echo "$OUTPUT"
echo "::endgroup::"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"context": "Tests whether the agent produces structured acceptance criteria for an iOS Safari scroll-snap bug fix without writing code or proposing a solution. Covers bug analysis, root cause investigation, reproduction steps, cross-browser scope, and regression prevention.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Bug clearly restated",
"max_score": 10,
"description": "Accurately summarizes the reported behavior (carousel snaps back to first item), the affected browser (iOS Safari only), and the trigger condition (swipe to next testimonial)"
},
{
"name": "Root cause analysis",
"max_score": 15,
"description": "Identifies the CSS change from overflow-x: auto to overflow-x: scroll as the likely cause; discusses the scroll-snap and overflow interaction on iOS Safari"
},
{
"name": "Expected behavior defined",
"max_score": 12,
"description": "Clearly states what correct scrolling behavior looks like: carousel advances to the next item on swipe and stays there, consistently across all browsers"
},
{
"name": "Reproduction criteria",
"max_score": 10,
"description": "Describes how to reproduce the bug: iOS Safari, swipe gesture on the carousel, and any specific conditions (e.g., number of items, scroll speed)"
},
{
"name": "Edge cases identified",
"max_score": 12,
"description": "Addresses edge cases such as rapid swiping, swiping past the last item, single-item carousel, orientation change during scroll, and programmatic scroll"
},
{
"name": "Cross-browser scope",
"max_score": 10,
"description": "Acceptance criteria ensure the fix does not break behavior on Chrome, Firefox, or desktop Safari"
},
{
"name": "No premature solution",
"max_score": 10,
"description": "Analyzes the problem without prescribing a specific CSS fix or implementation approach"
},
{
"name": "Responsive behavior considered",
"max_score": 8,
"description": "Mentions different viewport behaviors if relevant (e.g., touch vs non-touch, portrait vs landscape)"
},
{
"name": "Definition of done is testable",
"max_score": 8,
"description": "Includes a specific browser/device test matrix (e.g., iOS Safari 16+, Chrome latest, Firefox latest, desktop Safari)"
},
{
"name": "Regression prevention",
"max_score": 5,
"description": "Mentions the need for a test or verification step to prevent re-introduction of the bug in future refactors"
}
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Testimonial Carousel iOS Safari Scroll Bug — Analyze and Plan

## Bug Report

On the AEM Edge Delivery Services site, the `testimonial-carousel` block has a scrolling issue on iOS Safari. When a user swipes to the next testimonial, the carousel sometimes snaps back to the first item instead of advancing. This only happens on iOS Safari (works fine on Chrome, Firefox, and desktop Safari). The block uses CSS scroll-snap for navigation. The issue was introduced after a recent CSS refactor that changed the carousel container from `overflow-x: auto` to `overflow-x: scroll`.

## Output Specification

Analyze this bug and produce structured acceptance criteria for the fix. Do NOT write any code or propose a solution.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"context": "Tests whether the agent produces structured acceptance criteria for adding a video variant to an existing Hero block without writing code. Covers variant behavior, video attributes, mobile fallback, impact assessment, edge cases, and accessibility.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Variant behavior clearly defined",
"max_score": 15,
"description": "Describes what the video variant does differently from the existing image variant; clearly distinguishes the two variants' behavior"
},
{
"name": "Video attributes specified",
"max_score": 12,
"description": "Mentions autoplay, muted, and loop requirements for the background video"
},
{
"name": "Mobile fallback addressed",
"max_score": 15,
"description": "Poster image fallback on mobile is explicitly covered with criteria for when and how it triggers (e.g., viewport breakpoint, device detection, or connection speed)"
},
{
"name": "Impact on existing variant assessed",
"max_score": 10,
"description": "Confirms that the existing image variant must remain unchanged and functional; assesses risk of regression"
},
{
"name": "Edge cases identified",
"max_score": 12,
"description": "Addresses edge cases such as: video fails to load, no poster image provided, unsupported video format, very short or very long videos"
},
{
"name": "Responsive behavior specified",
"max_score": 10,
"description": "Mobile poster vs desktop video behavior is explicitly defined; tablet behavior is mentioned or addressed"
},
{
"name": "Author experience documented",
"max_score": 10,
"description": "Describes how the author enables the video variant and provides video/poster content (NOT implementation details like CSS classes or HTML attributes)"
},
{
"name": "Accessibility considered",
"max_score": 8,
"description": "Mentions reduced motion preference (prefers-reduced-motion), video without audio implications, or screen reader considerations"
},
{
"name": "Definition of done is testable",
"max_score": 8,
"description": "Specific, verifiable completion conditions that can be checked without ambiguity"
}
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Hero Block Video Variant — Analyze and Plan

## Problem/Feature Description

An existing Hero block on an AEM Edge Delivery Services site currently shows a full-width background image with overlaid headline and CTA. The client wants to add a new `video` variant that replaces the background image with an autoplaying, muted, looping background video. On mobile, the video should fall back to a poster image for performance. The text overlay and CTA should remain identical to the image variant.

## Output Specification

Analyze this variant addition and produce structured acceptance criteria. Do NOT write any code.

Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"context": "Tests whether the agent produces structured acceptance criteria for a new Pricing Table block without writing code. Covers functional requirements, edge cases, responsive behavior, author experience, and testable definition of done.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Functional requirements listed",
"max_score": 15,
"description": "Covers rendering of all 3 tiers (Basic, Pro, Enterprise), feature comparison list, pricing display, CTA buttons per tier, and visually highlighted 'recommended' Pro tier"
},
{
"name": "Pricing toggle addressed",
"max_score": 10,
"description": "Acceptance criteria mention the monthly/annual pricing toggle behavior and state management (e.g., which is the default state, how prices update on toggle)"
},
{
"name": "Edge cases identified",
"max_score": 15,
"description": "Addresses edge cases such as empty feature rows, missing CTA, uneven feature counts across tiers, very long tier names, or missing pricing for one billing period"
},
{
"name": "Responsive behavior specified",
"max_score": 12,
"description": "Mobile stacking and desktop side-by-side layout are explicitly defined; tablet behavior is mentioned or addressed"
},
{
"name": "Author experience documented",
"max_score": 12,
"description": "Describes what content inputs authors provide (NOT table/cell structure or implementation details); distinguishes required vs optional fields"
},
{
"name": "No premature implementation details",
"max_score": 10,
"description": "Does NOT prescribe HTML structure, CSS classes, or JS implementation; stays at the requirements/acceptance-criteria level"
},
{
"name": "Definition of done is testable",
"max_score": 10,
"description": "Completion conditions are specific and verifiable (e.g., 'all 3 tiers render with correct pricing'), not vague (e.g., 'block works correctly')"
},
{
"name": "Ambiguities flagged",
"max_score": 8,
"description": "Identifies open questions or ambiguities (e.g., what happens when a tier has no CTA? Is the toggle state persisted across page navigation? What currency format is used?)"
},
{
"name": "Structured format used",
"max_score": 8,
"description": "Output uses a structured template with clear sections such as functional requirements, edge cases, responsive behavior, author experience, and definition of done"
}
]
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Pricing Table Block — Analyze and Plan

## Problem/Feature Description

A client wants a Pricing Table block for their AEM Edge Delivery Services site. It shows 3 pricing tiers (Basic, Pro, Enterprise) with a feature comparison list, monthly/annual pricing toggle, and CTA buttons per tier. The Pro tier should be visually highlighted as "recommended". On mobile, tiers should stack vertically. On desktop, they should sit side by side.

## Output Specification

Analyze this requirement and produce structured acceptance criteria following the analyze-and-plan workflow. Do NOT write any code.

Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"context": "Tests whether the agent follows AEM EDS block file structure conventions and performance optimization patterns. Covers correct directory/file naming with kebab-case, lazy loading with IntersectionObserver, deferred heavy operations, dynamic imports for conditional modules, and proper use of aem.js utilities.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Correct directory path",
"max_score": 8,
"description": "The block JavaScript file is created at `blocks/{block-name}/{block-name}.js` (e.g., `blocks/video-embed/video-embed.js`), matching the block name exactly in kebab-case"
},
{
"name": "Correct CSS file path",
"max_score": 7,
"description": "The block CSS file is created at `blocks/{block-name}/{block-name}.css` (e.g., `blocks/video-embed/video-embed.css`), matching the block name in kebab-case"
},
{
"name": "IntersectionObserver for lazy load",
"max_score": 15,
"description": "Uses `IntersectionObserver` to defer loading the heavy embed content until the block enters the viewport (not loading immediately in the decorate function body)"
},
{
"name": "Observer disconnect after trigger",
"max_score": 10,
"description": "After the intersection is detected and loading triggered, the observer is disconnected (`observer.disconnect()`) to avoid firing repeatedly"
},
{
"name": "Minimal initial decoration",
"max_score": 10,
"description": "The synchronous/immediate part of decorate() does minimal work (e.g., adds placeholder UI or initializes observer) rather than eagerly fetching data or building complex DOM"
},
{
"name": "Dynamic import for heavy module",
"max_score": 12,
"description": "Any heavy or conditionally needed JavaScript module (e.g., a third-party player library or complex renderer) is loaded via dynamic `import()` inside the observer callback or conditional branch, NOT as a top-level static import"
},
{
"name": "aem.js imports with .js extension",
"max_score": 8,
"description": "Any import from `scripts/aem.js` uses the full relative path with `.js` extension: `import { ... } from '../../scripts/aem.js'`"
},
{
"name": "aem.js not modified",
"max_score": 8,
"description": "The solution does NOT modify or overwrite `scripts/aem.js`; it only imports from it"
},
{
"name": "async decorate function",
"max_score": 7,
"description": "The decorate function is declared with the `async` keyword (since it awaits operations or performs async logic)"
},
{
"name": "Default export decorate",
"max_score": 7,
"description": "The block JS uses `export default` for the decorate function"
},
{
"name": "Error handling on fetch",
"max_score": 8,
"description": "Any network requests (fetch) inside the block include a try/catch or .catch() error handler"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Video Embed Block — Performance-Optimized Implementation

## Problem/Feature Description

The editorial team at GlobalMedia Group wants to embed YouTube videos on multiple pages of their AEM Edge Delivery Services website. Video embeds are known to be a major source of page performance degradation — loading the YouTube iframe API and player code eagerly means the video player JavaScript starts executing before the user even scrolls to it, hurting Largest Contentful Paint (LCP) scores and Core Web Vitals.

The team needs a `video-embed` block that shows a static thumbnail image with a play button overlay as the initial state. The actual YouTube player should only be loaded and initialized when a user scrolls the block into the visible viewport. The block should support being placed anywhere on the page — including above the fold in hero sections — but must prioritize page performance in all cases by deferring the YouTube API load until it is needed. Authors will add the block to pages by putting the YouTube video URL in a simple one-cell table in Google Docs.

## Output Specification

Create a complete, working implementation of the `video-embed` block including:
- The JavaScript decoration file (at the standard AEM block path)
- The CSS file (at the standard AEM block path)

The implementation should:
- Parse the YouTube URL from the authored content to extract the video ID
- Display a clickable thumbnail as the initial state using YouTube's thumbnail URL format: `https://img.youtube.com/vi/{videoId}/hqdefault.jpg`
- Load the YouTube player only when the block scrolls into view
- Replace the thumbnail with the YouTube iframe once loading is triggered

Do not include the YouTube iframe API `<script>` tag in your HTML — load it dynamically from JavaScript when needed.

## Input Files

The following files are provided as inputs. Extract them before beginning.

=============== FILE: inputs/sample-block-content.html ===============
<!-- This shows the DOM structure the AEM platform delivers to the decorate() function.
The block receives one div child containing the authored YouTube URL as a paragraph. -->
<div class="video-embed">
<div>
<div>
<p>https://www.youtube.com/watch?v=dQw4w9WgXcQ</p>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"context": "Tests whether the agent follows AEM EDS CSS guidelines when implementing block styles. Covers selector scoping, CSS custom property usage, mobile-first responsive design with modern syntax, modern color and layout approaches, and anti-patterns to avoid.",
"type": "weighted_checklist",
"checklist": [
{
"name": "Block selector scoping",
"max_score": 12,
"description": "All CSS selectors begin with `main .{block-name}` (e.g., `main .testimonial-carousel { ... }`), not bare element names or unscoped class names"
},
{
"name": "No unscoped selectors",
"max_score": 8,
"description": "No CSS rules use bare element selectors (e.g., `h2 { }`, `.item { }`) that are not prefixed with `main .{block-name}`"
},
{
"name": "CSS custom properties for color",
"max_score": 10,
"description": "Uses CSS custom property variables for at least one color value (e.g., `var(--background-color)`, `var(--text-color)`, `var(--link-color)`) rather than hardcoded color values"
},
{
"name": "CSS custom properties for typography",
"max_score": 10,
"description": "Uses CSS custom property variables for at least one font value (e.g., `var(--body-font-family)`, `var(--heading-font-family)`, `var(--heading-font-size-m)`) rather than hardcoded font names or sizes"
},
{
"name": "Mobile-first default styles",
"max_score": 8,
"description": "Default (non-media-query) CSS styles represent mobile layout; larger screen styles are added inside media queries"
},
{
"name": "Modern media query syntax",
"max_score": 8,
"description": "Media queries use range syntax `(width >= 600px)` or `(width >= 900px)` rather than legacy `(min-width: Xpx)` syntax"
},
{
"name": "Standard breakpoints",
"max_score": 6,
"description": "Media queries use 600px for tablet and/or 900px for desktop breakpoints (not arbitrary values)"
},
{
"name": "No !important usage",
"max_score": 8,
"description": "The CSS file does NOT contain any `!important` declarations"
},
{
"name": "Variant CSS pattern",
"max_score": 6,
"description": "If variants (dark, wide, etc.) are styled, the selector combines block and variant classes: `main .{block-name}.{variant}` pattern"
},
{
"name": "No -wrapper/-container suffix inside block",
"max_score": 6,
"description": "Class names used inside the block do NOT end in `-wrapper` or `-container` (to avoid conflict with platform-generated wrapper divs)"
},
{
"name": "Gap over margin hacks",
"max_score": 8,
"description": "Flex or grid layouts use the `gap` property for spacing between items, NOT margin-based spacing tricks (e.g., `margin-left: -1rem` on container)"
},
{
"name": "No hardcoded font families",
"max_score": 10,
"description": "Font-family values use CSS custom properties (e.g., `var(--body-font-family)`) and NOT hardcoded font names like `'Arial'`, `'Lato'`, or `sans-serif`"
}
]
}
Loading