Skip to content

Add report practice focus selection - #593

Open
Hsieh-HC wants to merge 1 commit into
sysprog21:mainfrom
Hsieh-HC:report-practice-focus
Open

Hsieh-HC wants to merge 1 commit into
sysprog21:mainfrom
Hsieh-HC:report-practice-focus

Conversation

@Hsieh-HC

@Hsieh-HC Hsieh-HC commented Nov 5, 2026 •

Copy link
Copy Markdown
Contributor

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.

Written for commit db3562f. Summary will update on new commits.

View guided diff

@Hsieh-HC Hsieh-HC changed the title Report practice focus Add report practice focus selection Nov 5, 2026
cubic-dev-ai[bot]

This comment was marked as resolved.

@jserv jserv added the explained label Nov 5, 2026
Comment thread web/app.js Resolved
Comment thread web/app.js Resolved
Comment thread web/interview.js Resolved
Comment thread web/problem-picker.js Resolved
Comment thread web/render.js Resolved
jserv

This comment was marked as outdated.

@bangyou0912 bangyou0912 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two questions about undoing a selection and confirming it, and one about what the lobby test can tell apart.

Comment thread web/problem-picker.js Resolved
Comment thread tests/browser/lobby.test.js Resolved
Comment thread web/app.js Resolved
Comment thread web/interview.js Resolved
Comment thread web/app.js Resolved
Comment thread web/styles.css Resolved
@jserv

jserv commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Some review comments on this pull request are not settled yet. Please refine the change per the review comments listed below, reply on each thread with what you changed or why you did not, and mark each thread resolved yourself once it is settled (Resolve conversation, at the bottom of the thread). The pull request stays blocked while review threads are open.

Not addressed at the current head:

Checked at 83c1742.

@Hsieh-HC
Hsieh-HC force-pushed the report-practice-focus branch from 83c1742 to c5ad1b7 Compare November 6, 2026 16:27

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 24 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread web/app.js Resolved
Comment thread web/interview.js Resolved
Comment thread src/web/auth.rs Resolved
Comment thread web/app.js Resolved
Comment thread web/app.js Resolved
Comment thread web/interview.js Resolved
Comment thread web/problem-picker.js Resolved
Comment thread web/problem-picker.js Resolved
jserv

This comment was marked as outdated.

Comment thread web/app.js Resolved
Comment thread web/problem-picker.js Resolved
@jserv

jserv commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Some review comments on this pull request are not settled yet. Please refine the change per the review comments listed below, reply on each thread with what you changed or why you did not, and mark each thread resolved yourself once it is settled (Resolve conversation, at the bottom of the thread). The pull request stays blocked while review threads are open.

Not addressed at the current head:

Checked at c5ad1b7.

@Hsieh-HC
Hsieh-HC force-pushed the report-practice-focus branch from c5ad1b7 to e052d08 Compare November 7, 2026 07:14
cubic-dev-ai[bot]

This comment was marked as resolved.

jserv

This comment was marked as outdated.

Carry selected report improvements safely through interviews and
replay while preserving account ownership and lobby settings.

Change-Id: I974546bfeb9ffc69db5be0bab32220f46b647727
@Hsieh-HC
Hsieh-HC force-pushed the report-practice-focus branch from e052d08 to db3562f Compare November 7, 2026 08:31
@jserv

jserv commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

The interactive-review check changed in #610: the explained label no longer passes it, and this pull request is over the large-change thresholds, so its next run needs a signed record of the interactive review.

  1. Once: set up a signing key, as "Before your first large change" in CONTRIBUTING.md lists.
  2. Rebase this branch onto main; the pre-push hook that signs and sends the record is there.
  3. Run /codetrial-review on the branch and push. If the branch did not change, send the record with sh scripts/git-pre-push.sh --publish-review <fork-remote> [<branch>], then close and reopen this pull request.

Each refusal and its fix: https://github.com/sysprog21/codetrial/blob/main/docs/large-change-explanation.md#troubleshooting

@jserv jserv removed the explained label Nov 7, 2026

@jserv jserv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebase the current branch onto the upstream default branch and resolve any conflicts. Run /codetrial-review in AI agents (use $codetrial-review in Codex) and resolve all identified issues. Rework the series into minimal, logically coherent commits, squash closely related commits, and ensure all commit messages follow the project’s rules.

Comment thread web/app.js
try {
const currentSession = await fetchJson("/api/session");
const currentOwner = practiceFocusOwner(currentSession);
if (!currentOwner || currentOwner !== selectedPracticeFocusOwner) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check also runs for the automatic carry-forward focus, which has no owner of its own, so it changes the existing share path. Signed out with login required: tick Share this focus with Jim, type a GitHub username and press Start. recordGitHubLogin signs the page in, /api/session now answers with an account id, currentOwner is account:... while selectedPracticeFocusOwner is still device, and the box is unchecked and nothing is shared, with no message. The same happens when this /api/session call fails. Compare owners only when selectedPracticeFocus is set, and leave the automatic focus on its old path.

Comment thread web/problem-picker.js
}
}

export function readSelectedPracticeFocus(storage, owner) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing under web/ calls this; the lobby uses readSelectedPracticeFocusSelection, and only tests/browser/problem-picker.test.js imports this wrapper. Those tests therefore pin a function the page never runs. Delete it and point the tests at readSelectedPracticeFocusSelection(...)?.focus.

@jserv jserv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebase onto latest main branch and resolve conflicts.

@jserv

jserv commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

#603 changes the lobby Start handler to handle blocked session storage and adds a rule against bare storage globals. This pull request changes the same handler to carry a selected practice focus. After #603 merges, please rebase onto main, preserve both behaviors, update the storage calls and the affected tests for that rule, and rerun the required checks and interactive review.

Comment thread src/web/auth.rs
Comment on lines +574 to +577
let Some(accounts) = state.accounts.as_ref() else {
return state.accounts_error();
};
let account_id = account_owner_id(accounts, user.account_identity);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current_user only returns Ok(Some(user)) when state.accounts is Some, so this else never runs, and binding accounts here is what pushes the whole json! body one level deeper. Leaving the arm as it was and computing the field in place keeps the diff to the one new line:

"user": {
    "id": state.accounts.as_ref()
        .map(|accounts| account_owner_id(accounts, user.account_identity)),
    "login": user.login,
    "avatarUrl": user.avatar_url
}

Comment thread web/app.js
typeof data?.accountId !== "string" ||
data.accountId !== expectedAccountId
) {
if (generation !== historyLoad) return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This repeats the generation check just above with no await in between, so it can never fire.

Suggested change
if (generation !== historyLoad) return;

Comment thread web/app.js
Comment on lines +2235 to +2243
selectedPracticeFocus = focus;
selectedPracticeFocusSourceReportId = attempt.id || null;
storeSelectedPracticeFocus(
selectedPracticeFocusStorage,
selectedPracticeFocusOwner,
item,
attempt.interviewMode,
selectedPracticeFocusSourceReportId,
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result of storeSelectedPracticeFocus is dropped here. When setItem throws, the lobby shows the new focus, but a reload restores whatever selection was stored before, or none. The interview and replay paths check the result and show "Could not save this practice focus."; do the same here. Those five lines of status handling now exist three times, so a helper beside storeSelectedPracticeFocus in problem-picker.js would keep them in one place.

Suggested change
selectedPracticeFocus = focus;
selectedPracticeFocusSourceReportId = attempt.id || null;
storeSelectedPracticeFocus(
selectedPracticeFocusStorage,
selectedPracticeFocusOwner,
item,
attempt.interviewMode,
selectedPracticeFocusSourceReportId,
);
if (
!storeSelectedPracticeFocus(
selectedPracticeFocusStorage,
selectedPracticeFocusOwner,
item,
attempt.interviewMode,
attempt.id || null,
)
) {
const status = button.parentElement?.querySelector(
"[data-practice-focus-status]",
);
if (status) {
status.hidden = false;
status.textContent = "Could not save this practice focus.";
}
return;
}
selectedPracticeFocus = focus;
selectedPracticeFocusSourceReportId = attempt.id || null;

@jserv

jserv commented Nov 7, 2026

Copy link
Copy Markdown
Contributor

Some review comments on this pull request are not settled yet. Please refine the change per the review comments listed below, reply on each thread with what you changed or why you did not, and mark each thread resolved yourself once it is settled (Resolve conversation, at the bottom of the thread). The pull request stays blocked while review threads are open.

Not addressed at the current head:

Checked at db3562f.

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.

Let candidates choose a report improvement as the next practice focus

4 participants