diff --git a/docs/superpowers/plans/2026-03-26-summary-length.md b/docs/superpowers/plans/2026-03-26-summary-length.md new file mode 100644 index 0000000..4773fd8 --- /dev/null +++ b/docs/superpowers/plans/2026-03-26-summary-length.md @@ -0,0 +1,246 @@ +# Configurable Summary Length — Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add a `summary_length` setting (1=court, 2=moyen, 3=detaille) that controls how detailed article summaries are and how much article body is sent to the LLM. + +**Architecture:** New integer setting (1-3) following the existing settings pattern. Affects the classify prompt instruction and body snippet size in the pipeline. Frontend slider with 3 positions. + +**Tech Stack:** Rust (sqlx), SolidJS, PostgreSQL + +**Spec:** `docs/superpowers/specs/2026-03-26-summary-length-design.md` + +--- + +### Task 1: Migration + backend setting + +**Files:** +- Create: `backend/migrations/20260326000023_add_summary_length.sql` +- Modify: `backend/src/models/settings.rs` +- Modify: `backend/src/db/settings.rs` +- Modify: `backend/src/services/prompts.rs` (test fixture) +- Modify: `backend/tests/api_syntheses_test.rs` (test fixture) +- Modify: `backend/tests/pipeline_test.rs` (test fixture) +- Modify: `CLAUDE.md` + +Follow the exact same pattern as `batch_size` was added. This is mechanical. + +- [ ] **Step 1: Create migration** + +```sql +ALTER TABLE settings ADD COLUMN summary_length INTEGER NOT NULL DEFAULT 3; +``` + +- [ ] **Step 2: Add `summary_length: i32` to all Rust settings structs** + +In `backend/src/models/settings.rs`: +- Add `pub summary_length: i32` to `UserSettings` and `UpdateSettingsRequest` (after `batch_size`) +- Add to `Default for UserSettings`: `summary_length: 3,` +- Add to `valid_request()` test fixture: `summary_length: 3,` +- Add validation: +```rust +if !(1..=3).contains(&self.summary_length) { + return Err("summary_length must be between 1 and 3".into()); +} +``` + +- [ ] **Step 3: Update DB queries in `db/settings.rs`** + +Add `summary_length` to `SettingsRow`, `TryFrom` impl, both SQL queries (INSERT columns, VALUES, ON CONFLICT SET, RETURNING), and `.bind()` calls. + +- [ ] **Step 4: Update test fixtures** + +Add `summary_length: 3,` to: +- `backend/src/services/prompts.rs` → `test_settings()` +- `backend/tests/api_syntheses_test.rs` → settings JSON payload +- `backend/tests/pipeline_test.rs` → `setup_user_with_settings` JSON payload + +- [ ] **Step 5: Update CLAUDE.md** + +Change `## Database (22 migrations)` to `## Database (23 migrations)`. + +- [ ] **Step 6: Build and test** + +Run: `cd backend && cargo build && cargo test --lib` +Expected: All pass + +- [ ] **Step 7: Commit** + +```bash +git add backend/migrations/20260326000023_add_summary_length.sql \ + backend/src/models/settings.rs backend/src/db/settings.rs \ + backend/src/services/prompts.rs backend/tests/api_syntheses_test.rs \ + backend/tests/pipeline_test.rs CLAUDE.md +git commit -m "feat: add summary_length setting (1=court, 2=moyen, 3=detaille)" +``` + +--- + +### Task 2: Prompt and pipeline changes + +**Files:** +- Modify: `backend/src/services/prompts.rs` +- Modify: `backend/src/services/synthesis.rs` + +- [ ] **Step 1: Update `build_article_classify_prompt` to accept `summary_length`** + +In `backend/src/services/prompts.rs`, add `summary_length: i32` as a new parameter: + +```rust +pub fn build_article_classify_prompt( + title: &str, + body_snippet: &str, + categories: &[String], + summary_length: i32, +) -> (String, String) { +``` + +Change the instruction line from: +``` +"Genere un titre clair et un resume de 4 a 5 lignes." +``` +To: +```rust +let summary_instruction = match summary_length { + 1 => "Genere un titre clair et un resume de 3 a 4 lignes.", + 2 => "Genere un titre clair et un resume de 6 a 8 lignes.", + _ => "Genere un titre clair et un resume detaille de 12 a 15 lignes.", +}; +``` + +Use `summary_instruction` in the format string instead of the hardcoded line. + +- [ ] **Step 2: Update all call sites in `synthesis.rs`** + +Find all calls to `build_article_classify_prompt` in `synthesis.rs`. There are 2 (Phase 1 and Phase 2 Brave classify loops). Add `settings.summary_length` as the new argument. + +Also update the body snippet size from hardcoded 500 to dynamic: + +```rust +let snippet_size = match settings.summary_length { + 1 => 500, + 2 => 2000, + _ => 4000, +}; +let body_snippet: String = body_text.chars().take(snippet_size).collect(); +``` + +Apply this in both Phase 1 (~line 487) and Phase 2 Brave (~line 665) classify loops. + +- [ ] **Step 3: Update prompt tests** + +In `prompts.rs` tests, update existing `article_classify_prompt_*` tests to pass `summary_length: 3`. Add a new test: + +```rust +#[test] +fn article_classify_prompt_short_summary() { + let (_, user) = build_article_classify_prompt( + "Title", "Content", &["AI".into()], 1, + ); + assert!(user.contains("3 a 4 lignes")); +} + +#[test] +fn article_classify_prompt_detailed_summary() { + let (_, user) = build_article_classify_prompt( + "Title", "Content", &["AI".into()], 3, + ); + assert!(user.contains("12 a 15 lignes")); +} +``` + +- [ ] **Step 4: Build and test** + +Run: `cd backend && cargo build && cargo test --lib` +Expected: All pass + +- [ ] **Step 5: Commit** + +```bash +git add backend/src/services/prompts.rs backend/src/services/synthesis.rs +git commit -m "feat: dynamic summary length and body snippet size based on setting" +``` + +--- + +### Task 3: Frontend slider + i18n + types + +**Files:** +- Modify: `frontend/src/types.ts` +- Modify: `frontend/src/i18n/fr.ts` +- Modify: `frontend/src/pages/Settings.tsx` +- Modify: `e2e/tests/generation-live.spec.ts` + +- [ ] **Step 1: Update frontend types** + +In `frontend/src/types.ts`: +- Add `summary_length: number;` to `UserSettings` (after `batch_size`) +- Add `summary_length: 3,` to `DEFAULT_SETTINGS` + +- [ ] **Step 2: Add i18n labels** + +In `frontend/src/i18n/fr.ts`, add: + +```typescript +'settings.summaryLength': 'Niveau de detail des resumes', +'settings.summaryLengthHelp': 'Controle la longueur des resumes generes pour chaque article.', +'settings.summaryShort': 'Court', +'settings.summaryMedium': 'Moyen', +'settings.summaryDetailed': 'Detaille', +``` + +- [ ] **Step 3: Add slider to Settings.tsx** + +In `frontend/src/pages/Settings.tsx`, add a slider in the main settings section (near `max_items_per_category`). Use an `` with min=1, max=3, step=1: + +```tsx +
{t('settings.summaryLengthHelp')}
+