Tasks completed: 2/2 - Backend prompts router with 4 CRUD endpoints - Frontend Prompt Editor page with types, hooks, route, sidebar SUMMARY: .planning/phases/02-prompt-control-output-review/02-01-SUMMARY.md Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
102 lines
4.5 KiB
Markdown
102 lines
4.5 KiB
Markdown
---
|
|
phase: 02-prompt-control-output-review
|
|
plan: 01
|
|
subsystem: prompt-management
|
|
tags: [fastapi, react, crud, prompt-editor, tanstack-query]
|
|
|
|
dependency_graph:
|
|
requires:
|
|
- 01-02 (PromptService with load/save/list/variables/exists methods)
|
|
- 01-04 (Web UI with stone/amber palette, Sidebar, Layout, routing)
|
|
provides:
|
|
- Prompt CRUD API (4 endpoints: list, read, write, reset)
|
|
- Prompt Editor UI page with live variable extraction
|
|
affects:
|
|
- 02-02 (Output Review enhancement may reference prompt editing)
|
|
- Future phases that add new prompt types
|
|
|
|
tech_stack:
|
|
added: []
|
|
patterns:
|
|
- Lazy PromptService init for directory lifecycle sync
|
|
- Default vs modified comparison for prompt versioning
|
|
- Client-side regex for live variable extraction
|
|
|
|
key_files:
|
|
created:
|
|
- backend/routers/prompts.py
|
|
- frontend/src/pages/PromptEditor.tsx
|
|
modified:
|
|
- backend/main.py
|
|
- frontend/src/types.ts
|
|
- frontend/src/api/hooks.ts
|
|
- frontend/src/App.tsx
|
|
- frontend/src/components/Sidebar.tsx
|
|
|
|
decisions:
|
|
- id: prompt-lazy-init
|
|
decision: "PromptService initialized lazily via _get_prompt_service() instead of module-level"
|
|
reason: "PROMPTS_PATH directory is created during FastAPI lifespan, not at import time. Module-level init would fail with FileNotFoundError during import."
|
|
date: 2026-03-08
|
|
|
|
metrics:
|
|
duration: ~5 min
|
|
completed: 2026-03-08
|
|
---
|
|
|
|
# Phase 02 Plan 01: Prompt CRUD + Prompt Editor UI Summary
|
|
|
|
**PromptService CRUD completo con 4 endpoint FastAPI e pagina React Prompt Editor con lista, textarea monospace, variabili live, salva e reset al default.**
|
|
|
|
## What Was Done
|
|
|
|
### Task 1: Backend prompts router (4 CRUD endpoints)
|
|
Created `backend/routers/prompts.py` with `APIRouter(prefix="/api/prompts", tags=["prompts"])`:
|
|
|
|
- **GET /api/prompts** — Lists all `.txt` prompts with `modified` flag (compares runtime vs default in `backend/data/prompts/`)
|
|
- **GET /api/prompts/{name}** — Returns content, required variables, and modified flag
|
|
- **PUT /api/prompts/{name}** — Saves modified content with min_length=10 validation, returns updated variables
|
|
- **POST /api/prompts/{name}/reset** — Restores default content from `backend/data/prompts/`, returns 404 if no default exists
|
|
|
|
Key implementation detail: PromptService is lazily initialized via `_get_prompt_service()` because `PROMPTS_PATH` is created during FastAPI's lifespan event, not at module import time.
|
|
|
|
Router registered in `main.py` before the SPA catch-all mount.
|
|
|
|
### Task 2: Frontend Prompt Editor (page, hooks, types, route, sidebar)
|
|
- **Types**: Added `PromptInfo`, `PromptListResponse`, `PromptDetail` to `types.ts`
|
|
- **Hooks**: Added `usePromptList`, `usePrompt`, `useSavePrompt`, `useResetPrompt` to `hooks.ts` with TanStack Query cache invalidation
|
|
- **Page**: Created `PromptEditor.tsx` with two-column layout (1/3 list, 2/3 editor on lg, stacked on mobile)
|
|
- Prompt list with amber "Modificato" / stone "Default" badges
|
|
- Monospace textarea (min-height 400px, stone-900 bg)
|
|
- Live client-side variable extraction via regex `{{nome}}`
|
|
- Save button (amber, disabled when not dirty)
|
|
- Reset to Default with inline confirmation dialog
|
|
- Success/error feedback inline
|
|
- **Route**: `/prompt-editor` added in `App.tsx`
|
|
- **Sidebar**: "Prompt Editor" nav item with `Pencil` icon, positioned after "Genera Singolo Post" and before "Impostazioni"
|
|
|
|
## Deviations from Plan
|
|
|
|
### Auto-fixed Issues
|
|
|
|
**1. [Rule 3 - Blocking] Lazy PromptService initialization**
|
|
- **Found during:** Task 1
|
|
- **Issue:** Module-level `PromptService(PROMPTS_PATH)` raised `FileNotFoundError` because `PROMPTS_PATH` directory doesn't exist at import time — it's created in the FastAPI lifespan event.
|
|
- **Fix:** Changed to lazy initialization via `_get_prompt_service()` function with `PROMPTS_PATH.mkdir(parents=True, exist_ok=True)` on first access.
|
|
- **Files modified:** `backend/routers/prompts.py`
|
|
- **Commit:** 05972fa
|
|
|
|
## Verification
|
|
|
|
- [x] Backend imports without errors: `from backend.routers.prompts import router` OK
|
|
- [x] 4 routes registered: `/api/prompts/`, `/api/prompts/{name}`, `/api/prompts/{name}`, `/api/prompts/{name}/reset`
|
|
- [x] `main.py` includes `app.include_router(prompts.router)` before SPA catch-all
|
|
- [x] TypeScript compiles with `npx tsc --noEmit` — zero errors
|
|
- [x] Route `/prompt-editor` in App.tsx
|
|
- [x] Sidebar contains "Prompt Editor" nav link
|
|
- [x] Types and hooks exported correctly
|
|
|
|
## Next Phase Readiness
|
|
|
|
Plan 02-01 is complete. The Prompt Editor is functional for CRUD operations on prompt files. Plan 02-02 can proceed independently (Output Review enhancements).
|