Project

General

Profile

Actions

Feature #1551

open
RA

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

API: mode-aware spec writer and the Sécurité marker at filing

Feature #1551: API: mode-aware spec writer and the Sécurité marker at filing

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:** #1549
**Blocks:** nothing

Carry the mode through to the draft and to the filed issue.

`MistralTicketSpecWriter.draft()` (`infrastructure/intake/mistral_spec_writer.py:73`) takes a `request_type` and **forces** the resulting `issue_type` from it rather than letting the model choose: `bug`→`bug`, `feature`→`feature`, `security`→`bug`. Keep the existing faithfulness sentence in `SYSTEM_PROMPT` (*"Base it strictly on what the client said and the context; do not invent scope"*) — it is the guard against the model inventing scope, and it stays.

Then `create_ticket_from_draft.py` stamps a **`Sécurité` marker** into the description metadata block when the mode was `security`, in exactly the shape `BF_DISAGREE_MARKER` uses (`:48`). Redmine custom fields 2–9 are Jenkins-owned, so "tag" in this integration has always meant a greppable token in the body — not a label.

**Two things this ticket must NOT do**, both from #1513's ACs as originally written:

- **Do not set status `Submitted`.** That AC was copied from #47, the SecOps *scanner* path, where we file our own scan output unbilled. On the client path `Submitted` is the paid credit gate. A security conversation files at **Backlog (16)** like every other client ticket. The existing post-create status check (`:192`) stays and must still pass.
- **Do not write `security_key`.** That custom field is the scanner's dedup key; putting a client's free-text concern in it would suppress a real scan finding sharing that key.

The complexity score continues to come from the model in the same JSON call and is pinned verbatim into `ticket_charges` — this ticket does not change pricing.

## Acceptance criteria
- [ ] `draft()` accepts `request_type` and forces `issue_type` from it; a test proves a `security` mode yields `issue_type="bug"` **even when the model returns `"feature"`**.
- [ ] Omitting `request_type` preserves today's behaviour (model-chosen `issue_type`) — existing callers keep working.
- [ ] The faithfulness sentence is still present in `SYSTEM_PROMPT`.
- [ ] A `security` filing renders the `Sécurité` marker in the metadata block; a `bug`/`feature` filing does not.
- [ ] A `security` filing is created with `status_id = RedmineStatus.BACKLOG` — asserted on the outbound Redmine payload, not just the response.
- [ ] A `security` filing sends **no** `security_key` custom field (assert the field is absent from the payload).
- [ ] `bf-disagree` still renders independently and can co-occur with `Sécurité`.
- [ ] The pinned `ticket_charges` cost is unchanged by the mode (same score in → same cost recorded).
- [ ] Gates green: `python -m pytest -q` (**run serially**), `ruff check .`, `mypy src`. TDD: failing test first.

No data to display

Actions

Also available in: PDF Atom