Skip to content

Phase 3 + 4-SWE recovery: 72 commits orphaned by stacked-merge of PRs #12-#15#16

Merged
TahaKhanM merged 74 commits into
mainfrom
phase-4-swe-wave-1
May 15, 2026
Merged

Phase 3 + 4-SWE recovery: 72 commits orphaned by stacked-merge of PRs #12-#15#16
TahaKhanM merged 74 commits into
mainfrom
phase-4-swe-wave-1

Conversation

@TahaKhanM

Copy link
Copy Markdown
Owner

Summary

Recovery PR for Phase 3 (3 sub-plans) + Phase 4 sub-plan #1 (SWE Wave 1). The stack of PRs #12 / #13 / #14 / #15 was based on each other (PR #15phase-3-leetcode-sandboxphase-3-behavioural-mental-mathsphase-3-arena-hub-cv-battleworktree-phase-2-pagesmain). When PR #11 merged the bottom of the stack into main at 17:46:11Z, GitHub auto-closed PRs #12#15 as "merged" because their bases were merged, but the actual commits never propagated to main. Same gotcha as PR #10 → PR #11 last cycle (feedback_stacked_prs.md).

This PR re-targets the same branch phase-4-swe-wave-1 (which contains the cumulative tip of the stack) directly at main. 72 commits, clean 3-way merge (no conflicts).

What this recovers

PR #12 — Phase 3 sub-plan #1: Arena hub + cv_battle E2E + 9-step Workflow pipeline + dashboard real data + TopBar.
PR #13 — Phase 3 sub-plan #2: behavioural_duel + mental_maths_blitz mechanics + answer-key sanitization.
PR #14 — Phase 3 sub-plan #3: leetcode_medium + real CodeExecJudge + SandboxRunner (StubSandboxRunner + LocalSubprocessSandboxRunner DEV-only).
PR #15 — Phase 4 sub-plan #1: SWE Wave 1 — leetcode_easy_drill, leetcode_hard_battle, behavioural_lp_drill, system_design_hl, Amazon Internship Superday boss pack, SystemDesignRoom composite, swe_fundamentals skill branch + 4 leaves, SWE cohort taxonomy.

Aggregate: 8 mechanics, 1 boss pack, 21 Ascendra frontend composites, 9-step durable scoring pipeline, 6 HMAC-gated /internal/workflow/* endpoints, 13+ calibration anchors seeded.

Plan / ADR links

  • Plans (will be archived to done/ after merge):
    • docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
    • docs/superpowers/plans/2026-05-15-phase3-behavioural-mental-maths.md
    • docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md
    • docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md
  • ADRs: no new ADRs needed; all decisions fit existing ADRs 0001–0014.

Test plan

Verification re-run on the recovery worktree (.claude/worktrees/phase-4-recovery) at HEAD 28daa6d:

  • cd backend && uv run ruff check app tests scriptsAll checks passed!
  • cd backend && uv run pytest -q351 passed, 1 deselected, 3 warnings in 38.31s
  • cd backend && uv run python scripts/check_context_boundaries.py — clean
  • cd frontend-v2 && npm run lint — clean
  • cd frontend-v2 && npm run build — 11 routes generated (/, /arena, /arena/[mechanic]/play, /dashboard, /design, /login, /onboarding, /replay/[id], /replay/[id]/share, /signup, /_not-found) + Proxy middleware
  • cd frontend-v2 && npm run testTest Files 43 passed (43) / Tests 339 passed (339)

Risks

  • Surface area: 174 files / +28,895 / −1,378. The work is already-reviewed (each sub-plan was its own PR that "merged" cleanly); this PR just lands the orphaned commits at the right target.
  • Rollback: revert this merge; the branch is preserved on origin/phase-4-swe-wave-1.
  • Stacked PR gotcha is now documented and remembered (feedback_stacked_prs.md) — future stacks will be re-targeted explicitly as the chain merges.

🤖 Generated with Claude Code

TahaKhanM and others added 30 commits May 15, 2026 12:22
…+ Workflow 9-step)

Spec at docs/superpowers/specs/2026-05-15-phase3-arena-hub-cv-battle-design.md;
TDD plan at docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md.

Scope: arena hub page (/arena), cv_battle challenge room, redesigned /replay/[id],
dashboard wired to real backend data, top-bar signOut, Vercel Workflow rewritten
as 6 durable steps (collapsing 9 service-layer steps per spec §3.2), FastAPI
submit_challenge_attempt refactored into per-step helpers, AnchorCache invalidation
wired, legacy score_attempt path retired.

Also commits the untracked infra/workflows/.gitignore (.vercel) left from Phase 1.

ADRs governing: 0002, 0003, 0004, 0007, 0008, 0010, 0011, 0012, 0013, 0014.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… 3 sub-plan #1 Task A1)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e_attempt (Task A2)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…JudgePlan build (Task A3)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e on failure (Task A4)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nolith (Task A6)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…k A7)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…fact + integrity (Task A8)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…r eligible ranked (Task A9)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…Task A10)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… A11)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…or + drop legacy score_attempt path (Task A12)

- Rewrite ``submit_challenge_attempt`` as a thin dispatcher:
  workflow disabled → ``run_pipeline_in_process`` (full 9-step inline);
  workflow enabled → ``pipeline.fetch.run`` + ``pipeline.integrity.run``
  + ``ScoringWorkflowClient.enqueue_scoring`` (durable path).
- Delete the legacy ``score_attempt`` / ``ScoringOutcome`` /
  ``llm_score_submission`` symbols and the ``llm_scoring.py`` module
  entirely. Both submit modes now drive the same per-judge pipeline.
- Add ``DeterministicAIGatewayStub`` so the test suite + local dev
  (no provider keys) still produce non-trivial deterministic scores
  through the real ``RubricLLMJudge`` / ``PairwiseLLMJudge`` paths.
- Expose ``pipeline_fetch_run`` / ``pipeline_integrity_run`` as
  call-time-deferred ports wrappers so cross-context callers honour
  ADR 0008 without creating a circular import with ``attempts.ports``.
- Update tests: ``test_workflow_telegraph`` renamed targets to
  ``_enqueue_workflow_scoring``; ``test_ascendra_api`` judge-count
  assertions loosened (legacy fallback now produces 1 ``RubricLLMJudge``
  instead of 2 legacy primary+meta drafts).
- Add ``test_submit_uses_pipeline.py`` covering both dispatcher
  branches end-to-end.

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…sub-plan #1

Replace the legacy synchronous fallback description with the
9-step pipeline package layout under
``app/contexts/scoring/services/pipeline/``. Document
``submit_challenge_attempt`` as a thin in-process / workflow
dispatcher and call out the ``DeterministicAIGatewayStub``
fallback for keyless dev/test runs. Refresh the environment-
variables note (drop ``OPENAI_API_KEY``; add ``GEMINI_API_KEY``
/ ``ANTHROPIC_API_KEY`` + workflow vars).

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Single-shot dashboard read that the v2 dashboard page renders without
follow-up requests. Composes existing services through the public
ports of each bounded context (ADR 0008):

- domain.get_domain_profile_or_error → rating panels (per arena +
  overall) with rating, division ladder, confidence, and 7-day delta
  computed from EloSnapshot history.
- matches.list_matches(limit=5) → anonymised "recent matches" strip,
  ordered by resolved_at desc. Now uses a two-stage id-first query so
  the limit isn't broken by participant-join row duplication.
- skill.get_top_repair_leaf (new) → lowest-progress non-mastered
  SkillMastery, paired with its repair-anchored ChallengeTemplate.
- quests.list_active_quests_for_user (new) → first IN_PROGRESS
  QuestProgress with computed 0..1 fraction and the default reward XP.
- leaderboards.get_leaderboard_rows → optional next_cohort_rank.

The endpoint mounts at /api/v1/me/dashboard via a second include
of /me on the v1 router. The boundary check stays green: each
cross-context call goes through `ports.py`, never through
{models,services,schemas,api} directly.

5 new tests in test_me_dashboard.py cover auth, missing-profile,
the full-shape happy path, the empty-state nulls, and the
caller-isolation case for matches. Full suite: 249 pass.

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ine (Task A13)

Add the six HMAC-gated internal endpoints that let the TS Vercel Workflow
drive the FastAPI scoring pipeline step-by-step (spec §3.2 + §4.1):

- POST /attempts/{id}/fetch                       — re-load + return identifiers
- POST /attempts/{id}/integrity                   — duplicate-submission heuristic
- POST /attempts/{id}/score-judges-and-aggregate  — judges + meta → FinalScoreInputs
- POST /attempts/{id}/persist-final-score         — FinalScore + ReplayArtifact + flags
- POST /attempts/{id}/apply-rating                — Match + EloSnapshot (ranked only)
- POST /attempts/{id}/finalize                    — mastery + quests + status flip

The workflow is stateless across steps: only attempt_id rides between
calls (+ FinalScoreInputs body between aggregate and persist). Each
endpoint rebuilds its PipelineContext fresh via the new
``pipeline_rebuild_context`` helper (re-loads attempt + template +
mechanic + domain_profile + consent without mutating state — distinct
from ``pipeline.fetch.run`` which is destructive).

New files:
- backend/app/contexts/scoring/schemas/workflow_io.py — Pydantic
  request/response models. ``WorkflowScoreAndAggregateResponse`` mirrors
  ``FinalScoreInputs`` so the workflow ships the body verbatim to
  ``persist-final-score``.
- backend/app/contexts/scoring/services/pipeline/rebuild.py — the
  read-only context rebuilder, re-exported via ``scoring.ports`` as
  ``pipeline_rebuild_context`` (call-time-deferred to break the
  attempts ↔ scoring ports cycle).
- backend/tests/test_internal_workflow_phase3_endpoints.py — 17 tests
  covering rebuild_context (round-trip + missing attempt) and each of
  the 6 endpoints (200 happy path + 401 unsigned + side effects).

Constraints honoured:
- All routes mounted under ``/internal/workflow/`` with
  ``include_in_schema=False`` (ADR 0011).
- HMAC-gated by the existing ``WorkflowHMACMiddleware``; tests verify
  the 401 fail-closed.
- ``AppError`` only — no raw HTTPException.
- ADR 0008 boundaries clean: pipeline step modules imported through
  scoring.ports (deferred) or directly (same context). New helper +
  schemas re-exported via scoring.ports.

Test counts: 249 passed (baseline 232 + 17 new). Ruff + boundary check
both clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… (Task B1)

Adds the TS-side counterparts to the six Phase 3 /internal/workflow/*
endpoints that Stream A shipped:

  - workflowFetch
  - workflowIntegrity
  - workflowScoreAndAggregate
  - workflowPersistFinalScore
  - workflowApplyRating
  - workflowFinalize

Each wrapper HMAC-signs the body, sends `request_id` via X-Request-Id
header (the FastAPI handlers read it from there, not the body), and
throws WorkflowStepError on non-2xx so the workflow SDK's retry policy
fires. Response shapes mirror backend/.../scoring/schemas/workflow_io.py
character-for-character (snake_case keys, UUIDs as strings).

The persist-final-score body is the verbatim FinalScoreInputs JSON
returned by score-judges-and-aggregate -- backend inlines the fields
at the body root, so no `score_inputs` wrapper goes on the wire.

Existing Phase 1 helpers (getHealth, echoAttempt) retained for ad-hoc
smoke checks post-deploy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the Phase 1 2-step scaffold (ping_health + echo_attempt) with
the real 6-step durable pipeline that drives FastAPI's 9-step scoring
engine through the /internal/workflow/* surface.

Step mapping (scoring.ts):

  1. fetch                       -> WorkflowFetchResponse
  2. integrity                   -> WorkflowIntegrityResponse
  3. score-judges-and-aggregate -> WorkflowScoreAndAggregateResponse (FinalScoreInputs)
  4. persist-final-score        -> WorkflowPersistFinalScoreResponse (consumes step 3's body)
  5. apply-rating               -> WorkflowApplyRatingResponse
  6. finalize                   -> WorkflowFinalizeResponse

Steps use the `workflow` SDK's directive API (`"use step"` /
`"use workflow"`) so the runtime checkpoints between each `await` and
retries failed steps with exponential backoff. The trigger endpoint
now calls `start(scoringWorkflow, [payload])` from `workflow/api` to
enqueue the run rather than executing inline.

Test strategy decision: skip vitest. The TS surface is small (six
thin wrappers + one orchestrator), the wire contract is end-to-end
covered by the backend's tests/test_internal_workflow_phase3_endpoints.py,
and adding a vitest harness with ESM + `.js` extension source-import
quirks would exceed the 15-minute time budget. The gate is `npm run
type-check` (clean) + code review.

README updated to document the six steps, the redeploy flow (additive
vs breaking contract changes, HMAC rotation), and the smoke-test path.
package-lock.json reshuffled by `npm install` on a fresh tree -- no
functional dep changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… internal endpoints

Brings frontend-v2's lib/api/generated.ts in sync with the backend OpenAPI schema
after Stream A added:
- /v1/me/dashboard aggregator (Task A14)

(Internal /workflow/* endpoints are include_in_schema=False so they don't show
up in the OpenAPI document, by design.)

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md (Task E1)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the "big door" composite used on /arena: one per arena (profile,
professional, technical). Renders a clickable Card with the arena
accent CSS variable used for the border + a subtle linear-gradient
tint. Whole card is button-like, keyboard accessible (Enter + Space
via native button semantics).

The `comingSoon` variant disables clicks, dims the card, and surfaces
a "Coming soon" badge. Designed so the arena page can show Phase 3's
profile arena with cv_battle available while professional/technical
remain placeholders.

Built on the Phase 2 shadcn `Card` primitive and the OKLCH accent
tokens (`--accent-profile`, `--accent-professional`,
`--accent-technical`). Uses `color-mix(in oklch, ...)` for the tint
so the gradient stays inside the design token space.

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
Spec: docs/superpowers/specs/2026-05-15-phase3-arena-hub-cv-battle-design.md §5.2

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Renders one card per mechanic inside an arena door's shelf. Surfaces
the four pieces of info from master plan §3.5.4: difficulty (pill
with semantic colour), time limit (or "Async" when null), mode
(practice/unranked/ranked badge), and the user's current rating in
that mechanic.

Rating rail uses RatingTooltip from Phase 2 to surface the
uncertainty band (±80 Elo, the typical Glicko-2 RD for an established
rating; the real per-mechanic RD will land via the dashboard API).
When the user has not yet attempted the mechanic, the rating is
replaced with a dashed `—` placeholder marked as role="img" with an
"No rating yet" aria-label so axe + screen readers stay happy.

A `comingSoon` prop dims the card and swaps the "Start" CTA for a
disabled "Coming soon" button. The Start CTA's aria-label always
names the mechanic ("Start CV Battle") so it remains useful when
shelves contain many cards.

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
Spec: docs/superpowers/specs/2026-05-15-phase3-arena-hub-cv-battle-design.md §5.2

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Top-of-replay-page hero showing aggregated score / 100, confidence
band chip (high/medium/low with semantic colours + tooltip), an
optional disagreement warning chip when (1 - mean Kendall tau) > 0.35
per ADR 0012 §MetaJudge, optional pairwise winrate, judge count,
formatted timestamp, and arena accent border.

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
Spec: docs/superpowers/specs/2026-05-15-phase3-arena-hub-cv-battle-design.md §3.5.6 + §5.2
Tests: 11 new vitest cases (rendering, threshold behaviour,
disagreement/kendallTau alias, axe pass).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the global top-bar shown across the (app) group: Ascendra
wordmark, primary nav (Dashboard / Arena / Skill tree / Quests /
Leaderboards) with arena-cyan active underline, and the user
avatar dropdown wiring Profile / Settings / Sign out.

Also adds the shadcn `dropdown-menu` and `avatar` primitives
needed by the composite. Sign-out invokes the prop callback so
both server actions (`signOutAction`) and inline handlers can be
mounted by the (app) layout in Task D5.

Tests cover: wordmark, every nav link's href, aria-current for
both exact and nested routes, dropdown open + sign-out callback,
Profile / Settings menu items, email-initial fallback, anonymous
state (Sign in link), and axe.

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
One card per JudgeResult on the replay page. Header shows the judge
type label + model/version. Score is the large tabular number,
confidence is a small uppercase pill. Each category in
categoryScores renders as a labelled Progress bar. Evidence quotes
are clickable buttons that call onEvidenceClick(quote) for the
parent to scroll the submission to that span. The explanation is
inside a collapsible <details>.

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
Spec: docs/superpowers/specs/2026-05-15-phase3-arena-hub-cv-battle-design.md §3.5.6 + §5.2
Tests: 8 new vitest cases (header, score, categories, evidence
clicks fire callback, collapsible explanation, empty-state guards,
axe pass).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Full challenge-room shell for cv_battle. Two-column layout: role brief
on the left (rendered as preformatted text — Phase 3 placeholder for
the eventual TipTap viewer), full-height textarea on the right.

Behaviour per master plan §3.5.5 and the Phase 3 sub-plan:

- Character counter renders when `characterLimit` is set; flips to a
  warning colour at ≥90% capacity. `aria-live="polite"` so screen
  readers learn when the user is approaching the cap.
- Countdown timer renders when `timeLimitSeconds` is set. Below 30s
  remaining the ring/text switches to the `--warning` token and
  becomes a polite live region. At 0 the component force-calls
  `onSubmit` with the current draft.
- Autosave debounces 5s after the draft last changed, then fires
  `onAutosave(draft)`. The component does not own storage — the page
  threads `onAutosave` to whatever persistence layer the route uses.
- Submit is disabled until the trimmed draft is ≥50 chars (and ≤ any
  character limit). Clicking Submit opens a shadcn `Dialog` with
  "Are you sure? You can't edit after submitting." Confirming calls
  `onSubmit(draft)`; cancelling re-opens editing.
- `initialDraft` supports resume-from-autosave.

A `submittedRef` guards against double-submission (e.g. user clicks
Confirm while the timer hits zero on the same tick).

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
Spec: docs/superpowers/specs/2026-05-15-phase3-arena-hub-cv-battle-design.md §5.2

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Consent-gated right-side shadcn Sheet for the replay page that
shows the user's submission next to a recruiter-anchored exemplar
(strong / average / weak / edge tier). When consentGranted=false,
renders a consent-reminder block linking back to the consent
settings page. When the anchor is null, renders an empty state.
Anchor rationale renders in a subtle box beneath the anchor pane.

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
Spec: docs/superpowers/specs/2026-05-15-phase3-arena-hub-cv-battle-design.md §3.5.6 + §5.2
Tests: 7 new vitest cases (panes render, rationale renders, consent
reminder branch, empty-state branch, close button fires
onOpenChange(false), axe pass in both consent states).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
React 19's `react-hooks/refs` rule rejects `someRef.current = value`
during the render phase. Three refs in CvBattleRoom were being
synced this way to stay current for the autosave + countdown timer
effects without forcing re-subscribes.

Switch the sync into a `useLayoutEffect` so refs are still up-to-date
before any subsequent effect or event handler runs, but the lint rule
is satisfied. Also inline the submit handler's `draft` access via the
closure (it's reactive, the timer's `draftRef.current` still resolves
via the layout-effect update).

All 12 cv-battle-room tests still pass. `npm run lint` and
`npm run build` clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Repair-path list on the replay page. Each leaf renders as a card
with name, description, mastery progress bar (or "Not attempted
yet" when masteryEma is null), and a primary "Drill now" CTA when
drillTemplateId is set (links to /arena/cv-battle/play?template=…)
or a fallback "View in skill tree" link via skillTreeUrl. Renders
a friendly empty state when nodes is [].

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
Spec: docs/superpowers/specs/2026-05-15-phase3-arena-hub-cv-battle-design.md §3.5.6 + §5.2
Tests: 7 new vitest cases (cards render, drill href correct, skill
tree fallback, mastery percentage rendering, not-attempted marker,
empty state, axe pass).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… Query hooks (Task E2)

Wires the three new Phase 3 sub-plan #1 reads to TanStack Query
following the MVP API-layer pattern:

- `lib/api/dashboard.ts` → `GET /api/v1/me/dashboard` (the new
  aggregator endpoint from Task A14). Returns the typed
  `DashboardSnapshot` shape; throws with the backend `code` on
  4xx so query hooks surface a stable error.
- `lib/api/arena.ts` → wraps `GET /api/v1/challenge-templates`
  and projects each row into a UI-friendly `ArenaMechanic`. Also
  exposes `COMING_SOON_MECHANICS` placeholders for behavioural /
  mental-maths / leetcode so `/arena` can render all three doors
  before sub-plans #2 + #3 ship. Stubs are filtered against live
  `mechanic_key`s so the placeholders disappear automatically as
  templates land.
- `lib/api/replays.ts` → `GET /api/v1/replays/{id}` returning
  `ReplayDetailResponse`.

Adds matching TanStack Query hooks in `lib/hooks/` plus a
`useSupabaseSession()` shim over `useAuth()` so hooks can pull
just the bearer token. Each hook is `enabled` only when the
Supabase session has hydrated, preventing 401 thrash on first
paint.

To support client-side use (the existing `api()` reads cookies via
the server-only Supabase client), `lib/api/client.ts` gains two
additive typed wrappers — `apiGet<T>` and `apiPost<T>` — that take
the bearer token explicitly and return the same `{data, error}`
envelope. The server-side `api()` stays unchanged.

Tests added (29 total): 9 extending `api-client.test.ts` for the
new wrappers, 4 for dashboard, 7 for arena, 6 for replays, plus 5
hook integration tests that drive a real `QueryClientProvider`.

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shadcn Dialog for the consent-gated share flow on the replay page.
When consentGranted=false, renders a checkbox-confirm step
explaining that only the anonymisedHandle (e.g. "Challenger #4f2a")
appears publicly; ticking the box calls onConsentChange(true).
When consentGranted=true, renders the readonly public URL
(/replay/{attemptId}/share) plus a Copy link button that uses
navigator.clipboard.writeText (feature-detected). Cancel closes
the dialog via onOpenChange(false). Copy state self-resets after
1.5s with cleanup on unmount.

Plan: docs/superpowers/plans/2026-05-15-phase3-arena-hub-cv-battle.md
Spec: docs/superpowers/specs/2026-05-15-phase3-arena-hub-cv-battle-design.md §3.5.6 + §5.2
Tests: 7 new vitest cases (consent confirm step, onConsentChange
fires on tick, public URL render, clipboard copy with mocked
navigator.clipboard, cancel fires onOpenChange(false), axe pass
in both states).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
TahaKhanM and others added 28 commits May 15, 2026 16:56
… /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>
…Judge + SandboxRunner)

Spec at docs/superpowers/specs/2026-05-15-phase3-leetcode-sandbox-design.md;
TDD plan at docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md.

Scope:
- SandboxRunner Protocol + StubSandboxRunner + LocalSubprocessSandboxRunner
  (dev-only) + factory. Real Vercel Sandbox provider deferred to a follow-up
  per ADR 0005.
- Real CodeExecJudge (replaces Phase 1 stub).
- leetcode_medium mechanic + Two Sum template + hidden_test_harness.
- Public-template-read sanitization extension for hidden_test_harness.
- LeetcodeRoom composite (plain textarea + monospace; Monaco deferred to Phase 8).
- Page dispatcher + COMING_SOON cleanup (now empty — all 4 Phase 3 mechanics live).

ADRs governing: 0005, 0006, 0008, 0011, 0012. No new ADRs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 3 sub-plan #3 / spec §4.1: two-column challenge room for
`leetcode_medium`. Problem statement (rendered as `<pre>` for Phase 3)
on the left; mono-fonted `<textarea>` on the right. Tab inserts 4
spaces at the cursor; submit opens a shadcn `Dialog` confirmation; the
confirmation fires `onSubmit({source_code, language: "python"})`. The
disabled language selector is wired so we can ship multi-language
support later without restructuring the header.

Submit is gated on ≥ 20 chars of trimmed source so a user can't fire
the judge on an empty buffer (the deterministic stub would record
`passed=0` and still cost an attempt). A countdown is rendered when
the page passes a `timeLimitSeconds`; on expiry the room force-submits
the current draft mirroring `CvBattleRoom`'s timeout path.

Monaco editor + Markdown rendering for the prompt are deferred to
Phase 8 polish per spec §6.

Tests: 10 vitest cases covering render, language pin, submit gating,
dialog confirm + cancel, Tab indentation, countdown presence /
absence, axe pass.

Plan: docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…Task A1)

Phase 3 sub-plan #3 lands the SandboxRunner layer that the real
CodeExecJudge will call against. Tiny Protocol (one ``run`` method +
``name`` discriminator) with two implementations:

- StubSandboxRunner — deterministic, never spawns a subprocess. Reads
  the harness for ``_T = [...]`` to count tests and the first
  ``from solution import <name>`` line to extract the expected
  function name; reports ``passed=total`` iff the user defines that
  function.
- LocalSubprocessSandboxRunner — DEV-ONLY. Real subprocess execution
  with Unix ``resource.setrlimit`` caps on CPU + address-space.
  Module docstring carries a security warning; the factory gates it
  behind ``SANDBOX_PROVIDER=local``.

Factory ``get_default_sandbox_runner()`` defaults to the stub;
unknown providers log a warning and fall back to the stub.

Re-exports surface ``SandboxRunner`` / ``SandboxRequest`` /
``SandboxResult`` / ``StubSandboxRunner`` / ``LocalSubprocessSandboxRunner``
/ ``get_default_sandbox_runner`` via ``scoring.ports`` so downstream
contexts can wire it without crossing ADR 0008 boundaries.

Plan: docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Five TDD tests covering the dev-only subprocess sandbox runner:

- known-good solution against a Two-Sum harness → 3/3 pass
- partial solution → faithful 1/3 pass count
- syntax error → failure_message surfaces SyntaxError
- tight infinite loop → timeout or CPU-rlimit kill, zero passed
- missing function (ImportError in harness) → zero passed

The runner itself was implemented as part of Task A1 (so the factory
could reference it). This commit lands its dedicated test module,
gated POSIX-only via ``pytest.mark.skipif(os.name == 'nt')``.

Plan: docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replaces the Phase 1 stub with a real implementation that calls into
the SandboxRunner layer (ADR 0005). The judge:

- Reads ``source_code`` + ``language`` from submission_payload and
  ``hidden_test_harness`` from rubric_definition.
- Calls the injected SandboxRunner (defaults to the factory's
  StubSandboxRunner; production swaps via env).
- Reports ``score = passed/total*100`` rounded to 2dp; confidence
  0.95 when ≥1 test ran, 0.0 otherwise.
- Surfaces sandbox provenance + telemetry on ``raw_payload`` so
  replay artifacts can audit which runner produced the row.

Edge cases:
- Missing source_code → zero-score, zero-confidence skip draft.
- Missing harness → zero-score, zero-confidence skip draft.
- Sandbox reports total_tests=0 → zero-score, zero-confidence with
  failure_message preserved.

Removes ``tests/test_code_exec_judge_stub.py`` (superseded by the
9-test ``tests/test_code_exec_judge.py``).

Plan: docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…+ empty COMING_SOON (Task B2)

Phase 3 sub-plan #3 dispatcher wiring:

- Extends the `/arena/[mechanic]/play` switch with a `leetcode-medium`
  arm that mounts `<LeetcodeRoom>`. Reuses the shared helpers
  (`useDomainProfileQuery`, `useCreateAttemptMutation`,
  `useFullTemplateQuery`, `deriveEffectiveMode`) so the flow is
  identical to behavioural-duel + mental-maths-blitz — only the
  submission payload shape differs (`{source_code, language}`
  forwarded verbatim).
- `extractLeetcodePrompt` reads `prompt_text` (falling back to
  legacy `prompt` then `description`); `extractLeetcodeStarter`
  reads `rubric_definition.starter_code`. The seed in Task A4 is
  the canonical source of both fields; Task A5 strips
  `hidden_test_harness` from the public template read so this is
  safe to consume client-side.
- Empties `COMING_SOON_MECHANICS` — every Phase 3 mechanic now
  ships live. Updates the doc-comment + the `ComingSoonPlaceholder`
  blurb so the placeholder copy stays accurate (now points at
  Phase 4+ for the remaining arenas).

Test updates:
- `tests/lib/api/arena.test.ts`: `COMING_SOON_MECHANICS` is empty;
  the snapshot's `comingSoon` array is empty by default.
- `tests/lib/hooks/use-arena-mechanics.test.tsx`: same assertion
  shift — coming-soon is empty until Phase 4.
- `tests/pages/arena-mechanic-play.test.tsx`: replaces the
  `leetcode-medium`-as-unknown-mechanic test with a
  `totally-unknown-mechanic` case (the URL segment is now live);
  adds two new tests under `leetcode-medium happy path` —
  render + submit-shape assertion.

326 vitest tests pass; lint clean; production build clean.

Plan: docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… A4)

Adds the ``leetcode_medium`` mechanic + a default "Two Sum" template
to the seed catalogue. The mechanic ships:

- Technical arena, no domain pinning (relevant for SWE, Quant, Quant
  Dev pathways).
- ``requires_sandbox=True`` so dispatchers route through the
  SandboxRunner layer.
- 40-min time limit (per master plan §2.6).
- Single ``code_exec`` judge + meta in the default judge mix; no LLM.

The Two Sum template carries:

- Markdown problem statement (kept on ``prompt``).
- Starter Python function stub (kept on ``rubric.starter_code``).
- Five hidden tests via ``rubric.hidden_test_harness`` — uses the
  deterministic ``RESULT:PASS:<n>:TOTAL:<m>`` protocol the sandbox
  runners parse.

Enum extensions (all reuse the existing VARCHAR(N) + CHECK pattern;
no migration needed since ``native_enum=False``):

- ``ChallengeType.LEETCODE`` — distinct from TIMED_DRILL so the
  frontend dispatcher routes to the LeetcodeRoom composite.
- ``InputType.CODE`` — distinct from TEXT so analytics + the public
  read API can branch on the mechanic.
- ``OutputType.CODE_SUBMISSION`` — same rationale.

We reuse ``ScoringMode.DETERMINISTIC`` rather than adding a new
``SANDBOX_EXEC`` value (the spec says either is acceptable; reuse
keeps the enum + migration surface lean).

Plan: docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… (Task A5)

Extends ``_sanitize_rubric_for_public_read`` (introduced in sub-plan
#2 for ``correct_answers``) to also strip ``hidden_test_harness`` from
leetcode_medium rubrics on the public read path. The judge / scoring
pipeline keeps reading templates via the ORM directly, so
``CodeExecJudge`` continues to see the full harness.

Also widens ``RubricDefinition`` (Pydantic schema) to expose
``starter_code`` + ``language`` so the leetcode_medium room composite
can seed the editor — these two fields are intentionally public
(unlike the harness) so the frontend knows the function signature
to scaffold.

Three new tests:

- Unit test on the sanitizer helper: confirms hidden_test_harness is
  stripped while starter_code + language + categories survive.
- API test on the single-template read endpoint: leetcode_medium
  template via GET /api/v1/challenge-templates/{id} has no harness.
- API test on the list endpoint: same guarantee on list reads.
- A regression test that the ORM-backed read (used by the scoring
  pipeline) still sees the harness.

Plan: docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wire the leetcode_medium mechanic + Two Sum template into the
conftest-driven seed path so every test gets a sandbox-graded
template fixture without an extra setup call.

The bootstrap loads the seed script via the same ``_load_script_module``
helper sub-plan #2 uses, then upserts via ``seed_leetcode_medium``.
The template is linked to three existing technical skill leaves:

- ``debugging-patterns`` (emphasis 1.2 — primary)
- ``problem-decomposition`` (emphasis 1.0)
- ``system-design-thinking`` (emphasis 0.6 — light)

Two new test assertions:

- ``leetcode_medium`` mechanic + template exist after the fixture
  runs, with ``requires_sandbox=True`` and the harness intact via
  the ORM read path.
- The template is linked to the three SWE-flavoured technical skill
  nodes above.

Plan: docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…-plan #3 (Task C2)

- Root CLAUDE.md: bump frontend-v2 surface to include leetcode-medium.
- frontend-v2/CLAUDE.md: rename section to "Phase 3 sub-plans #1 + #2 + #3 additions";
  add leetcode-room.tsx composite; note that COMING_SOON_MECHANICS is now empty;
  update the play-page dispatcher row to mention {source_code, language} payload shape.
- backend/CLAUDE.md: extend the sanitization section to include hidden_test_harness;
  add a Sandbox runners subsection pointing at services/sandbox/.
- Master plan §9 Phase 3: strike through with completion note + all three PR links.

Plan: docs/superpowers/plans/2026-05-15-phase3-leetcode-sandbox.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spec at docs/superpowers/specs/2026-05-15-phase4-swe-wave-1-design.md;
TDD plan at docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md.

Scope: 4 SWE mechanics (leetcode_easy_drill, leetcode_hard_battle,
behavioural_lp_drill, system_design_hl) + Amazon Internship Superday
boss-battle pack + 8+ calibration anchors + skill-tree leaves under
swe_fundamentals + cohort taxonomy validation + new SystemDesignRoom
frontend composite + page dispatcher updates.

All four mechanics reuse Phase 3 infrastructure (CodeExecJudge, SandboxRunner,
RubricLLMJudge, BehaviouralDuelRoom). Only SystemDesignRoom is genuinely new.

ADRs governing: 0005, 0006, 0008, 0011, 0012. No new ADRs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the 2-column system-design room: prompt + rubric-hint cards on the
left (40%), large textarea + character counter + countdown on the right
(60%). Submit gated at >=200 chars; opens shadcn Dialog with the
"Hidden rubric judges will score it." confirmation copy. Tab inserts 2
spaces. Force-submits whatever the user has when the 45-min countdown
expires (mirrors CvBattleRoom / LeetcodeRoom). 8 vitest cases cover
render, character-gate, confirm + cancel, counters, rubric-hint
conditional, and axe.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three easy LeetCode problems (reverse_string, is_palindrome, two_sum)
combined into a single 25-minute drill. Reuses CodeExecJudge + sandbox
from Phase 3 sub-plan #3; harness imports all three function names and
emits the RESULT:PASS:N:TOTAL:M protocol.

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
"Trapping Rain Water" hard-tier problem, 45-minute battle. Reuses the
CodeExecJudge + sandbox path from Phase 3 sub-plan #3. Six hidden test
cases including edge cases (empty + single-bar arrays).

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…k A3)

Five Amazon LP behavioural questions in a 15-minute drill (5x3 min).
Mirrors behavioural_duel's judge-mix shape (2 rubric_llm + 1 pairwise
vs STRONG anchor). Six rubric categories tuned to LP signals:
star_structure, specificity, ownership, customer_obsession,
bias_for_action, learning. Three STRONG anchors stitch five LP
answers with `\n\n---\n\n` so a single rubric pass sees the full set.

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…chanics (Task B2)

Adds dispatch cases for `leetcode-easy-drill`, `leetcode-hard-battle`,
`behavioural-lp-drill`, and `system-design-hl`. The three reuse-existing-room
mechanics parameterize the existing leetcode/behavioural play components on
`mechanicKey` + `urlSegment` + display label so we avoid duplicating ~150
LoC per variant — `LeetcodeRoom` and `BehaviouralDuelRoom` already cover
their full UX. `system-design-hl` ships a dedicated `SystemDesignHlPlay`
that submits `{source_text}` and extracts rubric hints from
`template.rubric_definition.categories` (each category becomes a
`{label, description}` card with comma-joined focus_keywords).

5 new vitest cases cover: render-mounted smoke for each of the 4 new
mechanics + full submit-payload assertion for system-design-hl. Total
vitest grows 334 -> 339.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Long-form system-design walkthrough mechanic for the Twitter feed
prompt. 45-minute textual response scored by RubricLLMJudge against
a six-category rubric (requirements / architecture / data model /
scalability / trade-offs / communication, weights sum to 1.0).

Dev judge mix is 2x rubric_llm Gemini + 1x pairwise vs STRONG anchor;
production swaps to Claude. Calibration anchor set: 3 STRONG + 2
AVERAGE, each a 300-500 word coherent walkthrough.

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…sk A5)

BenchmarkPack combining leetcode_medium (Phase 3) +
behavioural_lp_drill (Task A3) + system_design_hl (Task A4) into a
three-stage SWE Superday simulation. Pack is BOSS difficulty,
elo_eligible=False (benchmark packs are intentionally non-Elo in the
MVP), application_cycle=INTERNSHIP, pathway=SOFTWARE_ENGINEERING.

Adapted to the real BenchmarkPack model (slug/title rather than
the spec's key/name; M2M template_links rather than top-level
template_ids; no readiness_thresholds column — the spec wording is
approximate, per ADR 0008 we adapt to the model that already
exists).

Pack guard: upsert_pack raises RuntimeError if any of the three
required templates has not been seeded yet. This protects the
seed_reference_data ordering once Task A8 wires the mechanic seeds
in.

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…es (Task A6)

Add a new `swe-fundamentals` BRANCH node + four LEAF nodes
(`algorithms`, `data-structures`, `system-design-foundations`,
`code-quality`) under the Technical trunk. Dependencies:
swe-fundamentals → problem-decomposition; each leaf →
swe-fundamentals.

Ship `_link_phase4_templates_to_skill_nodes` to wire the four
Phase 4 mechanic templates into the new + existing leaves:
 - leetcode_easy_drill → algorithms, data-structures
 - leetcode_hard_battle → algorithms, data-structures
 - behavioural_lp_drill → existing Professional leaves
   (star-storytelling, stakeholder-judgement, leadership-framing).
   No new behavioural-communication leaf in this sub-plan.
 - system_design_hl → system-design-foundations + the existing
   system-design-thinking branch.

Mirrors Phase 3 sub-plan #2 `_link_phase3_templates_to_skill_nodes`
(silently skips when templates are missing, so the helper can be
called before the mechanic seeds run). The wire-up into
`seed_reference_data` lands in Task A8.

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Verifies derive_default_cohort_key produces the canonical
`pathway:cycle:level` shape for the SWE summer-internship /
pre-final-year cohort, and that the format generalises across all
seven pathways.

The spec mentions SUMMER_INTERNSHIP / UNDERGRAD_PENULTIMATE enum
values; the actual ApplicationCycle / ExperienceLevel enums use
INTERNSHIP / DEVELOPING. Per ADR 0008 we test against the enum that
exists rather than introducing a migration just to match the spec
wording.

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add _seed_phase4_mechanics(db) to bootstrap.py that drives the four
Phase 4 mechanic seeds + the Amazon Internship Superday boss-battle
pack, then calls _link_phase4_templates_to_skill_nodes. Mechanic seeds
run before the boss pack because the pack depends on three mechanic
templates (leetcode_medium / behavioural_lp_drill / system_design_hl).

Test surface:
 - Extend test_seed_reference_data_phase3.py with 5 new assertions
   covering the Phase 4 mechanics + the Amazon Superday pack +
   the Phase 4 skill-link wiring.
 - Update per-mechanic anchor tests (behavioural_lp_drill,
   system_design_hl, amazon_superday) so the anchor / link
   "expected new=N" counts reflect that the conftest fixture already
   pre-seeded them via seed_reference_data (mirrors the
   behavioural_duel test pattern from Phase 3 sub-plan #2).
 - test_link_helper_silently_skips_missing_templates simulates the
   partial-state case by deleting one template first.
 - test_seed_raises_when_dependencies_missing uses the same delete-
   first technique to verify the boss pack still guards its FK
   dependencies.

Also: refactor the leetcode_easy_drill harness body to keep lines
under 100 columns (ruff clean).

Trifecta clean: 351 backend tests pass (302 baseline + 49 new); ruff
clean; context-boundary clean.

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ve 1) (Task C2)

- Root CLAUDE.md: bump frontend-v2 mechanic count to 8 live (4 Phase 3 + 4 Phase 4 SWE).
- Master plan §9 Phase 4: mark SWE Wave-1 subset implementation complete with PR #15
  reference; note that remaining SWE mechanics (debugging_drill, code_review_drill,
  system_design_deep_dive, leetcode_medium_battle pairwise) land in later sub-plans
  or Phase 6.

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Phase 0 smoke spec asserted on the placeholder "Ascendra v2"
heading. PR #11 replaced the placeholder with the marketing home
(Hero + PathwayGrid + ...), so the heading no longer exists. The
recovery PR for Phase 3 + Phase 4 SWE Wave 1 (PR #16) inherited
this stale assertion since it forked off the same lineage.

Update the spec to assert the actual H1 in `components/marketing/hero.tsx`:
"The rating that earns you the offer."

Verified locally: 1 passed (4.0s).

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md (recovery follow-up)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 3 added several backend schema changes that were never reflected
in the committed `generated.ts` files:

- `ChallengeType` gained `mental_maths` + `leetcode` variants.
- `InputType` gained `long_text`, `numeric_streak`, `code`.
- `OutputType` gained `structured`, `code_submission`.
- `ScoringMode` gained `judge_llm`, `deterministic`.
- `RubricDefinition` gained `language`, `questions`, `starter_code`, `time_bonus_seconds`.
- New `RubricQuestion` schema (Phase 3 sub-plan #2 mental_maths).
- `/api/v1/me/dashboard` endpoint added (Phase 3 sub-plan #1).
- Plus many smaller field additions across replay / template payloads.

Detected by the recovery PR (#16) codegen-diff CI check. Regenerated via
`scripts/codegen-openapi.sh` against the current backend `openapi.json`.

Plan: docs/superpowers/plans/2026-05-15-phase4-swe-wave-1.md (recovery follow-up)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@TahaKhanM
TahaKhanM merged commit 9f61191 into main May 15, 2026
6 checks passed
@TahaKhanM
TahaKhanM deleted the phase-4-swe-wave-1 branch July 3, 2026 05:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant