You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

247 lines
7.6 KiB
Markdown

# 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 `<input type="range">` with min=1, max=3, step=1:
```tsx
<div>
<label for="summaryLength" class="block text-sm font-medium text-gray-700">
{t('settings.summaryLength')}
</label>
<p class="text-xs text-gray-500 mb-2">{t('settings.summaryLengthHelp')}</p>
<div class="flex items-center gap-4">
<span class="text-xs text-gray-500">{t('settings.summaryShort')}</span>
<input
type="range"
id="summaryLength"
min="1"
max="3"
step="1"
class="flex-1 h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-indigo-600"
value={settings().summary_length}
onInput={(e) =>
setSettings((prev) => ({
...prev,
summary_length: parseInt(e.currentTarget.value) || 3,
}))
}
/>
<span class="text-xs text-gray-500">{t('settings.summaryDetailed')}</span>
</div>
<div class="text-center text-xs text-gray-500 mt-1">
{settings().summary_length === 1
? t('settings.summaryShort')
: settings().summary_length === 2
? t('settings.summaryMedium')
: t('settings.summaryDetailed')}
</div>
</div>
```
- [ ] **Step 4: Update E2E test fixture**
In `e2e/tests/generation-live.spec.ts`, add `summary_length: 3,` to the settings payload.
- [ ] **Step 5: TypeScript check**
Run: `cd frontend && npx tsc --noEmit`
Expected: No errors
- [ ] **Step 6: Commit**
```bash
git add frontend/src/types.ts frontend/src/i18n/fr.ts \
frontend/src/pages/Settings.tsx e2e/tests/generation-live.spec.ts
git commit -m "feat: add summary length slider to Settings page"
```