Most interview advice ends at "use STAR". That is a structure, not a measurement, and when you are rehearsing alone you cannot hear whether your answer has one.

I built a small offline checker to make the shape visible before you say it to a person. It is one HTML file, no build step, no network calls. This post is about the interesting part: what you can actually detect with word-level heuristics, and where they lie to you.

The four checks

const SIT = /\b(when|last|previous|at the time|our|my team|quarter|project|incident|release|customer)\b/i; const TASK = /\b(my job|i had to|i was asked|the goal|needed to|responsible for|target|deadline)\b/i; const ACT = /\b(i (pulled|built|wrote|shipped|ran|asked|tested|changed|designed|debugged|led)\b|then i|so i|first i)/i; const RES = /\b(result|outcome|went from|dropped|increased|reduced|saved|ended up|as a result|impact)\b/i; 

Four booleans is a crude model, but it is the right crude model for the failure people actually have. In my own drafts the missing piece was never the story — it was the last sentence. The answer stopped at what I did, not at what changed.

That is why the checker's most useful output is not a score. It is the line:

✗ Result — End with a before/after number.

Numbers are the cheapest signal

Counting quantities is a two-line regex and it correlates with the thing interviewers are listening for:

const quantities = raw.match(/\b\d+(\.\d+)?%?|\b(one|two|...|million)\b/gi) || []; 

Zero quantities is almost always a real problem. "We made the pipeline faster" is a claim; "p95 went from 2.4s to 610ms" is evidence. The checker cannot tell whether your number is true — only whether you offered one.

Filler density, not filler count

Counting "um" and "like" per answer is useless: short answers look clean and long answers look terrible. Divide instead:

const density = fillers.length / words; // flag when > 1 per 40 words 

One filler every 40 words is invisible to a listener. One every 8 words is the thing they remember about you.

Ownership: "I" versus "we"

const owned = (text.match(/\bI\b/g) || []).length; const team = (text.match(/\bwe\b/gi) || []).length; 

This one needs care. "We" is correct when the team genuinely did the work, and forcing "I" into a team story reads as credit-taking. The signal worth acting on is only the asymmetric case: we > I in an answer that is supposed to be about your decisions.

Where the heuristics fail

  • Paraphrase beats vocabulary. "My remit was to..." never matches my job. A structurally perfect answer can score 2/4.
  • False positives from context words. "Our release was late" matches the situation regex even when it is the result.
  • No semantics. The tool cannot tell that your action was copying a file and someone else's was redesigning a schema. Both are "I changed".
  • Speaking time is an estimate. words ÷ 140 wpm assumes a conversational pace; a nervous speaker at 180 wpm gets a materially shorter answer than the number suggests.

I left all of these in rather than adding an LLM call, because the constraint is what makes it useful: it runs in a browser tab with the network off, on an answer you would never paste into a service.

What the tool does with the text

Beyond flags, it reconstructs a skeleton from your own sentences — picking the first situation-shaped sentence, the task sentence, then two action sentences and the result — so your next attempt starts from your words, not a template:

SITUATION - Last quarter our checkout error rate doubled after a release. TASK - My job was to find the cause before the peak weekend. ACTION - I pulled the logs for the three biggest failures... RESULT - Error rate went from 4.1% to 0.6% in two days. 

Source and live demo (MIT, single file): star-answer-checker · repo

The honest limit of this approach is that structure is the cheap half. The expensive half is delivery under follow-up questions — someone interrupting your result to ask "why was the retry loop there?" and watching whether the story survives. I practice that with MockLive, which records the answer, asks adaptive follow-ups, and quotes your own words back with the audio.