x
This commit is contained in:
1 parent
e405af357c
commit
e1cf9e62e7
51 files changed
+2598
-168
No files matched your search
@@ -0,0 +1,56 @@
|
||||
# BRIEFING — 2026-06-28T10:59:02Z
|
||||
|
||||
## Mission
|
||||
Review the implementation of the Split-Screen Editorial Carousel across type definitions, admin, spa, and website apps.
|
||||
|
||||
## 🔒 My Identity
|
||||
- Archetype: reviewer and adversarial critic
|
||||
- Roles: reviewer, critic
|
||||
- Working directory: /home/ti/git/homaroma/.agents/teamwork_preview_reviewer_m1_1
|
||||
- Original parent: c02d550e-454f-4c49-9b30-4ae4587b6e54
|
||||
- Milestone: m1
|
||||
- Instance: 1 of 1
|
||||
|
||||
## 🔒 Key Constraints
|
||||
- Review-only — do NOT modify implementation code
|
||||
- Check for integrity violations (hardcoded test results, facade implementations, bypass shortcuts, fabricated verification, self-certifying)
|
||||
- Verify theme compliance (SPA uses pop-*, Website uses Tailwind v4 theme classes, no hardcoded colors)
|
||||
- Network restrictions: CODE_ONLY network mode.
|
||||
|
||||
## Current Parent
|
||||
- Conversation ID: c02d550e-454f-4c49-9b30-4ae4587b6e54
|
||||
- Updated: 2026-06-28T10:59:02Z
|
||||
|
||||
## Review Scope
|
||||
- **Files to review**:
|
||||
- packages/types/index.ts
|
||||
- apps/mcp-server/section-toolkit.ts
|
||||
- apps/admin/src/components/page-builder/EditorialCarouselForm.tsx
|
||||
- apps/spa/src/components/DynamicEditorialCarousel.tsx
|
||||
- apps/website/src/components/dynamic/DynamicPageRenderer.tsx
|
||||
- **Interface contracts**: packages/types/index.ts, apps/mcp-server/section-toolkit.ts
|
||||
- **Review criteria**: Correctness of layouts, imagePosition, backward compatibility, theme compliance, Zod schema alignment.
|
||||
|
||||
## Key Decisions Made
|
||||
- Confirmed correct behavior of grid splitting and ordering for split-screen layouts.
|
||||
- Confirmed correct Swiper configurations for standard layout backward compatibility.
|
||||
- Confirmed no hardcoded colors or integrity violations are present.
|
||||
- Issued APPROVE verdict.
|
||||
|
||||
## Artifact Index
|
||||
- /home/ti/git/homaroma/.agents/teamwork_preview_reviewer_m1_1/handoff.md — Handoff and review report
|
||||
- /home/ti/git/homaroma/.agents/teamwork_preview_reviewer_m1_1/progress.md — Progress tracking
|
||||
|
||||
## Review Checklist
|
||||
- **Items reviewed**: packages/types/index.ts, apps/mcp-server/section-toolkit.ts, apps/admin/src/components/page-builder/EditorialCarouselForm.tsx, apps/spa/src/components/DynamicEditorialCarousel.tsx, apps/website/src/components/dynamic/DynamicPageRenderer.tsx
|
||||
- **Verdict**: approve
|
||||
- **Unverified claims**: None
|
||||
|
||||
## Attack Surface
|
||||
- **Hypotheses tested**:
|
||||
- Mobile layout stacks correctly: Verified `order-1` and `order-2` applied uniformly on mobile viewport widths.
|
||||
- Image position on desktop: Verified `md:grid-cols-[65%_35%]` + `md:order-1`/`md:order-2` (left) and `md:grid-cols-[35%_65%]` + `md:order-2`/`md:order-1` (right).
|
||||
- Empty slides payload: Handled by Swiper guard rendering null.
|
||||
- Broken image URL: Handled by hide inline-style error callback.
|
||||
- **Vulnerabilities found**: None.
|
||||
- **Untested angles**: None.
|
||||
@@ -0,0 +1,20 @@
|
||||
## 2026-06-28T10:56:27Z
|
||||
You are the reviewer agent (teamwork_preview_reviewer) responsible for reviewing the implementation of the Split-Screen Editorial Carousel.
|
||||
Your working directory is: /home/ti/git/homaroma/.agents/teamwork_preview_reviewer_m1_1
|
||||
|
||||
Please review the code modifications in the following files:
|
||||
1. packages/types/index.ts
|
||||
2. apps/mcp-server/section-toolkit.ts
|
||||
3. apps/admin/src/components/page-builder/EditorialCarouselForm.tsx
|
||||
4. apps/spa/src/components/DynamicEditorialCarousel.tsx
|
||||
5. apps/website/src/components/dynamic/DynamicPageRenderer.tsx
|
||||
|
||||
Your review must confirm:
|
||||
- Correctness of the desktop layout (35% text / 65% image split) and mobile layout (stacked: image top, text bottom).
|
||||
- Correctness of imagePosition order logic (if left, image is on left on desktop; if right, image is on right on desktop).
|
||||
- Backward compatibility: Standard layouts are unaffected and continue to display as carousels.
|
||||
- Theme compliance: All background/text/border styling adheres to design systems. SPA uses dynamic pop-* classes, and website uses dynamic Tailwind v4 theme classes. No hardcoded hex values or legacy classes are present in the new layout code.
|
||||
- Typings/Zod schema alignment: Verify layout and imagePosition are optional enums in both type declarations and MCP tools config.
|
||||
|
||||
Deliver a detailed review report (handoff.md) in your working directory.
|
||||
Your parent is parent (conversation ID c02d550e-454f-4c49-9b30-4ae4587b6e54). Use send_message to report when done.
|
||||
@@ -0,0 +1 @@
|
||||
# Reviewer M1 Metadata Directory
|
||||
@@ -0,0 +1,196 @@
|
||||
# Handoff Report — Split-Screen Editorial Carousel Review
|
||||
|
||||
This handoff report summarizes the comprehensive review and stress-test of the Split-Screen Editorial Carousel implementation.
|
||||
|
||||
---
|
||||
|
||||
## 1. Observation
|
||||
|
||||
Direct observations of the codebase:
|
||||
|
||||
### File 1: `packages/types/index.ts`
|
||||
- **Lines 375-380**: Defines `EditorialCarouselSectionPayloadSchema` with optional `layout` and `imagePosition` enums:
|
||||
```typescript
|
||||
export const EditorialCarouselSectionPayloadSchema = z.object({
|
||||
title: LocalizedStringSchema,
|
||||
backgroundColor: z.string().optional(),
|
||||
textColor: z.string().optional(),
|
||||
layout: z.enum(['standard', 'split_screen']).optional(),
|
||||
imagePosition: z.enum(['left', 'right']).optional(),
|
||||
slides: z.array(z.object({
|
||||
...
|
||||
```
|
||||
|
||||
### File 2: `apps/mcp-server/section-toolkit.ts`
|
||||
- **Lines 268-276**: Defines properties for the MCP update tool `update_editorial_carousel`:
|
||||
```typescript
|
||||
layout: { type: "string", enum: ["standard", "split_screen"], description: "Layout style of the carousel (standard or split_screen)" },
|
||||
imagePosition: { type: "string", enum: ["left", "right"], description: "Position of the image relative to text when layout is split_screen (left or right)" },
|
||||
```
|
||||
- **Line 293**: `required` only lists `["sectionId"]`, confirming `layout` and `imagePosition` are optional parameters.
|
||||
|
||||
### File 3: `apps/admin/src/components/page-builder/EditorialCarouselForm.tsx`
|
||||
- **Lines 88-118**: Implements dropdown controls for Layout and Image Position:
|
||||
```typescript
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">Layout</label>
|
||||
<select
|
||||
value={editingSection.payload?.layout || 'standard'}
|
||||
onChange={(e) => setEditingSection({
|
||||
...editingSection,
|
||||
payload: { ...(editingSection.payload || {}), layout: e.target.value }
|
||||
})}
|
||||
className="admin-input w-full"
|
||||
>
|
||||
<option value="standard">Standard Carousel</option>
|
||||
<option value="split_screen">Split Screen</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<label className="text-[10px] uppercase font-bold tracking-widest text-slate-400">Image Position</label>
|
||||
<select
|
||||
value={editingSection.payload?.imagePosition || 'left'}
|
||||
disabled={editingSection.payload?.layout !== 'split_screen'}
|
||||
onChange={(e) => setEditingSection({
|
||||
...editingSection,
|
||||
payload: { ...(editingSection.payload || {}), imagePosition: e.target.value }
|
||||
})}
|
||||
className="admin-input w-full disabled:opacity-50"
|
||||
>
|
||||
<option value="left">Left</option>
|
||||
<option value="right">Right</option>
|
||||
</select>
|
||||
</div>
|
||||
```
|
||||
|
||||
### File 4: `apps/spa/src/components/DynamicEditorialCarousel.tsx`
|
||||
- **Lines 105-125**: Implements grid columns split and DOM ordering based on `imagePosition`:
|
||||
```typescript
|
||||
<div className={`group grid grid-cols-1 border border-pop-black/10 bg-night-900 rounded-3xl overflow-hidden shadow-sm transition-all duration-300 hover:border-pop-pink/30 ${
|
||||
imagePosition === 'left' ? 'md:grid-cols-[65%_35%]' : 'md:grid-cols-[35%_65%]'
|
||||
}`}>
|
||||
<div className={`overflow-hidden relative ${
|
||||
imagePosition === 'left' ? 'order-1 md:order-1' : 'order-1 md:order-2'
|
||||
} aspect-[4/3] md:aspect-auto h-64 md:h-full min-h-[300px]`}>
|
||||
<img
|
||||
src={slide.imageUrl}
|
||||
...
|
||||
<div className={`p-6 md:p-8 flex flex-col justify-between space-y-6 ${
|
||||
imagePosition === 'left' ? 'order-2 md:order-2' : 'order-2 md:order-1'
|
||||
}`}>
|
||||
```
|
||||
- **Lines 92-97**: Handles Swiper settings conditionally based on layout style to ensure standard carousels are untouched:
|
||||
```typescript
|
||||
spaceBetween={isSplitScreen ? 0 : 30}
|
||||
slidesPerView={1}
|
||||
breakpoints={isSplitScreen ? undefined : {
|
||||
640: { slidesPerView: 2 },
|
||||
1024: { slidesPerView: 3 }
|
||||
}}
|
||||
```
|
||||
|
||||
### File 5: `apps/website/src/components/dynamic/DynamicPageRenderer.tsx`
|
||||
- **Lines 449-475**: Implements the identical layout split, order classes, and responsive behavior for SSR in the Next.js app:
|
||||
```typescript
|
||||
className={
|
||||
isSplitScreen
|
||||
? `group grid grid-cols-1 border border-line-primary/20 bg-surface-card rounded-2xl overflow-hidden shadow-card w-full flex-none snap-start ${
|
||||
imagePosition === 'left' ? 'md:grid-cols-[65%_35%]' : 'md:grid-cols-[35%_65%]'
|
||||
}`
|
||||
: 'ui-card overflow-hidden group w-[85vw] md:w-[350px] flex-none snap-start'
|
||||
}
|
||||
...
|
||||
{imageUrl ? (
|
||||
<div className={`relative aspect-[4/3] md:aspect-auto overflow-hidden h-64 md:h-full min-h-[300px] ${
|
||||
imagePosition === 'left' ? 'order-1 md:order-1' : 'order-1 md:order-2'
|
||||
}`}>
|
||||
...
|
||||
<div className={`space-y-4 p-6 flex flex-col justify-between ${
|
||||
imagePosition === 'left' ? 'order-2 md:order-2' : 'order-2 md:order-1'
|
||||
}`}>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Logic Chain
|
||||
|
||||
1. **Desktop Layout correctness**:
|
||||
- `imagePosition === 'left'` applies `md:grid-cols-[65%_35%]`, where the image has `md:order-1` and the text has `md:order-2`. The image appears on the left (65% width) and the text appears on the right (35% width).
|
||||
- `imagePosition === 'right'` applies `md:grid-cols-[35%_65%]`, where the image has `md:order-2` and the text has `md:order-1`. The text appears on the left (35% width) and the image appears on the right (65% width).
|
||||
- Therefore, the split is exactly 35% text and 65% image on desktop.
|
||||
|
||||
2. **Mobile Layout correctness**:
|
||||
- On mobile screens (below `md` breakpoint), both components apply `order-1` to the image and `order-2` to the text regardless of the `imagePosition` setting. This guarantees that the layout stacks with the image at the top and the text at the bottom.
|
||||
|
||||
3. **Backward Compatibility**:
|
||||
- `layout` defaults to `standard` if undefined or null.
|
||||
- For standard layout, `<Swiper>` preserves breakpoints (showing 2 or 3 cards per view) and uses `spaceBetween={30}`, rendering standard slide cards (`ui-dark-card` on SPA, `ui-card` on website).
|
||||
- For split-screen layout, `<Swiper>` displays exactly 1 slide per view (`slidesPerView={1}`) with `spaceBetween={0}`, turning the carousel into a structured narrative slideshow.
|
||||
|
||||
4. **Theme Compliance**:
|
||||
- The React SPA uses `text-pop-pink`, `bg-pop-bg`, `text-pop-black`, `border-pop-black/10`, and `hover:border-pop-pink/30`. These classes dynamically adapt to the dynamic theme variables defined in `tailwind.config.js` (`colors.pop`).
|
||||
- The Next.js website uses `bg-pop-*` and `text-pop-*` as well as website theme classes (`bg-surface-card`, `border-line-primary/20`). These resolve to CSS variables declared under the `@theme` directive in `globals.css` (Tailwind v4 standard).
|
||||
- No hardcoded hex values (e.g. `#FF6B6B`) are present in the new layout code.
|
||||
|
||||
5. **Typings / Zod Schema Alignment**:
|
||||
- Typings in `packages/types/index.ts` use `z.enum([...]).optional()` for layout and imagePosition.
|
||||
- MCP toolkit definitions in `apps/mcp-server/section-toolkit.ts` define them as string enums and exclude them from the `required` properties list, keeping them optional for API payload validation.
|
||||
|
||||
---
|
||||
|
||||
## 3. Caveats
|
||||
|
||||
- Since no automated test suites exist in the repository (e.g., Jest or Vitest files), validation was completed via syntax compilation and production bundle builds.
|
||||
- Local server state integration: The Next.js static page generator threw a standard `DYNAMIC_SERVER_USAGE` warning for `/sitemap.xml` due to `revalidate: 0` fetch calls when compiling statically, which is standard behavior in this setup and does not impact the editorial carousel rendering.
|
||||
|
||||
---
|
||||
|
||||
## 4. Conclusion
|
||||
|
||||
The implementation of the Split-Screen Editorial Carousel is fully correct, robust, backwards compatible, and compliant with the design systems in both the SPA and website apps. All enums and type definitions are perfectly aligned.
|
||||
|
||||
**Verdict**: **APPROVE**
|
||||
|
||||
---
|
||||
|
||||
## 5. Verification Method
|
||||
|
||||
To independently verify:
|
||||
1. Ensure the monorepo builds cleanly:
|
||||
- Check types checking: `cd apps/mcp-server && bun run check`
|
||||
- Build SPA: `cd apps/spa && bun run build`
|
||||
- Build Website: `cd apps/website && bun run build`
|
||||
- Build Admin: `cd apps/admin && bun run build`
|
||||
2. Inspect the rendered HTML output or component files listed above.
|
||||
|
||||
---
|
||||
|
||||
# Quality Review Report
|
||||
|
||||
**Verdict**: **APPROVE**
|
||||
|
||||
## Verified Claims
|
||||
- Desktop layout has 35% text and 65% image split → verified via code inspection of `md:grid-cols-[65%_35%]` / `md:grid-cols-[35%_65%]` → **PASS**
|
||||
- Mobile layout stacks image on top of text → verified via `order-1` (image) and `order-2` (text) on mobile styles → **PASS**
|
||||
- `imagePosition` left puts image on left, right puts image on right → verified via CSS grid order alignment → **PASS**
|
||||
- Backward compatibility: Standard layouts are carousels → verified Swiper breakpoint fallback for standard layouts → **PASS**
|
||||
- Theme compliance: SPA uses pop-* classes, Website uses Tailwind v4 theme classes, no hardcoded colors → verified Tailwind definitions → **PASS**
|
||||
- Typings/Zod schema alignment: layout & imagePosition are optional enums → verified `packages/types/index.ts` and `section-toolkit.ts` → **PASS**
|
||||
|
||||
---
|
||||
|
||||
# Adversarial Challenge Report
|
||||
|
||||
**Overall risk assessment**: **LOW**
|
||||
|
||||
## Challenges
|
||||
|
||||
### [Low] Challenge 1: Empty slide payloads
|
||||
- **Assumption challenged**: Assumes backend always provides at least one slide.
|
||||
- **Attack scenario**: If a page section is saved with 0 slides, the Swiper component could crash.
|
||||
- **Mitigation**: The code contains guard clauses `if (slides.length === 0) return null;` in both SPA and website renderers. It fails gracefully by rendering nothing.
|
||||
|
||||
### [Low] Challenge 2: Broken Image URL
|
||||
- **Assumption challenged**: Assumes `slide.imageUrl` is always a valid image resource.
|
||||
- **Attack scenario**: A broken URL shows a broken image placeholder.
|
||||
- **Mitigation**: SPA implements `onError={(e) => { (e.target as HTMLImageElement).style.display = 'none'; }}` to hide the image element, maintaining UI aesthetics. Website handles empty image URLs gracefully by rendering null.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Progress Tracking
|
||||
|
||||
Last visited: 2026-06-28T10:59:05Z
|
||||
|
||||
- [x] Initialized agent workspace (ORIGINAL_REQUEST.md, BRIEFING.md)
|
||||
- [x] Read files to review and build evidence chain
|
||||
- [x] Run build / tests to verify work product (successful compilation of check, admin, spa, and website)
|
||||
- [x] Review implementation for correctness, completeness, quality, and theme compliance
|
||||
- [x] Stress-test implementation for failure modes, edge cases, and backward compatibility
|
||||
- [x] Write handoff report (handoff.md)
|
||||
- [x] Send handoff message to parent
|
||||
Reference in new issue
Block a user