Skip to content

Let the candidate mark unclear interviewer lines - #433

Open
April-ying wants to merge 1 commit into
sysprog21:mainfrom
April-ying:mark-unclear-lines
Open

April-ying wants to merge 1 commit into
sysprog21:mainfrom
April-ying:mark-unclear-lines

Conversation

@April-ying

@April-ying April-ying commented Oct 22, 2026 •

Copy link
Copy Markdown

What

During the interview, an "Unclear" button beside the "Live CC:" label marks the Jim turn on screen; pressing it again unmarks it. The button shows only while a Jim turn is on screen, and it is disabled on unmarked turns once 10 are marked. Jim is not told about a mark.

When the report is saved, the marked turns are resolved to their transcript text and stored as unclearLines in the history entry, after the report returns, so they are never part of the report request. The report shows a "Lines you marked as unclear" section after "Practice next", in the web card and the Markdown export, and the export also tags the marked turns in its transcript as "Jim (marked unclear)". A report reopened from Past attempts shows the section too; its export has no transcript to tag, as before.

One difference from the issue body: the web report card has no transcript, so tagging inside the transcript happens only in the Markdown export downloaded at the end of the interview.

Measurements

Local history in this browser held 21 reports: 594 to 12,109 bytes each, 6,933 on average, 145,600 bytes in total against the 167,936-byte budget, so the budget fits about 24 average reports, not 500.

Interviewer lines from three downloaded reports (93 lines): median 172 bytes, 90th percentile 333 bytes, longest 548 bytes.

With about 3 bytes of JSON per string, 10 marks add about 1.8 KB at the median line length and at most about 5.5 KB if every mark were as long as the longest line seen, about 25% and 79% of an average report. An interview at the cap therefore pushes out at most one older report, so the cap is 10. A cap of 20 could cost more than one.

Tests

  • tests/browser/progress.test.js: an entry at the cap keeps all 10 lines, an entry past the cap or with an oversized line is bounded on read, and unclearLines that is missing, null, a string, a number, an object, or an array holding a non-string is read as no marks.
  • tests/browser/captions.test.js: the button marks and unmarks the current turn, hides during candidate speech, starts unmarked on a new Jim turn, and stops marking at the cap; hiding or disabling the focused button, or hiding the bar through the idle timeout or a code edit, moves focus to the editor.
  • tests/browser/render.test.js: the Markdown export lists and tags marked lines, and a report without marks has no section in either view.
  • Existing tests that rebuild saveHistory now pass unclearLines, and the replay vocabulary test lists the new section's words.

./scripts/test.sh passes locally, including the Playwright browser tests. One lobby layout test, "problem cards span desktop panels and return home on narrow screens", passes on some runs and fails on others here, also on an unmodified checkout.

Contract version

No version bump: no prompt, rubric, or report schema changed, and unclearLines lives in the history entry outside the report.

Screenshots

Before: the caption bar.
image

After: the Unclear button, unmarked and marked.
image

image

After: the report section.
image

Closes #391


Summary by cubic

Lets the candidate mark Jim's lines as unclear during the interview so they can review them later; pressing the new Unclear button again unmarks the line. Jim never sees the marks.

  • The button shows only while a Jim turn is on screen and disables on unmarked turns once 10 are marked, which keeps a marked interview within one average report of the local history budget.
  • Marks are resolved to transcript text when the report is saved and stored as unclearLines in the history entry, outside the report and its request, so no prompt, rubric, or report schema changes; marks that would push the report body past the server's size limit are dropped rather than costing the report.
  • The report and its Markdown export show a "Lines you marked as unclear" section; the export tags marked turns by id, so a repeated line is not tagged twice. Reopened reports from Past attempts show the section too; the field is read only as an array of strings, so older or hand-edited entries render as before.

Written for commit 7387d2f. Summary will update on new commits.

View guided diff

Copilot AI balanced review requested due to automatic review settings October 22, 2026 12:58

This comment was marked as low quality.

cubic-dev-ai[bot]

This comment was marked as resolved.

Comment thread web/captions.js

function showUnclearButton(visible) {
if (!nodes.captionUnclear) return;
nodes.captionUnclear.hidden = !visible;

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.

Hiding captionUnclear while it has focus drops keyboard focus to <body>: tab to Unclear, press Space, start speaking, and the next updateCaptions("you", ...) hides the focused button. The cap does the same with disabled when the next Jim turn arrives. Before hiding or disabling, check document.activeElement === nodes.captionUnclear and move focus to a stable control (the editor or the captions bar).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: before the button is hidden or disabled while it has focus, focus moves to the captions bar, which now has tabindex="-1". Two caption tests cover candidate speech and the cap.

Comment thread web/interview.html Outdated
Comment thread web/render.js Outdated
cubic-dev-ai[bot]

This comment was marked as resolved.

Comment thread web/interview.js Outdated
Comment thread web/captions.js Outdated
Comment thread web/captions.js Outdated
Comment thread web/interview.js Outdated
Comment thread web/lib.js
// Above the longest interviewer turn measured (548 bytes), so a real turn is
// kept whole, while ten lines of four-byte characters stay under 24 KB of the
// 64 KB report body.
const MAX_UNCLEAR_LINE_CHARS = 600;

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.

boundedText cuts at 600 code points without any marker, and Past attempts keep no transcript, so the end of a long marked turn (often the actual question) is gone for good with nothing on screen saying so. 548 bytes was the longest of 93 sampled lines, and a long hint can exceed it. Append an ellipsis when a line is clipped so the report shows the cut.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: a line longer than 600 code points is cut to 599 and ends in an ellipsis, so the report shows the cut. A lib test covers it.

Comment thread web/interview.html
Comment on lines +803 to +811
<button
id="caption-unclear"
type="button"
class="caption-unclear"
aria-pressed="false"
hidden
>
Unclear
</button>

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 button now sits inside #captions-bar, which is aria-live="polite", and showUnclearButton flips its hidden at every switch between candidate and Jim captions. Unhiding it is an addition to the live region, so a screen reader announces "Unclear" before Jim lines, and the aria-pressed change is read out as caption content too. Keep the control out of the announced content: move aria-live and aria-label from the bar onto #captions-text, so only the caption text is live.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed: aria-live and aria-label moved from #captions-bar onto #captions-text, so only the caption text is announced.

Comment thread web/captions.js Outdated
Non-native candidates often miss a word or two of what Jim says and
answer anyway, and nothing let them note the line to review later. An
Unclear button beside the live caption marks the Jim turn on screen.
Marks never reach Jim or the report request: they are resolved to
transcript text when the report is saved and stored as unclearLines in
the history entry, since saved history keeps no transcript, while the
live export tags turns by id so a repeated line is not tagged twice.
The cap of 10 keeps a marked interview within one average report of
the 164 KB local history budget, and marks are dropped before they
would push the 64 KB report body past the server limit, so they never
cost the report. Past attempts and replay accept the field only as an
array of strings, so older or hand-edited entries render as before.
Comment thread web/lib.js
export const MAX_UNCLEAR_LINES = 10;
// Above the longest interviewer turn measured (548 bytes), so a typical turn is
// kept whole; a longer one is cut with an ellipsis that says so.
const MAX_UNCLEAR_LINE_CHARS = 600;

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.

MAX_UNCLEAR_LINE_CHARS caps code points, but the history budget that decides eviction is serialized UTF-8 bytes, and the cap of 10 was justified with byte measurements (548 bytes longest, about 5.5 KB worst case). A turn of 600 non-ASCII characters passes clipUnclearLine at up to 2,400 bytes, so ten marks can reach about 24 KB and push out three or four older reports instead of one. Clipping by TextEncoder byte length (with the ellipsis inside the budget) would make the guarantee in the description hold for any script, not only English.

@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 latest main branch to apply security updates.

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 the candidate mark interviewer lines they did not understand

3 participants