Add report practice focus selection

HS
11h ago
+2659-199

Problem and behavior

Reports already suggest concrete items under Practice next, but the candidate could not choose one of those items to carry into the next interview. The lobby instead derived its practice focus automatically from report history.

This adds a Practice this action to each valid improvement-plan item. Choosing one carries that exact phase, weakness, drill, and success criterion into the lobby and gives it precedence over the automatic carry-forward focus for the next interview. If the candidate does not choose an item, the existing automatic behavior is unchanged.

The selection changes only the practice focus. It does not change the selected problem, difficulty, interview duration, format, or editor settings, and the report's durationMin remains guidance for the improvement item rather than becoming the next interview's duration. Sharing the focus with Jim also remains a separate opt-in and is unchecked when a focus is selected.

Approach

The selected improvement is kept in session storage as selectedPracticeFocus. It survives lobby reloads and takes precedence over practiceFocus(reports) until the candidate starts the next interview, at which point the selection is consumed. If no explicit selection exists, the existing automatic carry-forward path is unchanged.

Only phase, weakness, drill, and successCriterion are carried. The selection also retains its source report id so deleting an unrelated or already-missing report does not discard it, while deleting its source report or all saved history does.

The same selection path is available from saved lobby reports, the completed interview report, and replay reports. Interview navigation stores the selection only after the existing leave safeguards permit navigation, and storage failures keep the candidate on the report with feedback instead of silently navigating with a lost selection.

The selection is also bound to the account that created it. /api/session exposes the browser-facing owner as user.id, while /api/reports and signed-in /api/token responses expose the same value as accountId. These are opaque values derived from the account's stable identity rather than the recyclable sequential users.id database key. Temporary-account cleanup therefore cannot transfer an old browser owner to a new account even if SQLite reuses its row id, while the same GitHub account retains a stable owner across sign-ins.

Before Start hands a selected weakness to the interview, the lobby re-reads /api/session and drops the focus if the account owner changed. Sharing remains a separate opt-in, and its checkbox is checked again immediately before the handoff is stored.

The report HTML gains the action, while Markdown report output remains unchanged.

Validation

./scripts/test.sh passes on the final head: 2971 tests, 2944 passed, 0 failed, and 27 environment-dependent tests skipped.

Browser regression coverage checks the exact selected improvement, persistence across lobby reloads and consumption on Start, automatic fallback, the unchecked sharing control, source-report deletion without clearing selections from unrelated or already-missing reports, persisted-page reconciliation, interview leave cancellation and duplicate-leave protection, storage-failure feedback, replay selection, cross-account sharing protection, last-moment Share consent, and Strict report selection. The lobby test also verifies that choosing Practice this does not change the problem, difficulty, duration, interview format, or editor settings.

HTTP regression coverage verifies that /api/session, /api/reports, and signed-in /api/token expose the same opaque owner for an account, guest token responses expose no account owner, and cleaning up a temporary account does not recycle its browser owner when SQLite later reuses the same users.id.

The required interactive review for the 2846-line pull-request diff was completed on the final head. No live provider behavior or desktop-specific behavior was exercised; this change is limited to the existing web report and lobby practice-focus flow.

Screenshots

Practice this in the report

螢幕擷取畫面 2026-11-05 150455 Each improvement item exposes its own **Practice this** action.

Selected focus in the lobby

螢幕擷取畫面 2026-11-05 150628 The selected item is shown in the existing lobby focus area, while **Share this focus with Jim** remains unchecked.

Markdown report unchanged

螢幕擷取畫面 2026-11-05 150715 The Markdown report remains unchanged and does not include the interactive **Practice this** action.

Close #580


Summary by cubic

Adds a Practice this action to each report improvement item so a candidate can carry that exact phase, weakness, drill, and success criterion into the lobby as the practice focus. A selected focus overrides the automatic carry-forward for the next interview; without a selection, existing automatic behavior is unchanged.

  • The selection only changes the practice focus, never the problem, difficulty, duration, format, or editor settings, and is stored in session storage once the existing leave safeguards pass.
  • The focus is bound to its owner (a signed-in account id, or device for signed-out and guest sessions); switching accounts, signing out, deleting the source report, or starting the interview clears it.
  • The action appears in completed, saved, and replay reports; Markdown output stays unchanged.
  • Sharing the focus with Jim remains a separate opt-in and clears when a focus is selected.
  • Server responses (/api/session, /api/reports, /api/token) now include a signed accountId so the lobby discards report rows that belong to another account.