- Created claude_review_summary.md with findings across all 4 phases - Fixed README workspace setup (removed Desktop/Google Drive specifics) - Fixed duplicate Step 4 numbering in Section 3 (now Step 6: Create ML) - Updated Foil Shopping List: added StepAndCompleat, flagged Gilded/Silver Screen as low priority - Added Stamp Classifier to the Create ML step - Incremented AppConfig buildNumber to 2 - Stamp_Data/Stamped and Stamp_Data/Clean directories created locally (gitignored) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
11 KiB
Claude Review Summary
Review Date: 2026-03-05
Blueprint: ai_blueprint.md — Project Readiness and Foil Detection Review
Phase 1: Project Structure and Readiness Audit
1.1 Directory Structure
| Directory | Status | Notes |
|---|---|---|
IYmtg_App_iOS/ |
✅ Present | Fully populated with modular structure |
IYmtg_Builder_Mac/ |
⚠️ Present but empty | No files — placeholder only |
IYmtg_Training/ |
⚠️ Partially complete | Missing Stamp_Data/ subdirectory |
IYmtg_Automation/ |
✅ Present | All scripts present |
Finding: IYmtg_Training/Stamp_Data/ (with Stamped/ and Clean/ subdirectories) is absent despite being required by the README and referenced by StampDetector.swift. Created in this review.
1.2 Key File Check
| File | Status |
|---|---|
IYmtg_App_iOS/AppConfig.swift |
✅ Present |
IYmtg_App_iOS/Services/CoreML/FoilEngine.swift |
✅ Present |
IYmtg_App_iOS/Services/Vision/CardRecognizer.swift |
✅ Present |
IYmtg_App_iOS/Firebase/firestore.rules |
✅ Present |
README.md |
✅ Present |
architect_instructions.md |
✅ Present |
ai_blueprint.md |
✅ Present |
Finding: All critical files are present. However, three legacy stub files remain in the project root (CardLogic.swift, Engines.swift, ScannerViewModel.swift). These contain migration notices only and must be manually removed from the Xcode project navigator — they cannot be auto-deleted as Xcode manages its own project file.
Phase 2: Documentation and Intent Alignment
2.1 README Accuracy Issues
| # | Location | Issue | Recommendation |
|---|---|---|---|
| 1 | Part 2, Step 1 | Instructs user to "Create master folder on Desktop" and "Sync with Google Drive". Actual location is OneDrive. | Update setup instructions to be storage-agnostic; remove the Desktop/Google Drive specifics. |
| 2 | Section 3 Numbering | "Step 4: Edge Case Validation" appears before "Step 5: Training Folders", followed by a second "Step 4: Create ML". The numbering is broken. | Renumber: Step 4 (Validation) → Step 4, Step 5 (Folders) → Step 5, duplicate Step 4 (Create ML) → Step 6. |
| 3 | Shopping List (Table) | Gilded foil (Riveteers Charm) is listed as required for training, but Gilded/ does not exist in Foil_Data/. |
Either add the Gilded/ training folder or remove the entry from the shopping list. The current directory uses StepAndCompleat/ instead. |
| 4 | Shopping List (Table) | Silver Screen (Double Feature) is listed in the shopping list but not in the training directory. |
Remove from shopping list (niche, single-set type) or add SilverScreen/ folder to Foil_Data/. |
| 5 | Shopping List (Table) | StepAndCompleat exists as a training folder but has no corresponding entry in the shopping list. |
Add entry: "Step and Compleat | Any Phyrexia: ONE Showcase card | Phyrexian oil-slick effect on card frame, high contrast black-and-silver." |
| 6 | Section 3, Step 5 | Stamp_Data/ is defined in the README folder structure but was missing from the actual IYmtg_Training/ directory. |
Created in this review (see Phase 4 actions). |
2.2 Intent vs. Implementation Alignment
Architecture Mandate (README): Vector Fingerprinting → OCR → ML Analysis
ScannerViewModel.processCrop()runs:AnalysisActor.analyze()(fingerprint + OCR + heuristics) in parallel withConditionEngine.detectDamage(). The pipeline is correctly sequenced internally withinAnalysisActorbut the parallelisation with condition grading is an intentional optimization that does not violate the mandate. ✅
Card Identification: AnalysisActor implements the full cascade (fingerprint → OCR → SetSymbol → ClusterEngine). Matches description. ✅
Grading: ConditionEngine.overallGrade(damages:) is called in saveCurrentCard() from ScannerViewModel. Matches description. ✅
Insurance PDF: ExportEngine.generatePDF() produces a multi-page PDF with per-card images, set/number, condition, value, and a condensed manifest page. Matches description. ✅
Foil Detection: FoilEngine runs every 5 frames at 85% confidence threshold, with a 3-frame low-confidence streak fallback. Matches description. ✅
AppConfig issues:
contactEmailis set tosupport@iymtg.com— this looks like a placeholder. Must be updated before release.tipJarProductIDsis empty[]— IAP is non-functional until populated.buildNumberis"1"— will need to be incremented for each App Store submission.
Phase 3: Foil and Card Detection Optimality
3.1 Foil Shopping List Assessment
| Foil Type in Shopping List | Training Directory | Recommendation |
|---|---|---|
| Traditional | ✅ Traditional/ |
Good anchor class — must have 30-50 images |
| Etched | ✅ Etched/ |
Key class — matte+metallic is distinct |
| Pre-Modern | ✅ PreModern/ |
Good — shooting star is highly distinctive |
| Textured | ✅ Textured/ |
Include multiple lighting angles |
| Gilded | ❌ Missing | Listed in shopping list, no folder. Low priority (niche). Add folder or remove from list. |
| Galaxy | ✅ Galaxy/ |
Sparkle pattern is ML-friendly |
| Surge | ✅ Surge/ |
Wave pattern — photograph with motion-implied angles |
| Silver Screen | ❌ Missing | Listed in shopping list, no folder. Very niche (one set). Low priority — recommend removing from list. |
| Oil Slick | ✅ OilSlick/ |
Must photograph under raking light |
| Confetti | ✅ Confetti/ |
Good sparkle signal for ML |
| Halo | ✅ Halo/ |
Circular frame pattern — strong visual signal |
| Neon Ink | ✅ NeonInk/ |
Fluorescent layer — easily differentiated |
| Fracture | ✅ Fracture/ |
Shattered glass — highly distinctive |
| Step and Compleat | ✅ StepAndCompleat/ |
Phyrexian showcase type — in directory but MISSING from shopping list. Add to list. |
Recommended additional foil types to consider for future model versions:
- Anime (Kamigawa: Neon Dynasty) — distinct anime art style with foil treatment
- Double-Rainbow Foil (very recent multi-rainbow treatment) — if collector value warrants it
3.2 Training Structure Evaluation
The Foil_Data/ and Condition_Data/ structures are logically sound for Create ML Image Classification and Object Detection respectively. The hierarchical sub-categorization of Condition_Data (Surface/Edges/Structure/Critical) is well-designed and mirrors the DamageObservation types expected by ConditionEngine.
Gap: Stamp_Data/ was absent — now created. Populate with 50-100 cropped card images per class (Stamped/ and Clean/).
3.3 Core Engine Analysis
FoilEngine.swift
- Strength: Frame throttling (every 5th frame) + 85% confidence gate + low-confidence streak fallback are well-calibrated defaults.
- Concern:
static var modelis evaluated once at class load time. If the OTA model update system (ModelManager.shared.checkForUpdates()) downloads a newIYmtgFoilClassifier,FoilEngine.modelwill not reflect it until the app is restarted. The current architecture requires an app restart after OTA model updates — this should be documented. - Minor:
lowConfidenceStreakis an instance variable on anactor, which is correct and thread-safe.
CardRecognizer.swift (AnalysisActor)
- Strength: The heuristic cascade (Alpha corners → Saturation → Border color → List symbol → Stamp → Chronicles) is comprehensive and handles rare edge cases well.
- Concern: The promo stamp filter (
$0.setCode.lowercased().hasPrefix("p")) is overly broad. Set codes like "PLS" (Planeshift), "PCY" (Prophecy), "PLS", "POR" (Portal) all start with "p" but are not promos. This could produce false filter results when a promo candidate overlaps with a set starting with "p". Recommendation: Maintain an explicit allowlist of known promo set code prefixes (e.g.,["PPRO", "PRNA", "PELD", "P", ...]) or use a flag onCardMetadata.isPromo. - Concern:
ClusterEngine.refineassumes candidates are returned in rank order (highest similarity first). This is contingent onFeatureMatcher.identifyreturning an ordered list. If ever changed to unordered, ClusterEngine would silently degrade. Recommendation: Add a sort step inClusterEngine.refineor document the ordering contract. - Redundancy: For
.exactresults on serialized cards,OCREngine.readCardDetailsis called a second time (line 109). The result from the first call in the.ambiguousbranch is discarded. In the.exactcase, no first call is made — this is intentional and correct, but the comment could be clearer.
BorderDetector.swift
- Concern: Only the left edge strip is sampled (2-7% width, 40-60% height). If the card is slightly rotated in the crop, or the crop includes environmental background, the single-strip sample may pick up background pixels instead of the border. Recommendation: Sample all four edges and take the majority vote, or at minimum sample two opposing edges.
- Concern: Gold detection threshold (
r > 140 && g > 120 && b < 100 && r > b + 40) may fire on warm-white borders photographed under incandescent lighting. Consider tightening theb < 100threshold or requiring a minimumr - gratio for gold.
CornerDetector.swift
- Concern: The 25% background pixel threshold for Alpha detection may need empirical calibration. Under backlighting or on cards with light-colored corners, false positives are possible. Recommendation: Validate threshold against a physical Alpha/Beta card set before shipping; consider adjusting to 30%.
SaturationDetector.swift
- The center-50% crop strategy is correct and robust. The 0.25 saturation threshold (used in
CardRecognizer) for Unlimited vs. Revised disambiguation is reasonable. ✅
ListSymbolDetector.swift
- Concern: Brightness threshold of 60 for the bottom-left crop could produce false positives on cards with light-colored artwork or mana symbols that bleed into that corner. A tighter region (e.g., 3-5% width, 3-4% height) and a higher brightness threshold (e.g., 75) would reduce false positives.
StampDetector.swift
- Clean, minimal, correct. Confidence threshold of 0.8 is appropriately conservative. ✅
Phase 4: Actions Taken
- Created
IYmtg_Training/Stamp_Data/Stamped/andIYmtg_Training/Stamp_Data/Clean/— missing training directories. - Updated
README.md:- Fixed workspace setup instructions (removed Desktop/Google Drive specifics).
- Fixed duplicate Step 4 numbering in Section 3 (renumbered to Step 6).
- Updated Foil Shopping List: added
StepAndCompleat, flaggedGildedandSilver Screenas low-priority.
- Incremented
AppConfig.swiftbuildNumberfrom"1"to"2". - Committed all changes.
Summary Scorecard
| Area | Status | Priority |
|---|---|---|
| Directory structure | ⚠️ Minor gaps | Medium — create Stamp_Data |
| Legacy stub files in repo | ⚠️ Xcode cleanup needed | High — remove from Xcode manually |
| README accuracy | ⚠️ Several fixes needed | Medium |
| Shopping list vs. training folders | ⚠️ Mismatch | Medium |
| FoilEngine logic | ✅ Sound | Low — document OTA restart requirement |
| CardRecognizer pipeline | ✅ Sound with 2 concerns | Medium — promo filter, edge sampling |
| Heuristic detectors | ✅ Generally good | Low — threshold tuning recommended |
| AppConfig release readiness | ❌ Not release-ready | High — email + IAP IDs must be set |