--- phase: 21-fix-image-input-deduplication plan: 01 type: execute --- Resolve duplicate image saving across input/generated images by unifying the hashing approach. Purpose: Ensure the deduplication system consistently prevents duplicate files in the generations folder by using the same hashing algorithm everywhere. Output: Consistent MD5 hashing across all image saving operations. ~/.claude/get-shit-done/workflows/execute-phase.md ~/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md # Key source files: @src/app/api/save-generation/route.ts @src/utils/imageStorage.ts # Prior phase with related hashing decision: @.planning/phases/13-fix-duplicate-generations/13-01-SUMMARY.md **Tech stack available:** Next.js 16, Zustand **Established patterns:** MD5 content hashing for deduplication (Phase 13) **Issues being addressed:** 1. ~~nano-banana-pro model generates without considering image inputs~~ - RESOLVED (no longer an issue) 2. Input and generated images have duplicate files despite different hashes - need consistent hashing approach **Root cause:** - imageStorage.ts uses position-based sampling hash while save-generation uses MD5 - these are incompatible - Same image saved via different code paths gets different hashes Task 1: Unify image hashing to MD5 across all save operations src/utils/imageStorage.ts Replace the position-based sampling hash in imageStorage.ts with MD5 content hashing (matching save-generation/route.ts pattern). The current approach at line 209-211 uses a weak hash based on string length and sampled substrings: ``` const hash = `${folder}-${len}-${imageData.substring(50, 100)}-${imageData.substring(mid, mid + 50)}-${imageData.substring(Math.max(0, len - 50))}`; ``` This is problematic because: 1. Different hash method than save-generation API (MD5) 2. Same image can get different hashes if saved via different paths 3. Position-based sampling is weak for dedup (similar images may have same samples) Replace with: 1. Import crypto at top: `import crypto from "crypto";` 2. Create helper: `function computeContentHash(data: string): string { return crypto.createHash("md5").update(data).digest("hex"); }` 3. Replace the hash computation: `const hash = `${folder}-${computeContentHash(imageData)}`;` (folder prefix still needed to separate inputs/generations) WHY: MD5 is already used in save-generation (Phase 13 decision), provides reliable deduplication, and is fast enough for our use case. Build succeeds with `npm run build`. TypeScript types check with no errors. imageStorage.ts uses MD5 hashing, consistent with save-generation API. Same image saved twice gets same hash and is deduplicated. Before declaring phase complete: - [ ] `npm run build` succeeds without errors - [ ] `npm test` passes all existing tests - [ ] No TypeScript errors in modified files - Task completed - All verification checks pass - Deduplication uses consistent MD5 hashing across all image save paths After completion, create `.planning/phases/21-fix-image-input-deduplication/21-01-SUMMARY.md`