Choose the interview language before joining

Merged
MA
3d ago
+699-59

Jim's coding greeting asked which language the candidate wanted, but answering aloud changed nothing: only the editor's language tabs reach the server, so a spoken answer kept the Python starter and the recovery briefing asked again. This implements placement B from #431, one commit per sub-task in the issue.

  • The token request may name the starting language. Only an id the language tabs offer reaches the signed metadata, a whiteboard request drops it, and the agent checks it again. The interview then starts in that language with the choice recorded, so the greeting does not ask, Jim does not announce the first editor packet as a switch, and no recovery briefing asks again. A session without a language keeps today's greeting. Live prompt 33, bundle 43.
  • The interview page resolves the starting language as the issue describes: the URL's language (Try again, #310), else the language the candidate last started an interview in, else Python, whichever the problem can run first. Only C needs the judge: when the preferred language is C and its judge is still loading, Start waits up to five seconds and otherwise starts in the fallback. Every other start goes straight on. The page stores the language once the token request succeeds.
  • The Before you join dialog has a Programming language menu under Interview preferences, above Jim's voice and accent. It offers what the editor tabs offer by the same rule, so a class problem withholds C and a server without compiled runs withholds C, C++ and Java. A whiteboard interview hides it, and the lobby is unchanged.
  • Strict assigns the problem in the token response. Before assignment the menu offers what every problem can run (C waits for a judge, so it is withheld), the token names that language, and the assigned problem opens in it.

One existing behavior changes on purpose. Once the token has named a language, a judge arriving later enables C in the tabs but no longer switches to it, because the token already told the agent which language it is. tests/browser/strict-selection.test.js asserted the old switch for a Strict language=c; that case now asserts the interview stays in Python, and docs/interview-selection.md says so.

BeforeAfter
01-before-preflight02-after-preflight-java

Java chosen before joining: the editor opens on the Java starter and Jim's greeting does not ask for a language.

03c-java-opening-transcript

Validation, on Windows at 8751aa5:

  • ./scripts/test.sh browser: 1832 passed, 2 failed, 12 skipped (no javac). The two failures are the floor-capture.test.js interruption tests, which fail the same way on main on this machine (checked at a7b0b22).
  • tests/browser/start-language.test.js (11) and tests/browser/strict-selection.test.js (56) pass. I checked the new tests by breaking the code they cover: an unbounded judge wait, storing before the token succeeds, opening a Strict assignment in the default language, resolving the starting language before applyLanguages, and waiting on the judge for a Python start each make them fail.
  • cargo test: every suite passes except three tests. The two gemini::tests::bounded_http_diagnostic_* failures reproduce on main (checked at 3bb4b11). recording::a_refused_interview_leaves_its_consent_unspent fails while deleting its temporary database, which Windows reports as still open (os error 32), after the test body has run; it does not touch the language path.
  • gen-wire-fixtures.mjs --check passes once its imports use file URLs, which Node needs for a C: path; the fixtures have not drifted.

Closes #431