7.6 KiB
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
ALTER TABLE settings ADD COLUMN summary_length INTEGER NOT NULL DEFAULT 3;
- Step 2: Add
summary_length: i32to all Rust settings structs
In backend/src/models/settings.rs:
- Add
pub summary_length: i32toUserSettingsandUpdateSettingsRequest(afterbatch_size) - Add to
Default for UserSettings:summary_length: 3, - Add to
valid_request()test fixture:summary_length: 3, - Add validation:
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_settingsJSON 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
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_promptto acceptsummary_length
In backend/src/services/prompts.rs, add summary_length: i32 as a new parameter:
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:
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:
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:
#[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
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;toUserSettings(afterbatch_size) -
Add
summary_length: 3,toDEFAULT_SETTINGS -
Step 2: Add i18n labels
In frontend/src/i18n/fr.ts, add:
'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:
<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
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"