docs(01-02): complete servizi dominio plan

Tasks completed: 2/2
- Task 1: Costanti dominio, Pydantic schemas, FormatSelector
- Task 2: CalendarService, PromptService, 7 prompt .txt in italiano

SUMMARY: .planning/phases/01-core-generation-pipeline/01-02-SUMMARY.md
This commit is contained in:
Michele
2026-03-08 02:02:35 +01:00
parent ef9b9471fc
commit f9c452586f
2 changed files with 175 additions and 12 deletions

View File

@@ -0,0 +1,159 @@
---
phase: 01-core-generation-pipeline
plan: 02
subsystem: domain-logic
tags: [python, pydantic, calendar, prompts, constants, domain-model]
# Dependency graph
requires:
- phase: 01-core-generation-pipeline (plan 01)
provides: backend/config.py con PROMPTS_PATH, struttura directory base
provides:
- CalendarService con generate_calendar() — 13 slot PN+Schwartz+fasi+nicchie+date
- FormatSelector con select_format() — matrice 30 combinazioni tipo x livello
- PromptService con load/list/compile — gestione prompt .txt con variabili
- CANVA_FIELDS locked (33 colonne) — schema CSV Canva definitivo
- 7 prompt .txt in italiano — system_prompt + topic_generator + 5 formati narrativi
- Pydantic schemas — CalendarSlot, GeneratedPost, TopicResult, PostResult
affects:
- 01-03 (LLMService userà PromptService e CalendarService)
- 01-04 (CSVBuilder userà CANVA_FIELDS e GeneratedPost schema)
# Tech tracking
tech-stack:
added: []
patterns:
- "Costanti LOCKED con assert a load-time per prevenire drift accidentale"
- "Pydantic Field con constraints espliciti (max_length, ge, min_length)"
- "Distribuzione PN/Schwartz verificata a doppio controllo: constants + calendar_service"
- "Prompt template con {{variabile}} doppia graffa (distingue da f-string e Jinja)"
key-files:
created:
- backend/constants.py
- backend/schemas/__init__.py
- backend/schemas/calendar.py
- backend/schemas/generate.py
- backend/services/__init__.py
- backend/services/format_selector.py
- backend/services/calendar_service.py
- backend/services/prompt_service.py
- backend/data/format_mapping.json
- backend/data/prompts/system_prompt.txt
- backend/data/prompts/topic_generator.txt
- backend/data/prompts/pas_valore.txt
- backend/data/prompts/listicle_valore.txt
- backend/data/prompts/bab_storytelling.txt
- backend/data/prompts/aida_promozione.txt
- backend/data/prompts/dato_news.txt
modified:
- .gitignore (fix: backend/data/ non più ignorato interamente)
key-decisions:
- "CANVA_FIELDS usa _image_keyword (non _image_url): keyword testuali ora, URL Unsplash in Phase 4"
- "Distribuzione L3: 4 slot totali — 2 da valore (Cattura) + 2 da riprova_sociale (Coinvolgi)"
- "Nicchie: 50% generico (slot pari), 50% verticali in rotazione (slot dispari)"
- "PromptService ValueError per variabili mancanti: fail esplicito, non silenzioso"
patterns-established:
- "Servizi puri: zero dipendenze HTTP, zero I/O async — testabili con pytest sincrono"
- "FormatSelector iniettabile in CalendarService (dependency injection per test)"
- "Prompt .txt scritti in italiano nativo — non tradotti da inglese"
# Metrics
duration: 9min
completed: 2026-03-08
---
# Phase 1 Plan 02: Servizi core di dominio — CalendarService, FormatSelector, PromptService, 7 prompt italiani
**CalendarService genera 13 slot PN+Schwartz con distribuzione locked, FormatSelector mappa 30 combinazioni tipo x livello, PromptService compila 7 prompt .txt scritti in italiano con sostituzione variabili {{...}}**
## Performance
- **Duration:** 9 min
- **Started:** 2026-03-08T00:51:34Z
- **Completed:** 2026-03-08T01:00:34Z
- **Tasks:** 2
- **Files modified:** 16
## Accomplishments
- CalendarService produce esattamente 13 slot con distribuzione PN corretta (4v+2s+2n+3r+1c+1p) e Schwartz corretta (L5=3,L4=3,L3=4,L2=2,L1=1), ordinati per fase funnel, con rotazione nicchie e calcolo date
- CANVA_FIELDS locked come costante con assert a load-time — 33 colonne definitive per CSV Canva Bulk Create
- FormatSelector mappa tutte le 30 combinazioni (6 tipi x 5 livelli) da format_mapping.json con fallback "PAS"
- PromptService carica/compila/lista prompt .txt con sostituzione {{variabile}} e ValueError esplicito per variabili mancanti
- 7 prompt .txt scritti interamente in italiano: system_prompt, topic_generator, pas_valore, listicle_valore, bab_storytelling, aida_promozione, dato_news — tutti con schema output JSON esplicito
- Pydantic schemas completi: CalendarSlot, CalendarRequest, CalendarResponse, SlideContent, GeneratedPost, TopicResult, GenerateRequest, PostResult, GenerateResponse
## Task Commits
Ogni task è stato committato atomicamente:
1. **Task 1: Costanti, schemas, FormatSelector** - `209d896` (feat)
2. **Task 2: CalendarService, PromptService, prompt .txt** - `ef9b947` (feat)
**Plan metadata:** (questo commit) (docs: complete plan)
## Files Created/Modified
- `backend/constants.py` — CANVA_FIELDS (33), PERSUASION_DISTRIBUTION, SCHWARTZ_DISTRIBUTION, FORMATI_NARRATIVI, FUNZIONI_CONTENUTO, FASI_CAMPAGNA, NICCHIE_DEFAULT, POST_PER_CICLO
- `backend/schemas/calendar.py` — CalendarSlot, CalendarRequest, CalendarResponse con field constraints
- `backend/schemas/generate.py` — SlideContent, GeneratedPost, TopicResult, GenerateRequest, PostResult, GenerateResponse
- `backend/data/format_mapping.json` — matrice 6 tipi x 5 livelli -> formato narrativo
- `backend/services/format_selector.py` — FormatSelector: carica JSON, select_format con fallback, get_mapping
- `backend/services/calendar_service.py` — CalendarService: generate_calendar, ordinamento funnel, rotazione nicchie, calcolo date
- `backend/services/prompt_service.py` — PromptService: list_prompts, load_prompt, compile_prompt, save_prompt, get_required_variables
- `backend/data/prompts/system_prompt.txt` — esperto content marketing B2B italiano, regole tono, struttura 8 slide
- `backend/data/prompts/topic_generator.txt` — genera topic per slot con guida livelli L1-L5
- `backend/data/prompts/pas_valore.txt` — formato PAS per post valore, schema JSON GeneratedPost
- `backend/data/prompts/listicle_valore.txt` — formato Listicle con 6 punti numerati
- `backend/data/prompts/bab_storytelling.txt` — formato BAB: Before→After→Bridge narrativo
- `backend/data/prompts/aida_promozione.txt` — formato AIDA per conversione, variabile call_to_action
- `backend/data/prompts/dato_news.txt` — Dato+Implicazione per news di settore
- `.gitignore` — fix: backend/data/ ignorato troppo aggressivamente (Regola 1 - Bug)
## Decisions Made
- **CANVA_FIELDS usa _image_keyword**: Le colonne immagine contengono keyword testuali, non URL. L'integrazione Unsplash arriva in Phase 4. Mantiene il CSV utile anche senza API Unsplash.
- **Distribuzione L3 split tra fasi**: I 4 slot L3 sono divisi tra "Cattura" (valore) e "Coinvolgi" (riprova_sociale). La logica è che chi conosce la soluzione (L3) ma non ancora il prodotto va nutrito sia con educazione che con prova sociale.
- **Nicchie 50/50**: Slot pari = generico, slot dispari = verticale in rotazione. Garantisce copertura del pubblico generico senza ignorare le nicchie specifiche.
- **PromptService fail esplicito**: ValueError per variabili mancanti invece di lasciare {{variabile}} nel testo. Un prompt con variabili non sostituite manderebbe al LLM istruzioni rotte.
## Deviations from Plan
### Auto-fixed Issues
**1. [Regola 1 - Bug] Fix .gitignore: backend/data/ era ignorato troppo aggressivamente**
- **Trovato durante:** Task 1 (staging dei file)
- **Problema:** Il pattern `data/` in .gitignore matchava anche `backend/data/`, impedendo di committare `format_mapping.json` e i file prompt .txt che sono file sorgente, non dati runtime
- **Fix:** Cambiato `data/` a `/data/` (solo root) e aggiunto le sottocartelle runtime specifiche (`backend/data/outputs/`, `backend/data/campaigns/`, `backend/data/config/`)
- **Files modificati:** `.gitignore`
- **Verifica:** `git check-ignore -v backend/data/format_mapping.json` → non ignorato
- **Committato in:** `209d896` (parte del Task 1 commit)
---
**Totale deviazioni:** 1 auto-fixed (1 bug)
**Impatto sul piano:** Necessaria per committare file sorgente. Nessuno scope creep.
## Issues Encountered
Nessun problema durante l'implementazione — piano eseguito secondo le specifiche.
## User Setup Required
Nessuno — nessun servizio esterno richiede configurazione per questi file di dominio puro.
## Next Phase Readiness
- CalendarService e PromptService pronti per essere usati da LLMService (Plan 03)
- CANVA_FIELDS locked — CSVBuilder (Plan 04) può iniziare a usarlo
- 7 prompt in italiano pronti — LLMService userà PromptService.compile_prompt() per prepararli
- Tutti i servizi sono puri (zero async, zero HTTP) — testabili indipendentemente
- Nessun blocco: Plan 03 può proseguire
---
*Phase: 01-core-generation-pipeline*
*Completed: 2026-03-08*