Phase 3 (2/3): behavioural_duel + mental_maths_blitz mechanics#13
Merged
TahaKhanM merged 11 commits intoMay 15, 2026
Merged
Conversation
…maths_blitz) Spec at docs/superpowers/specs/2026-05-15-phase3-behavioural-mental-maths-design.md; TDD plan at docs/superpowers/plans/2026-05-15-phase3-behavioural-mental-maths.md. Scope: behavioural_duel (Pro arena, 4-Q rubric LLM) + mental_maths_blitz (Tech arena, deterministic 30-Q streak). Both reuse the Phase 3 sub-plan #1 pipeline. Also includes a security fix: sanitize answer-key fields out of public template reads. ADRs governing: 0006, 0008, 0011, 0012, 0013, 0014. No new ADRs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a 4-question STAR-style wizard room for the behavioural_duel mechanic, mirroring CvBattleRoom's submit + confirmation pattern. Per spec §4.1: one question at a time, per-question 180s countdown that force-advances on expiry (or auto-submits if it's the last question), Skip + Next buttons, Submit-with-confirm-dialog on Q4. Also extracts the shared Countdown pill into `_countdown.tsx` so the new room and CvBattleRoom can both consume it. The existing `data-testid="countdown"` contract is preserved so CvBattleRoom tests stay green. Plan: docs/superpowers/plans/2026-05-15-phase3-behavioural-mental-maths.md (Task B1) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the keyboard-driven 30-question streak room for the mental_maths_blitz mechanic. Per spec §4.2: - Big tabular-nums prompt + autofocused numeric input. - Enter advances regardless of whether the answer is correct — no per-question feedback (deterministic judge runs server-side). - Single 90s overall countdown (NOT per-question). - "X answered" counter renders the running fill count. - Auto-submits on either time-out OR when the user finishes the last prompt. No confirmation dialog per blitz convention. Empty + Enter leaves the slot null so the deterministic judge can mark unanswered questions explicitly wrong. Reuses the shared <Countdown> helper introduced in Task B1. Plan: docs/superpowers/plans/2026-05-15-phase3-behavioural-mental-maths.md (Task B2) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…mix + 3 anchors (Task A1) Phase 3 sub-plan #2 Task A1. Mirrors the cv_battle seed pattern from seed_phase1_cv_battle_mechanic.py but targets the Professional arena: - New ``behavioural_duel`` mechanic with a STAR-style 5-category default rubric (star_structure, specificity, ownership, learning, fit) and four embedded behavioural questions used by the frontend room composite. - Dev judge mix is Gemini-primary (2x RubricLLMJudge + 1x PairwiseLLMJudge vs. STRONG anchor) per ADR 0013; production mix is Claude-primary per ADR 0006. Every judge attributes to the ``professional`` JudgeType. - One default ``behavioural-duel-phase3-default`` template linked to the mechanic with ``judge_mix_definition`` left NULL so the factory inherits from the mechanic. - Three STRONG ``CalibrationAnchor`` rows with role-flavoured 4-answer blobs (SWE intern, consulting placement, junior PM) joined by ``\n\n---\n\n`` separators so a single rubric pass reads the full submission. Indexed by ``model_baseline_scores['anchor_index']`` so the upsert path is stable across reruns (cv_battle only kept one anchor per tier; this seed keeps three STRONG anchors). - Added the enum values the new mechanics require: ``ChallengeType.MENTAL_MATHS``, ``ScoringMode.JUDGE_LLM``, ``ScoringMode.DETERMINISTIC``, ``InputType.LONG_TEXT``, ``InputType.NUMERIC_STREAK``, and ``OutputType.STRUCTURED``. Plan: docs/superpowers/plans/2026-05-15-phase3-behavioural-mental-maths.md (Task A1) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…estions (Task A2) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… + mental_maths_blitz (Task B3)
Extends the per-mechanic play page from a single-mechanic
dispatcher (cv-battle only) to a three-way dispatch covering
behavioural-duel and mental-maths-blitz alongside the existing
cv-battle path.
- `cv-battle` -> `CvBattlePlay` (unchanged)
- `behavioural-duel` -> `BehaviouralDuelPlay`:
- Fetches the full ChallengeTemplateRead to access
`rubric_definition.questions`
- Wires `BehaviouralDuelRoom` with the question list +
180s per-question timer (spec 4.1)
- Submits `{submission_payload: {answers: [{question, answer}, ...]}}`
- `mental-maths-blitz` -> `MentalMathsBlitzPlay`:
- Same full-template fetch to access the sanitized
`rubric_definition.questions[].prompt` (the `answer`
field is stripped server-side by Task A3)
- Wires `MentalMathsBlitzRoom` with the prompt list +
template-driven `totalTimeSeconds` (defaults to 90s
if neither attempt nor mechanic exposes one)
- Submits `{submission_payload: {answers: (number | null)[]}}`
- Anything else (e.g. `leetcode-medium`) falls through to the
shared `ComingSoonPlaceholder`.
Shared helpers (`useDomainProfileQuery`, `deriveEffectiveMode`,
`useCreateAttemptMutation`, `useFullTemplateQuery`,
`extractBehaviouralQuestions`, `extractMentalMathsPrompts`,
`NoDomainProfile`) keep the three play components symmetric while
preserving the cv_battle flow exactly. The dispatcher remains a
single file so the wiring story stays auditable.
Tests:
- 14 tests, all green.
- Existing 10 cv_battle / Coming-soon / error tests preserved.
- New: BehaviouralDuelRoom renders with the resolved question list,
and full 4-question submit posts the correct payload shape.
- New: MentalMathsBlitzRoom renders with the resolved prompt list,
and short-prompt submit posts `{answers: (number | null)[]}`.
- Frontend-v2 vitest count: 313 (was ~291 baseline; +B1 +B2 +B3
additions land here).
Plan: docs/superpowers/plans/2026-05-15-phase3-behavioural-mental-maths.md
Spec: docs/superpowers/specs/2026-05-15-phase3-behavioural-mental-maths-design.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ads (Task A3) The mental_maths_blitz mechanic embeds the deterministic answer key in ``rubric_definition.correct_answers`` and in each ``rubric_definition.questions[i].answer``. Both fields must NEVER reach the client — otherwise the deterministic judge is trivially defeated. Adds ``_sanitize_rubric_for_public_read`` to the templates service, plus ``list_challenge_templates_for_public_api`` and ``get_challenge_template_for_public_api`` wrappers that detach the template from the session and overwrite ``rubric_definition`` with a sanitized deep copy. The router now uses these wrappers. The pipeline / scoring helpers continue to call the unsanitised ``get_challenge_template_or_error`` so ``DeterministicNumericJudge`` still has the full answer key. Schema additions: ``RubricQuestion(prompt: str)`` and ``RubricDefinition.questions: list[RubricQuestion]`` so the room composites can read the question prompts; the matching ``answer`` field on each entry is stripped at the read boundary. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… /arena (Task B4) Drops `behavioural_duel` and `mental_maths_blitz` from `COMING_SOON_MECHANICS` now that their `BehaviouralDuelRoom` / `MentalMathsBlitzRoom` composites + page dispatcher are live (Tasks B1, B2, B3). Once the backend Task A1/A2/A4 seeds land in `seed_reference_data` the arena hub will render them via the live template path automatically. `leetcode_medium` stays on the placeholder list until sub-plan #3 ships its `ChallengeTemplate` + Vercel Sandbox-driven judge. Tests updated: - `COMING_SOON_MECHANICS` keys reduced to just `["leetcode_medium"]`. - New test verifies that when the backend returns `behavioural_duel` / `mental_maths_blitz` templates, they show up as `live` mechanics and don't reappear as coming-soon stubs. - Frontend-v2 vitest count: 314 (one new arena.test assertion). Plan: docs/superpowers/plans/2026-05-15-phase3-behavioural-mental-maths.md Spec: docs/superpowers/specs/2026-05-15-phase3-behavioural-mental-maths-design.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…reference_data (Task A4)
Adds two reusable entry points — ``seed_behavioural_duel(db, profile)`` and
``seed_mental_maths_blitz(db)`` — to the Phase 3 seed scripts so the
``seed_reference_data`` bootstrap can drive them with a caller-supplied
session. The bootstrap loads the seed modules via ``importlib.util``
(scripts/ is not a Python package). Both are idempotent — re-running is a
no-op for row counts.
Adjusts ``test_seed_behavioural_duel.py`` so the anchor-related tests
expect the conftest fixture to have already seeded the 3 STRONG anchors
(``upsert_anchors`` now returns 0 on rerun in test). Widens
``RubricDefinition.questions`` to accept either ``RubricQuestion`` dicts
or plain strings, since ``behavioural_duel`` stores 4 STAR prompts as
strings while ``mental_maths_blitz`` stores ``{prompt, answer}`` dicts
(the ``answer`` field is stripped at the public read boundary).
Adds ``test_seed_reference_data_phase3.py`` to lock in that both
mechanics + their default templates exist after the fixture runs.
Also drops an unused ``DomainPathway`` import + wraps the over-long
usage docstring in the behavioural seed (pre-existing ruff hits).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds ``_link_phase3_templates_to_skill_nodes`` to the bootstrap so the new ``behavioural-duel-phase3-default`` template surfaces in the Professional repair path (via ``star-storytelling``, ``stakeholder-judgement``, ``conflict-resolution``, ``leadership-framing``) and ``mental-maths-blitz-phase3-default`` feeds the Technical repair drills (via ``numerical-accuracy``, ``problem-decomposition``). No new skill nodes — existing leaves cover the relevant signals. Deeper skill-tree expansion lands in Phase 4. Idempotent: re-running upserts the link rows in place. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… (Task C2) - Root CLAUDE.md: bump frontend-v2 surface to include behavioural-duel + mental-maths-blitz mechanics. - frontend-v2/CLAUDE.md: rename section to "Phase 3 sub-plans #1 + #2 additions"; add the two new room composites; explain mechanic-specific submission_payload shapes; note that leetcode_medium is the only remaining COMING_SOON entry. - backend/CLAUDE.md: document the public-template-read sanitization split (get_*_for_public_api vs ORM-direct reads for the scoring pipeline). - Master plan §9 Phase 3: mark sub-plan #2 complete; note PR #13. Plan: docs/superpowers/plans/2026-05-15-phase3-behavioural-mental-maths.md Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
6 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 3 sub-plan #2 of the Ascendra v2 master plan. Two more mechanics shipped end-to-end through the new pipeline (built in sub-plan #1):
behavioural_duel— Professional arena. 4 behavioural questions (text answers), Gemini-primary multi-judge rubric scoring (2 rubric LLM + 1 pairwise vs. STRONG anchor). Production profile uses Claude Opus 4.7 + Sonnet 4.6.mental_maths_blitz— Technical arena. 30 deterministic numeric questions in 90 s (mix of multiplication, percentages, FX cross-rates, divisions). Scored byDeterministicNumericJudgewith accuracy + time bonus.Both mechanics now appear live on the
/arenahub and dispatch to dedicated room composites from/arena/[mechanic]/play.Plan: docs/superpowers/plans/2026-05-15-phase3-behavioural-mental-maths.md
Spec: docs/superpowers/specs/2026-05-15-phase3-behavioural-mental-maths-design.md
Stacked on: #12. Will be re-targeted to `main` once #12 merges.
Security fix included
mental_maths_blitzcarries the answer key (correct_answers+ per-questionanswer) in itsrubric_definition. The public template-read endpoints (GET /api/v1/challenge-templates/{id}and list) now sanitize these fields out before returning to clients. The scoring pipeline still reads the unfiltered rubric via the ORM directly, soDeterministicNumericJudgekeeps working. New endpointsget_challenge_template_or_error_for_public_api+list_challenge_templates_for_public_apienforce the sanitization at the API boundary.ADRs governing this work
0006 (LLM cost / judge mix), 0008 (contexts), 0011 (Workflow topology), 0012 (Judge Protocol), 0013 (Gemini dev), 0014 (direct provider APIs). No new ADRs.
Test plan
Backend
Frontend-v2
Commit highlights
Open follow-ups (deferred to sub-plan #3 or later phases)
Same set as PR #12's follow-ups, plus:
TranscriptAnalysisJudgewiring — still a stub; Phase 4.🤖 Generated with Claude Code