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.

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: 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:
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.rstest_settings()

  • backend/tests/api_syntheses_test.rs → settings JSON payload

  • backend/tests/pipeline_test.rssetup_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
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:

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; to UserSettings (after batch_size)

  • Add summary_length: 3, to DEFAULT_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"