Project

General

Profile

Actions

Feature #1549

open
RA

Feature #1513: Implémenter des agents conversationnels spécialisés pour la qualification des demandes sur claude code

API: RequestType, per-mode modules and Conversation.request_type

Feature #1549: API: RequestType, per-mode modules and Conversation.request_type

Added by Redmine Admin 1 day ago.

Status:
Spec
Priority:
Normal
Assignee:
-
Start date:
08/03/2026
Due date:
% Done:

0%

Estimated time:
spec_ref:

docs/superpowers/specs/2026-08-03-specialized-intake-agents-design.md

build_status:
build_number:
ci_run_url:
scan_status:
scan_report_url:
deploy_status:
preprod_url:
deployed_at:
branch:
pr_url:
security_key:
severity:
paused:

Description

**Surface:** backend (`api/`)
**Depends on:** nothing
**Blocks:** every other child of #1513

The foundation child: the new type, the per-mode prompt modules as pure data, and the column that persists the client's choice.

Add **`domain/intake/modes.py`** holding `RequestType = Literal["bug", "feature", "security"]`, the per-mode slot definitions (key, required flag, question text) and the prompt module strings. Pure data and strings — **no I/O, no LLM call, no FastAPI import** — so the whole thing is testable without a network or a database.

`RequestType` is deliberately **distinct from the existing `IssueType`** (`domain/intake/value_objects.py:6`, `bug | feature`). `RequestType` is the *conversational mode*; `IssueType` is what gets filed. Do **not** widen `IssueType` — a third value there would reach the Redmine mapping, the board and the MCP contract for no benefit. The `security` → `bug` mapping belongs to this module as an explicit table.

Then add `request_type` to `Conversation` (`domain/conversations/entities.py:12`) and an Alembic migration for the column. **Nullable, no backfill** — a null means today's generic persona, which keeps every existing conversation working untouched and keeps "just start typing" a valid entry path. `StartConversation` (`application/start_conversation.py`) accepts and persists it, defaulting to `None`.

The slot question text is client-facing, so it goes through the existing i18n message catalogue (`domain/i18n/messages.py`) in FR and EN, not hardcoded English.

## Acceptance criteria
- [ ] `RequestType` and the per-mode slot/module definitions live in `domain/intake/modes.py` with no I/O, no `httpx` and no FastAPI imports (assert by import in a unit test).
- [ ] `IssueType` is **unchanged** — still exactly `bug | feature`; a test asserts the mode→issue-type map sends `security` to `bug`.
- [ ] Every mode defines a non-empty slot set, and each slot carries a required flag and FR + EN question text.
- [ ] Alembic migration adds a **nullable** `request_type`; `alembic upgrade head` then `downgrade` both run clean against an ephemeral `pgvector/pgvector:pg16`.
- [ ] An existing conversation row (null `request_type`) loads and round-trips without error — no backfill, no default written.
- [ ] `StartConversation` persists a supplied `request_type` and defaults to `None` when omitted; the existing two-arg call site keeps compiling.
- [ ] An unknown/garbage `request_type` value is rejected rather than persisted.
- [ ] Gates green: `python -m pytest -q` (**run serially** — concurrent runs share one Postgres), `ruff check .`, `mypy src`. TDD: failing test first.

No data to display

Actions

Also available in: PDF Atom