Our interview practice product used to mark two things. One was what you said: a transcript, then relevance, clarity and structure. The other was how you looked while saying it: a vision model scored eye contact, posture and confidence out of 10 from stills pulled out of each recorded answer.

Last night we deleted the second one. This is what deleting a scored feature actually costs, and what we deliberately did not delete.

The argument, written where the code was

The reasoning now sits at the top of the feedback module, in place of the step it describes:

Body language (eye contact, posture, visual confidence) is deliberately not scored. Interview research finds visual cues add little over what a candidate actually says, HireVue dropped facial analysis for that reason, and camera-based scoring penalises people for things unrelated to the job. Only the audio of each answer is uploaded and analysed.

That last sentence is the one that matters to a user. HireVue, the best known vendor in one-way video interviewing, publicly stopped using facial analysis in its assessments in 2021 and said the visual signal added little to the model. We were a practice tool reproducing a scored dimension that the industry it imitates had already dropped, and a candidate with a tremor, a stim, a non-Western norm about eye contact or simply a bad webcam would be marked down for it by us.

What deletion looked like

97 removed lines in the diff mention frames or the vision pass. The pieces:

  • The model constants, including a doc comment on the image detail parameter, a note that a reasoning model emits reasoning tokens before the visible message so a tight output cap returns an empty string, and a measured token count per frame. All of that knowledge was real and is now gone from the codebase, which is the right trade when the feature is gone.
  • extractFrames, which used ffmpeg to pull three JPEGs per answer at 25, 50 and 75 per cent of its duration. The worker no longer decodes a single frame of anybody.
  • The VisualAnalysis type: eyeContact, posture, confidence, all number, all 0-10.

The processing worker's validator flipped with it. It used to require a video stream and treat audio as the thing it extracted; now it requires an audio stream and treats video as optional, because current clients upload audio only and older ones uploaded a video with sound in it. Both still parse. That half is its own post.

The one field we kept

Sessions marked before last night have a stored feedback blob in Postgres with those scores in it. We kept the field:

/** * - nonVerbalScores exists only on sessions marked before body language was * dropped from the product. It is kept so old rows still parse, and is * never displayed or written. */ nonVerbalScores?: { eyeContact: number; posture: number; confidence: number; }; 

No migration, no backfill, no UPDATE stripping the key out of the jsonb. Two reasons. Rewriting feedback a user has already read is its own kind of dishonesty, and a batch update over a column of blobs is a far riskier thing to run than leaving three numbers unread. The display component simply has no branch for the field any more, so the scores stop appearing and keep existing.

That is the whole shape of removing a scored dimension: new rows cannot have it, old rows keep it, and the type says which is which in a comment rather than in a version column.

Eleven edits to a page nobody reads, and one version number

The privacy policy is where this change becomes a promise rather than a preference. Forty-five changed lines on app/privacy/page.tsx: one bullet deleted (Non-verbal presentation scores: AI-generated scores (0-10) for eye contact, posture, and confidence, derived from video frames), two added, and eight rewritten elsewhere in the document.

The sharpest rewrite is the one that stopped describing a video upload:

Answer recordings: a recording of each spoken answer, uploaded to Cloudflare R2 secure cloud storage. Your camera picture is used for the on-screen preview and the replay of each answer, which stay on your device; only the audio is uploaded. If your browser cannot record audio on its own, the recording is uploaded with its video, but only the audio is analysed

The second clause is there because the fallback is real. A browser whose MediaRecorder cannot produce an audio-only stream still uploads the whole recording, and a policy that claimed "only audio is ever uploaded" would be false for that browser.

The processor list also changed, in both directions: the vision model came out of our OpenAI entry and the text-to-speech voice went in, with the note that only the question text is sent to it.

Then the part that is easy to skip. We have a constant:

export const CURRENT_PRIVACY_VERSION = '1.9.0'; 

Bumping it shows a policy-update banner to every signed-in account on their next dashboard visit. Our policy page itself lists the two things we do when the policy changes, and we have shipped a change that did neither. This one bumped: 1.8.0 on 29 October, 1.9.0 on 1 November, three days apart, because deleting a category of personal data you used to derive is exactly the kind of change the banner exists for.

The cookie policy moved too, from "Last updated: 12 September 2026" to 1 November, and its stored-data list lost the words "eye contact, posture, confidence". The sitemap did not notice: /cookies is still stamped 2026-05-01 there, because that date is hand-typed in app/sitemap.ts while the page's own date is hand-typed in the page. Two hand-typed dates for one document is one too many, and that one is still outstanding.

The residue, since we are being honest

Our guide pages still tell you to look at the camera. /interview/how-to-pass-a-video-interview uses the phrase "eye contact" four times and discusses facial expression, because advice for an interview a human will watch is not the same thing as what our marker reads. Keeping that advice while refusing to score it is the position, not an oversight, and the hub now says so in a FAQ entry.

See it

  • The new FAQ entry: cogniprep.app/interview, search the page for "Is my body language or face scored?". It is rendered copy and it is also inside the FAQPage JSON-LD, which you can see with curl -s https://cogniprep.app/interview | grep -o '"name":"Is my body language[^}]*}'.
  • The policy: cogniprep.app/privacy reads "Last updated: 1 November 2026 · Version: 1.9.0" and the word "non-verbal" appears nowhere in it. The old bullet is quoted above if you want to diff it by eye.
  • The processor list on the same page now names Whisper, a GPT-4o-mini text model and the interviewer voice, and no vision model.
  • The outstanding bug: cogniprep.app/cookies says 1 November 2026, and curl -s https://cogniprep.app/sitemap.xml | grep -A1 '/cookies' says 2026-05-01.