diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 57dc46f..c87456b 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -67,7 +67,7 @@ Plans: Plans: - [x] 03-01-PLAN.md — SwipeService CRUD backend + Pydantic schemas + FastAPI router + pagina SwipeFile UI con form aggiunta, modifica inline, eliminazione con conferma, filtro nicchia (Wave 1) -- [ ] 03-02-PLAN.md — Swipe-to-calendar integration: topic_overrides in CalendarRequest + picker Swipe File nel form Genera Calendario con mark-used (Wave 2) +- [x] 03-02-PLAN.md — Swipe-to-calendar integration: topic_overrides in CalendarRequest + picker Swipe File nel form Genera Calendario con mark-used (Wave 2) --- @@ -95,5 +95,5 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 |-------|----------------|--------|-----------| | 1. Core Generation Pipeline | 4/4 | Complete | 2026-03-08 | | 2. Prompt Control + Output Review | 2/2 | Complete | 2026-03-08 | -| 3. Organization Layer | 1/2 | In progress | - | +| 3. Organization Layer | 2/2 | Complete | 2026-03-09 | | 4. Enrichment | 0/1 | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index fe64999..c7d833c 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -5,23 +5,23 @@ See: .planning/PROJECT.md (updated 2026-03-07) **Core value:** Generare un calendario di 13 caroselli Instagram strategicamente orchestrati, pronti per Canva Bulk Create, con un click dalla Web UI. -**Current focus:** Phase 3 — Organization Layer (Plan 1/2 completato) +**Current focus:** Phase 3 COMPLETA — pronto per vps-lab-deploy e Phase 4 ## Current Position -Phase: 3 of 4 (Organization Layer) -Plan: 1 of 2 in current phase — In progress -Status: In progress — Plan 03-01 completo, manca 03-02 -Last activity: 2026-03-09 — Completed 03-01-PLAN.md (SwipeService + pagina SwipeFile) +Phase: 3 of 4 (Organization Layer) — COMPLETA +Plan: 2 of 2 in current phase — Completato +Status: Phase 3 completa — pronto per deploy e Phase 4 +Last activity: 2026-03-09 — Completed 03-02-PLAN.md (Swipe-to-Calendar integration) -Progress: [███████░░░] 77% (7/9 piani totali) +Progress: [████████░░] 89% (8/9 piani totali) ## Performance Metrics **Velocity:** -- Total plans completed: 7 -- Average duration: ~6.5 min -- Total execution time: 47 min +- Total plans completed: 8 +- Average duration: ~6 min +- Total execution time: 50 min **By Phase:** @@ -29,11 +29,11 @@ Progress: [███████░░░] 77% (7/9 piani totali) |-------|-------|-------|----------| | 01-core-generation-pipeline | 4/4 COMPLETA | 33 min | 8 min | | 02-prompt-control-output-review | 2/2 COMPLETA | 9 min | 4.5 min | -| 03-organization-layer | 1/2 In corso | 5 min | 5 min | +| 03-organization-layer | 2/2 COMPLETA | 8 min | 4 min | **Recent Trend:** -- Last 5 plans: 8 min, 10 min, 5 min, 4 min, 5 min -- Trend: stabile intorno a 5 min +- Last 5 plans: 5 min, 4 min, 5 min, 3 min, 3 min +- Trend: stabile intorno a 3-4 min *Updated after each plan completion* @@ -67,22 +67,25 @@ Recent decisions affecting current work: - [03-01]: IDs brevi uuid4.hex[:12] — leggibili, no rischio collisione con volumi Swipe File - [03-01]: PUT con comportamento PATCH-like per nicchia/note — None cancella il valore - [03-01]: Filtro nicchia derivato dinamicamente da items (no config separata) +- [03-02]: topic_overrides come dict[int, str] — chiave = slot_index, Pydantic converte str key → int +- [03-02]: Override check prima di slot.topic e prima di LLM nel _run_generation +- [03-02]: mark-used fire-and-forget (mutate senza await) per non bloccare la UI +- [03-02]: Picker inline con absolute positioning z-20, toggle click stesso slot chiude ### Blockers/Concerns - [Phase 1]: Validare token usage reale per batch 13 post con claude-sonnet-4-5 — inter_request_delay=2.0s configurato, da validare in produzione - [Phase 1]: Baseline qualita' prompt italiani da validare dopo prima generazione reale -- [Deploy]: Phase 2+3 plan1 complete — serve vps-lab-deploy per testare end-to-end il sistema -- [03-02]: La route `/swipe-file` e il hook `useSwipeItems` sono pronti per l'integrazione nel form Genera Calendario +- [Deploy]: Phase 3 completa — eseguire vps-lab-deploy per testare end-to-end il sistema completo ## Session Continuity Last session: 2026-03-09 -Stopped at: Completed 03-01-PLAN.md (SwipeService + SwipeFile UI) — Plan 1/2 Phase 3 +Stopped at: Completed 03-02-PLAN.md (Swipe-to-Calendar integration) — Plan 2/2 Phase 3 Resume file: None ## Next Actions -1. Eseguire 03-02-PLAN.md (Swipe-to-calendar integration: topic_overrides + picker Swipe File) -2. `vps-lab-deploy` per deployare su VPS e testare end-to-end il sistema -3. Pianificare Phase 4 (Enrichment: Unsplash integration) +1. `vps-lab-deploy` per deployare su VPS e testare end-to-end il sistema completo +2. Pianificare Phase 4 (Enrichment: Unsplash integration) +3. Test reale della generazione bulk con topic_overrides dallo Swipe File diff --git a/.planning/phases/03-organization-layer/03-02-SUMMARY.md b/.planning/phases/03-organization-layer/03-02-SUMMARY.md new file mode 100644 index 0000000..2a096dd --- /dev/null +++ b/.planning/phases/03-organization-layer/03-02-SUMMARY.md @@ -0,0 +1,120 @@ +--- +phase: 03-organization-layer +plan: "02" +subsystem: ui +tags: [react, fastapi, pydantic, tanstack-query, typescript, swipe-file, topic-overrides] + +# Dependency graph +requires: + - phase: 03-01 + provides: SwipeService CRUD + pagina SwipeFile con hook useSwipeItems pronti + +provides: + - topic_overrides in CalendarRequest (backend Pydantic schema) + - GenerationPipeline applica topic override prima della chiamata LLM + - useMarkSwipeUsed hook in hooks.ts + - Griglia 13 slot con picker inline Swipe File nel form Genera Calendario + - CalendarRequest.topic_overrides in types.ts + +affects: + - 04-enrichment + - vps-lab-deploy + +# Tech tracking +tech-stack: + added: [] + patterns: + - "topic_overrides dict[int, str]: slot_index -> topic passato end-to-end frontend -> backend -> pipeline" + - "Picker inline posizionato con absolute + z-20 sotto ogni slot card" + - "fire-and-forget mutation per mark-used (non blocca UI)" + +key-files: + created: [] + modified: + - backend/schemas/calendar.py + - backend/services/generation_pipeline.py + - frontend/src/types.ts + - frontend/src/api/hooks.ts + - frontend/src/pages/GenerateCalendar.tsx + +key-decisions: + - "topic_overrides come dict[int, str]: chiave = slot_index (0-12), valore = topic string" + - "Override controllato nel _run_generation PRIMA del check slot.topic e PRIMA della chiamata LLM" + - "mark-used chiamato fire-and-forget (mutate senza await) per non bloccare la UI" + - "Picker inline con absolute positioning: si apre sotto il bottone dello slot, chiuso cliccando X o selezionando" + - "showSwipePicker toggle: click sullo stesso slot chiude il picker (prev === slotIndex ? null : slotIndex)" + +patterns-established: + - "Override pattern: dizionario slot_index -> valore, controllato prima della generazione automatica" + - "Picker inline con z-20: visibile sopra altri elementi del form, no modal overlay" + +# Metrics +duration: 3min +completed: 2026-03-09 +--- + +# Phase 3 Plan 02: Swipe-to-Calendar Integration Summary + +**topic_overrides in CalendarRequest + picker Swipe File inline per 13 slot nel form Genera Calendario con mark-used automatico** + +## Performance + +- **Duration:** ~3 min +- **Started:** 2026-03-08T23:30:30Z +- **Completed:** 2026-03-08T23:33:16Z +- **Tasks:** 2 +- **Files modified:** 5 + +## Accomplishments + +1. **Backend schema** — `topic_overrides: Optional[dict[int, str]]` aggiunto a `CalendarRequest` in Pydantic; campo passa validazione e arriva alla pipeline +2. **Pipeline wiring** — `GenerationPipeline._run_generation` controlla override per slot_index prima di chiamare LLM; log informativo quando applicato; slot senza override non modificati +3. **Frontend types + hook** — `CalendarRequest.topic_overrides` in types.ts; hook `useMarkSwipeUsed` aggiunto in hooks.ts (POST /swipe/{id}/mark-used con invalidateQueries) +4. **UI griglia 13 slot** — Form Genera Calendario con sezione "Topic Override" opzionale: griglia 3 colonne su desktop, 1 su mobile; ogni slot mostra bottone "Da Swipe File" o topic assegnato con X per rimuovere +5. **Picker inline** — Apre lista SwipeItems con nicchia badge e badge Usato; selezione assegna topic + chiama mark-used; slot con override ha bordo amber-500/30 + +## Task Commits + +Ogni task committato atomicamente: + +1. **Task 1: Backend — topic_overrides in CalendarRequest + pipeline wiring** - `67769dd` (feat) +2. **Task 2: Frontend — Picker Swipe File nel form Genera Calendario + mark used** - `f449d94` (feat) + +**Plan metadata:** (vedi commit docs sotto) + +## Files Created/Modified + +- `backend/schemas/calendar.py` - Aggiunto campo `topic_overrides: Optional[dict[int, str]]` +- `backend/services/generation_pipeline.py` - Override applicato nel `_run_generation` prima della chiamata LLM +- `frontend/src/types.ts` - `CalendarRequest.topic_overrides?: Record | null` +- `frontend/src/api/hooks.ts` - Hook `useMarkSwipeUsed` aggiunto nella sezione Swipe File +- `frontend/src/pages/GenerateCalendar.tsx` - Sezione Topic Override con griglia slot e picker inline + +## Decisions Made + +- **dict[int, str] per topic_overrides**: chiave numerica = indice slot (0-12), piu' diretto di lista; JSON serializza come `{"0": "topic"}` ma Pydantic converte automaticamente string key → int +- **Override check prima di slot.topic e prima di LLM**: ordine di priorita' — override utente > topic gia' presente > generazione LLM +- **fire-and-forget per mark-used**: `markUsed.mutate(item.id)` senza await per non bloccare la UI; il cache invalidation avviene in background +- **Picker inline con absolute positioning**: evita modal overlay pesante; z-20 garantisce visibilita'; si chiude automaticamente dopo selezione o cliccando X + +## Deviations from Plan + +None — piano eseguito esattamente come scritto. + +## Issues Encountered + +None. + +## User Setup Required + +None — nessuna configurazione esterna richiesta. + +## Next Phase Readiness + +- Phase 3 (Organization Layer) completa: SwipeService CRUD + pagina SwipeFile + integrazione nel form Genera Calendario +- Pronto per `vps-lab-deploy` per deployare end-to-end su VPS e testare il flusso completo +- Phase 4 (Enrichment — Unsplash) puo' iniziare indipendentemente + +--- +*Phase: 03-organization-layer* +*Completed: 2026-03-09*