Review: Schedule image digestion: Claude Vision OCR to WorkQueueItems
Verdict: APPROVED
Re-review after refinement. Previous review:
review-1450-2026-06-13 (NEEDS_REFINEMENT, 4 items). Two body fixes confirmed resolved. Two scope items remain but are project-level shared gaps, not blocking for this ticket.Template Completeness
- [x] Type -- Feature
- [x] Lineage -- Standalone, extends Upload tab (#33)
- [x] Repo -- ldraney/landscaping-assistant
- [x] User Story -- crew lead schedule parsing
- [x] Context -- thorough, covers column-overflow, handwritten additions, existing infra, zero-bloat constraint
- [x] File Targets -- create 3, modify 5, explicit do-not-touch list
- [x] Feature Flag -- none, justified (extension of existing upload flow for lead+ roles)
- [x] Acceptance Criteria -- 9 criteria (8 original + error handling AC added per review)
- [x] Test Expectations -- 5 test expectations with run command (added malformed API response test)
- [x] Constraints -- Claude model, API key source, fuzzy matching approach
- [x] Checklist -- standard 3-item
- [x] Related -- references project and parent issue #33
Traceability
- [x] story:schedule-upload label -- present on board item
- [x] story note verified -- found in project-landscaping-assistant user-stories section: "Snap a photo of the paper schedule for later reference"
- [ ] story note OUTDATED -- [SCOPE] The user story summary still says "Snap a photo of the paper schedule for later reference" but this ticket extends the story to include AI-powered parsing into WorkQueueItems. Not blocking for this ticket -- project-level update needed separately.
- [x] arch:rails-app label -- present on board item
- [ ] arch note MISSING -- [SCOPE] No architecture note found for arch-rails-app in pal-e-docs. Shared gap across many board items, not blocking for this ticket.
- [x] Forgejo issue -- https://forgejo.tail5b443a.ts.net/ldraney/landscaping-assistant/issues/204, state: open
File Targets
Files to create:
- [x]
app/services/schedule_digester.rb-- directoryapp/services/does not exist yet (must be created). Standard Rails convention, acceptable. - [x]
app/views/uploads/digest.html.erb-- parent directoryapp/views/uploads/exists, confirmed - [x]
db/migrate/TIMESTAMP_add_week_start_to_uploads.rb-- standard migration, OK
Files to modify:
- [x]
Gemfile-- verified exists. Noanthropicgem present currently. Correct target. - [x]
app/controllers/uploads_controller.rb-- verified exists. Currently has index/show/create/edit/update/destroy. Adding digest and confirm_digest actions is appropriate. - [x]
app/models/upload.rb-- verified exists. Issue now correctly states: "addweek_startdate field (no AR associations to WorkQueueItem; the service creates items directly, the relationship is implicit through week_start date range)". This is clear and matches the architecture -- the service object pattern means Upload does not need has_many associations. Previous [BODY] finding RESOLVED. - [x]
config/routes.rb-- verified exists. Currentlyresources :uploads, only: [:index, :show, :create, :edit, :update, :destroy]. Adding member routes for digest/confirm_digest is correct. - [x]
app/views/uploads/show.html.erb-- verified exists. Adding "Digest Schedule" button is straightforward.
Do-not-touch files:
- [x]
app/models/property.rb-- confirmed exists, no schema changes needed. Property hasvalidates :client_name, presence: trueandhas_many :work_queue_items. - [x]
app/controllers/weeks_controller.rb-- confirmed exists, week view stays unchanged.
Repo Placement
OK -- issue filed on ldraney/landscaping-assistant, all file targets are in this repo. Single-repo change, no cross-repo concerns.
Dependencies
- [x] Issue #33 (Upload tab) -- done column on board. Upload model and controller exist and work.
- [x] WorkQueueItem model -- exists with work_date, property_id (unique per date), position, completed fields.
- [x] Property model -- exists with client_name field for fuzzy matching. Has
has_many :work_queue_items. - [x] Anthropic API key -- confirmed at ~/secrets/anthropic/credentials.env, file present.
- No blocking items found on the board. No items in in_progress that conflict.
Acceptance Criteria
9 acceptance criteria. All are testable by an agent:
- AC1-3: Vision API call, structured JSON response, column-overflow handling -- testable via mocked API response in unit tests
- AC4: Fuzzy matching -- testable with known property fixtures
- AC5: Confirmation screen with color-coded categories -- testable via request spec checking HTML response
- AC6: WorkQueueItem creation on confirm -- testable via request spec with confirm action
- AC7: No new Property records -- testable via assertion on Property.count
- AC8: Duplicate detection (skip, don't error) -- testable via uniqueness constraint (already exists:
validates :property_id, uniqueness: { scope: :work_date }plus DB index) - AC9: Error handling for API unavailability or malformed JSON -- testable via mocked error responses, verify no partial items created. Previous [BODY] finding RESOLVED.
Blast Radius
- WorkQueueItem uniqueness constraint already exists (
index_work_queue_items_on_work_date_and_property_id, unique: true) -- AC8 duplicate detection is enforced at DB level. Service should handle ActiveRecord::RecordNotUnique gracefully. - Upload model gains week_start field -- existing upload tests should still pass.
- No existing fuzzy matching or anthropic patterns in the codebase -- net-new functionality.
- Adding the anthropic gem adds an external API dependency. No other external AI/ML gems exist currently.
Decomposition Assessment
File count: 3 new + 5 modified = 8 files in 1 repo. AC count: 9 acceptance criteria + 5 test expectations. This is substantial but all within one repo and one logical feature. The service object pattern (ScheduleDigester) encapsulates the core complexity. Points: 8 (appropriate for scope). Borderline on the 5-minute rule but tightly coupled -- splitting would create artificial seams. No decomposition needed.
Recommendations
Both previous [BODY] findings have been addressed in the refined issue:
- [BODY] Confusing "has_many :work_queue_items through digest" language -- RESOLVED. Now reads: "no AR associations to WorkQueueItem; the service creates items directly, the relationship is implicit through week_start date range"
- [BODY] Missing error handling AC -- RESOLVED. AC9 added with clear criteria. Matching test expectation added.
Remaining project-level items (not blocking this ticket):
- [SCOPE] Update the schedule-upload user story on project-landscaping-assistant to reflect AI-powered parsing. Current: "Snap a photo of the paper schedule for later reference." Should reflect schedule digestion.
- [SCOPE] Create architecture note arch-rails-app. Shared gap across multiple board items.
No action needed for this ticket to proceed.