docs: hints engine P1-P4 livré (P5 partial)

§5 Phased plan adds Status column: P1 4f6d916, P2 1ed230e, P3 5500502, P4 61ca356 all . P5 firmware integration partial (hints_client OK, scenario integration PENDING). P6 auto-trigger stuck PENDING. §2.2 response envelope updated with 17 actual fields. §6 Risks: MLX 32B Q4 ~11s warm, F5-TTS event-loop blocking cross-ref. §7 Acceptance gates: 9 checked, 4 PENDING (playtest firmware + soak 24h).
This commit is contained in:
L'électron rare
2026-05-03 22:13:08 +02:00
parent 426137dce2
commit cf1bce241b
@@ -91,6 +91,8 @@ Content-Type: application/json
```
**Live response shape (P1-P4 delivered)**:
```json
{
"refused": false,
"reason": null,
@@ -103,6 +105,32 @@ Content-Type: application/json
"count": 1,
"level_requested": 1,
"level_served": 1,
"score_penalty": 50,
"total_penalty": 50,
"cooldown_until_ms": 1880000,
"retry_in_s": 60,
"level_floor_adaptive": 1,
"stuck_minutes": 3,
"failed_attempts": 0,
"group_profile_used": "MIXED"
}
```
### 2.3 Response (refused — anti-cheat)
```json
{
"refused": true,
"reason": "rate_limit",
"details": "3 hints already given for P5_MORSE (cap = 3)",
"cooldown_until_ms": null
}
```
Refusal reasons: `rate_limit` (cap reached), `cooldown` (too soon since last), `phase_blocked` (PROFILING), `unknown_puzzle`, `llm_unavailable`.
> **Implemented (2026-05-03)** — refusals are emitted as `{refused: true, reason: <code>, ...}` with the same envelope as success (fields like `retry_in_s`, `cooldown_until_ms`, `total_penalty` populated where relevant). Reason codes match the original list.
## 3. Adaptive level selection
```
@@ -116,6 +144,8 @@ Content-Type: application/json
# If stuck_timer is short (< 4 min), bump down one level
if context.stuck_timer_ms < 240_000 and base_level > 1:
return base_level - 1
elif context.group_profile == "NON_TECH":
# NON_TECH gets faster escalation when stuck_timer is high
if context.stuck_timer_ms > 360_000 and base_level < 3:
return base_level + 1
@@ -172,14 +202,14 @@ Rewrite is **temperature = 0.4** (slight variability for replay flavor, determin
| Risk | Probability | Mitigation |
|------|-------------|------------|
| LLM rewrites the base phrase into a literal solution leak | Medium | Per-puzzle banned-word list ; safety filter rejects, falls back to base |
| LiteLLM cold start adds latency to the first request | Medium | Warm-up call on hints-server boot ; player won't notice the first call after game start |
| Rate-limit math drifts between hints-server and ESP32 firmware view of `hints_already_given` | Medium | Server is single source of truth ; firmware sends its view but server returns authoritative count in response, firmware mirrors |
| Adaptive logic feels unfair to NON_TECH groups (escalates "too fast") | Medium | Tunable thresholds in YAML config ; one playtest per profile validates on each engine change |
| Stuck-timer auto-trigger fires while player is on a phone call / break | Low | Trigger requires a recent hardware event (any button press in last 60 s) before firing |
## 7. Acceptance gates (before declaring P6 done)
| LLM rewrites the base phrase into a literal solution leak | Medium | Per-puzzle banned-word list ; safety filter rejects, falls back to base |
| LiteLLM cold start adds latency to the first request | Medium | Warm-up call on hints-server boot ; player won't notice the first call after game start |
| Rate-limit math drifts between hints-server and ESP32 firmware view of `hints_already_given` | Medium | Server is single source of truth ; firmware sends its view but server returns authoritative count in response, firmware mirrors |
| Adaptive logic feels unfair to NON_TECH groups (escalates "too fast") | Medium | Tunable thresholds in YAML config ; one playtest per profile validates on each engine change |
| Stuck-timer auto-trigger fires while player is on a phone call / break | Low | Trigger requires a recent hardware event (any button press in last 60 s) before firing |
| **MLX 32B Q4 (`hints-deep`) warm latency ~11 s — dépasse le budget initial 2 s** | High (observed 2026-05-03) | Fallback verbatim sur timeout déjà actif ; envisager pré-roll TTS (lecture d'une phrase de transition Zacus pendant que le rewrite calcule) ; revisit du modèle si budget > 5 s persistant en playtest |
| **Event-loop blocking de F5-TTS si le hint final est resynthétisé via le pipeline TTS MacStudio** | Medium | Voir `2026-05-03-tts-stt-llm-macstudio-design.md` §2.5 — le hint doit emprunter la voie Piper Tower (synchrone, latence ~250 ms) plutôt que F5-TTS tant que l'event-loop n'est pas isolé en process worker |
## 7. Acceptance gates (before declaring P6 done)
- [x] Static phrase lookup avec couverture audit `/hints/coverage` (P1, commit `4f6d916`)
@@ -192,16 +222,25 @@ Rewrite is **temperature = 0.4** (slight variability for replay flavor, determin
- [x] LiteLLM-down test: hints server falls back to base phrase (P2, fallback path testé)
- [x] `npc_phrases.yaml` schema validator catches a missing `level_3` for a puzzle (refuses startup) (P1)
- [x] Suite Python totale : 35 tests verts au 2026-05-03
- [ ] Voice loop test: button → hint audio within 5 s p95 — **PENDING playtest firmware réel**
- [ ] Safety filter test sur la sortie LLM réelle (synthétique → rejeté) — partiellement couvert par tests unitaires, **PENDING validation playtest**
- [ ] At least one playtest in `playtests/` exercises 3 hints across 2 puzzles — **PENDING**
- [ ] Soak test 24 h hints-server (mémoire, leaks LiteLLM) — **PENDING**
## 9. Open questions
None at design stage. All decisions resolved during 2026-05-03 brainstorm:
- Trigger: button + auto stuck-timer ✅
- Escalation: adaptive per profile + stuck-timer ✅
- Anti-cheat: cap 3 + progressive penalty (50/100/200) ✅
## 8. Out of scope
- Hint **generation** (LLM authors fresh hints). The static bank stays canonical.
- Multi-language hints. French only.
- Hint quality tracking / playtest analytics dashboard. Possible future evolution if needed.
- Voice STT for the "more help" phrase. Use the button.
- Per-player hint history (multiple players → individual help). Group-level only.
## 9. Open questions
None at design stage. All decisions resolved during 2026-05-03 brainstorm:
- Trigger: button + auto stuck-timer ✅
- Escalation: adaptive per profile + stuck-timer ✅
- Anti-cheat: cap 3 + progressive penalty (50/100/200) ✅
- Content: hybrid static base + LLM rewrite (Qwen 72B) ✅
- Service: dedicated FastAPI server on MacStudio :4100 ✅