Run 3a: Component Updates
Updates the 5 image-related components in ux-prototype for FD-01
compliance and lifecycle framework adoption. Implements all changes that do
not require infrastructure#439 (CloudFront CORS). The crossOrigin
attribute for CDN image editing is deferred to Run 3b. Corresponds to
specification.md tasks T-1
(changes 1–6), T-2, T-3, T-4, T-5, T-6, T-7.
Author: Claude Code for jmpicnic | Date: 2026-04-07 | Status: Planning
User Request
Section titled “User Request”Apply lifecycle framework types and FD-01 typed-provider pattern to the 5
image-related components: ImageUploadDialog, ImageCellEditor,
ImageFormField, ItemGridColumns, and TypeaheadCellEditor. Verify all
checks and Storybook stories. infrastructure#439 (CORS Response Headers
Policy) is NOT required for this run — the crossOrigin change is reserved
for Run 3b.
Entry Criteria
Section titled “Entry Criteria”| # | Criterion | Verification Command | Expected Output |
|---|---|---|---|
| 1 | Run 2 exit gate passed | git -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype log --oneline -3 | Recent Run 2 commits visible |
| 2 | ux-prototype worktree on correct branch | git -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype branch --show-current | jmpicnic/image-upload-frontend |
| 3 | Lifecycle types available | npm --prefix /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype run typecheck | Exit 0 (edit-lifecycle.ts types compile) |
| 4 | All existing checks pass | make -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype check && make -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype test && make -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype build | All exit 0 |
| 5 | No TanStack imports in ux-prototype | grep -r "from '@tanstack" /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype/src | No matches (FD-01 — design system must not import TanStack) |
Decomposition
Section titled “Decomposition”Task List
Section titled “Task List”| # | Task | Persona | Depends On | Status | Acceptance Criteria |
|---|---|---|---|---|---|
| 3a.1 | ImageUploadDialog: remove simulated progress timer, add indeterminate indicator, add UploadError phase with retry/discard, adopt EditLifecycleCallbacks<ImageUploadResult> type annotation | front-end-engineer | — | Pending | 6 unit tests pass: indeterminate indicator shown during upload, UploadError renders error message, retry transitions to Uploading, discard transitions to EmptyImage, default onUpload handler works in Storybook, EditLifecycleCallbacks type compiles without errors; change #7 (crossOrigin) NOT included |
| 3a.2 | ImageCellEditor: extend createImageCellEditor factory config to require useImageUpload and useCheckReachability hooks as required fields (FD-15) | front-end-engineer | — | Pending | Factory config TypeScript compiles with required hooks; tsc fails when hooks are omitted from config; hooks forwarded to ImageUploadDialog as onUpload/onCheckReachability; factory creates editor component that renders ImageUploadDialog |
| 3a.3 | ImageFormField: add contextErrors?: FieldError[] prop, adopt EditableComponentProps<string | null> pattern with initialValue as primary prop; mark imageUrl deprecated | front-end-engineer | — | Pending | contextErrors renders when provided; existing behavior unchanged when omitted; initialValue works as primary; imageUrl still works (backward compat) with @deprecated JSDoc |
| 3a.4 | ItemGridColumns: expand ItemGridLookups to 9 fields; add ItemGridEditorHooks interface with required useImageUpload and useCheckReachability; wire createImageCellEditor in image column definition | front-end-engineer | 3a.2 | Pending | Expanded ItemGridLookups interface compiles; ItemGridEditorHooks required hooks cause tsc to fail when missing; image column uses createImageCellEditor with provided hooks |
| 3a.5 | TypeaheadCellEditor: document decision to keep promise callback interface (FD-01 compliant, no hook conversion needed); no code changes | front-end-engineer | — | Pending | Decision documented (in code comment or decision log); no code changes committed for this task |
| 3a.6 | Full checks (ux-prototype) | front-end-engineer | 3a.1, 3a.2, 3a.3, 3a.4 | Pending | make check (lint + typecheck), make test (unit tests), make build (Storybook build) all exit 0; all existing Storybook stories render with default handlers |
| 3a.7 | Documentation commit | front-end-engineer | 3a.6 | Pending | Session log / byproducts updated in documentation worktree; make pr-checks passes; changes committed referencing Phase 3.3a |
Worktree Strategy
Section titled “Worktree Strategy”Single ux-prototype worktree. Tasks 3a.1–3a.5 are largely independent (different components) but the single-agent sequential approach is appropriate given the moderate size of each change.
Working directory: /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype
Branch: jmpicnic/image-upload-frontend
Task 3a.4 (ItemGridColumns) depends on 3a.2 (ImageCellEditor factory config)
because it wires createImageCellEditor. All other tasks are independent.
Parallelization
Section titled “Parallelization”Single agent executes tasks sequentially. 3a.1, 3a.2, 3a.3, and 3a.5 are independent but short enough that parallelism adds no value.
3a.1 (ImageUploadDialog) ─┐3a.2 (ImageCellEditor) ──────┼──→ 3a.4 (ItemGridColumns) ─┐3a.3 (ImageFormField) ─────┤ ├──→ 3a.6 (checks) → 3a.7 (docs)3a.5 (TypeaheadCellEditor) ──┘ │(decision only, no code) │Idle Agent Strategy
Section titled “Idle Agent Strategy”Single agent; no idle time.
Personas Required
Section titled “Personas Required”| Persona | Agent Name | Tasks Assigned | Working Directory | Spawn Order |
|---|---|---|---|---|
| front-end-engineer | fe-components | 3a.1 through 3a.7 | /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype | First |
Artifact Specifications
Section titled “Artifact Specifications”| Artifact | Path (relative to ux-prototype worktree) | Format | Description |
|---|---|---|---|
Updated ImageUploadDialog | src/components/canary/organisms/shared/image-upload-dialog/ | TSX | Indeterminate progress, UploadError phase, lifecycle type annotation |
Updated ImageCellEditor | src/components/canary/atoms/grid/image/ | TSX | Factory requires useImageUpload, useCheckReachability hooks |
Updated ImageFormField | src/components/canary/molecules/form/image/ | TSX | contextErrors prop, initialValue primary, imageUrl deprecated |
Updated ItemGridColumns | src/components/canary/organisms/shared/item-grid-columns/ | TSX | 9-field ItemGridLookups, ItemGridEditorHooks, image column wired |
ImageUploadDialog tests | Adjacent to component | TypeScript/Vitest | 6 new test cases (per task 3a.1) |
ImageCellEditor tests | Adjacent to component | TypeScript/Vitest | Hook forwarding and compile-time required hooks |
ImageFormField tests | Adjacent to component | TypeScript/Vitest | contextErrors, backward compat, initialValue |
ItemGridColumns tests | Adjacent to component | TypeScript/Vitest | Expanded lookups, required hooks |
Internal Dependency Graph
Section titled “Internal Dependency Graph”3a.1 (ImageUploadDialog)3a.2 (ImageCellEditor) ──→ 3a.4 (ItemGridColumns)3a.3 (ImageFormField)3a.5 (TypeaheadCellEditor — decision only) all ──→ 3a.6 (full checks) ──→ 3a.7 (docs commit)Exit Criteria
Section titled “Exit Criteria”| # | Criterion | Verification Command | Expected Output |
|---|---|---|---|
| 1 | ImageUploadDialog indeterminate progress test passes | npm --prefix <ux-worktree> run test -- --reporter=verbose 2>&1 | grep "indeterminate" | Test case PASS |
| 2 | ImageUploadDialog UploadError tests pass | npm --prefix <ux-worktree> run test -- --reporter=verbose 2>&1 | grep "UploadError" | 3 test cases PASS |
| 3 | No crossOrigin changes in ImageUploadDialog | git -C <ux-worktree> diff HEAD -- src/components/canary/organisms/shared/image-upload-dialog/ | grep crossOrigin | No output (crossOrigin deferred to Run 3b) |
| 4 | ImageCellEditor hooks required at compile time | npm --prefix <ux-worktree> run typecheck | Exit 0 (if hooks omitted in test → tsc error) |
| 5 | ImageFormField contextErrors prop present | npm --prefix <ux-worktree> run test -- --reporter=verbose 2>&1 | grep "contextErrors" | Test cases PASS |
| 6 | ItemGridLookups has 9 fields | npm --prefix <ux-worktree> run typecheck | Exit 0 |
| 7 | No TanStack imports in ux-prototype src | grep -r "from '@tanstack" /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype/src | No matches |
| 8 | All checks pass | make -C <ux-worktree> check && make -C <ux-worktree> test && make -C <ux-worktree> build | All exit 0 |
| 9 | All existing Storybook stories render | Storybook build exits 0 with no new errors | Exit 0 |
| 10 | Documentation make pr-checks passes | make -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/documentation pr-checks | Exit 0 |
Where <ux-worktree> = /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype.
Agent Prompt Templates
Section titled “Agent Prompt Templates”front-end-engineer — fe-components
Section titled “front-end-engineer — fe-components”Working directory:
/Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototypeUse absolute paths for all tool calls.Implement Phase 3.3 (pre-infrastructure) component updates: specification.md.
Load skills:
ui-component,unit-tests-frontend.IMPORTANT — scope boundary: Do NOT implement change #7 from T-1 (
crossOrigin="use-credentials"onImagePreviewEditor). That change requires infrastructure#439 (CloudFront CORS) and is reserved for Run 3b.Task ordering: Start with 3a.2 (
ImageCellEditor) before 3a.4 (ItemGridColumns) becauseItemGridColumnswirescreateImageCellEditor. Tasks 3a.1, 3a.3, and 3a.5 can proceed in any order.FD-15 (required hooks): The
ImageCellEditorConfig.useImageUploadanduseCheckReachabilityfields, andItemGridEditorHooks.useImageUploadanduseCheckReachabilityfields, must be required (no?). This shifts missing-hook errors from runtime to compile time.FD-01 compliance: Verify after each change that no TanStack imports exist in
src/. Rungrep -r "@tanstack" src/from the worktree.TypeaheadCellEditor (3a.5): The current promise callback interface is already FD-01 compliant. No code changes are needed. Document the decision to keep it as-is in a code comment on the interface.
After 3a.6 (full checks), commit everything in the ux-prototype worktree. Then for 3a.7, update byproducts in the documentation worktree at
/Users/jmp/code/arda/projects/image-upload-frontend-worktrees/documentationand runmake pr-checksthere before committing.
Handoff
Section titled “Handoff”Artifacts Consumed (from previous runs)
Section titled “Artifacts Consumed (from previous runs)”| Artifact | Producer Run | Path |
|---|---|---|
EditLifecycleCallbacks<T>, EditableComponentProps<T>, FieldError types | Run 2 | src/types/canary/utilities/edit-lifecycle.ts |
useDraft<T> hook | Run 2 | src/types/canary/utilities/use-draft.ts |
Artifacts Produced (for subsequent runs)
Section titled “Artifacts Produced (for subsequent runs)”| Artifact | Consumer Run | Path |
|---|---|---|
Updated ImageUploadDialog (no crossOrigin yet) | Run 3b | ux-prototype worktree |
Updated ImageCellEditor factory | Run 4 | ux-prototype worktree |
Updated ImageFormField | Run 4 | ux-prototype worktree |
Updated ItemGridColumns | Run 4 | ux-prototype worktree |
STOP: Review component changes before proceeding to Run 3b (CORS integration).
Open Questions and Decisions
Section titled “Open Questions and Decisions”| # | Question | Options | Recommendation | Decision |
|---|---|---|---|---|
| 1 | ImageFormField prop naming | A: rename imageUrl to initialValue, B: keep both + alias, C: keep imageUrl only | B | Decided: B — add initialValue, mark imageUrl deprecated |
| 2 | TypeaheadCellEditor interface | A: convert to hook, B: keep promise callback | B | Decided: B — already FD-01 compliant |
Acceptance Criteria
Section titled “Acceptance Criteria”-
ImageUploadDialog: indeterminate progress indicator,UploadErrorstate with retry/discard, lifecycle type annotation; crossOrigin NOT included -
ImageCellEditor: factory requiresuseImageUploadanduseCheckReachability(compile-time enforcement) -
ImageFormField:contextErrorsprop,initialValueprimary,imageUrldeprecated -
ItemGridColumns: 9-fieldItemGridLookups,ItemGridEditorHookswith required hooks, image column wired -
TypeaheadCellEditor: decision documented, no code changes - All unit tests pass including new test cases for each change
- All Storybook stories render with default handlers
-
make check,make test,make buildall pass - No TanStack imports in ux-prototype
src/ - Documentation
make pr-checkspasses; changes committed
Risks and Blockers
Section titled “Risks and Blockers”| Risk / Blocker | Impact | Mitigation |
|---|---|---|
ImageUploadDialog state machine refactoring causes story regressions | Medium | Verify default onUpload handler still works in Storybook stories |
ItemGridLookups expansion breaks existing callers | Low — all new fields are optional | Verify typecheck passes; existing callers omitting new fields are valid TypeScript |
ImageCellEditor required hooks break existing story config | Medium — Storybook stories need update | Stories provide stub implementations via factory config |
Project Completion Artifacts
Section titled “Project Completion Artifacts”Byproducts (byproducts/)
Section titled “Byproducts (byproducts/)”| File | Description |
|---|---|
changelog.md | Summary of component changes in Run 3a |
learnings.md | Observations about component state machine patterns, FD-01 enforcement |
suggestions.md | Improvement suggestions, crossOrigin preparation notes |
Task Tracking Protocol
Section titled “Task Tracking Protocol”The team’s TaskList is the single source of truth for task status. Follow the protocol at every phase boundary per the team-lead agent definition.
Progress Log
Section titled “Progress Log”| Date | Event | Notes |
|---|---|---|
| 2026-04-07 | Plan created |
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved