Methodology

How Smart Tailoring works (and how we stop the AI from inventing things)

Inside the proposal pipeline behind the Tailor to job button: how proposals are generated, the five deterministic anti-hallucination guards that filter them, and what the credit pays for.

Updated June 3, 20266 min read

When you click Tailor to job in the Application workspace, our backend reads your resume + the job description, asks Gemini for a small set of targeted edits, then runs every proposal through five deterministic safety guards before showing you anything. This page documents the full pipeline — what's in the prompt, what the guards check for, and what the credit pays for.

The contract: minimal edits, never invention

Smart Tailoring is deliberately narrow. We are NOT asking the model to rewrite your resume. We are asking it to propose up to 8 minimal, single-field edits that better align an existing resume with a specific job. The proposals are constrained to three field types:

  • The Summary section
  • An individual Experience bullet
  • A Project description

We do not let the model touch your header, contact info, education, skills lists, languages, or certifications. We do not let it add entirely new bullets or new sections. The contract is "rewrite existing text" — never "invent new text."

This scope is enforced first by the prompt, second by a structured-output schema, and third by the path validator on the server: any proposal whose path doesn't resolve to one of those three field types is rejected before reaching you.

What the prompt is told

The system prompt lives in src/lib/tailor/prompt.ts and reads, abbreviated:

You receive a structured resume (with path tags) and a target job description. Propose up to 8 MINIMAL, targeted edits.

Hard rules — violations will be silently rejected by the server, wasting the user's review time:

  • Never invent companies, employers, schools, products, or people not present in the resume or JD.
  • Never invent dates or years not present in the resume or JD.
  • Never invent metrics (percentages, dollar amounts, multipliers, headcounts) not present in the resume or JD.
  • If a bullet would benefit from a metric the candidate hasn't supplied, write the suggestion as 'Add a number for X if possible' in the RATIONALE — do not fabricate the metric in the AFTER text.

The prompt also tells the model HOW to prioritise:

  1. Bullets that miss an important JD keyword the resume otherwise lacks
  2. Bullets with weak verbs ("helped", "worked on", "responsible for")
  3. Bullets with low Wave 7b impact scores (we pass the scores inline as annotations)
  4. Summary alignment when the summary fails to name the JD's headline tools

That priority order is why Smart Tailoring usually surfaces 4-6 proposals on a well-written resume and 7-8 on a weak one — there are simply more high-leverage edits available.

The five deterministic guards

A prompt is a soft layer. Models comply with prompts most of the time, not all of the time. The hard layer is the server-side validator in src/lib/tailor/guards.ts, which runs five checks on every proposal before letting it through:

1. Stale-path

The proposal's before text must match (after normalisation) the current text at the resolved path. If they don't match, the resume was edited between when the proposal was generated and when it would have been applied — silently dropping the proposal is safer than risking an overwrite of newer content.

2. No-op

If before === after after normalisation, the model returned a non-edit. Drop it.

3. Fabricated-date

Any year (1900-2099) or month-year combination ("01/2024", "January 2024") in the after text must appear somewhere in either your resume or the job description. If a proposal tries to insert a date that exists nowhere in the source, it's fabricated — drop the proposal.

4. Fabricated-number

Numeric tokens — percentages, dollar amounts, multipliers ("10x"), shorthand ("100k", "2M"), and bare integers ≥10 — must appear in your resume or the JD. A bullet you wrote that says "led a small team" can't be proposed as "led a 12-person team" unless the number 12 is somewhere in the source.

5. Fabricated-proper-noun

Capitalised two-or-more-word phrases ("Goldman Sachs", "Stanford GSB", "Operator A/B Platform") in after must appear somewhere in the source. This is the guard that catches "Acquired by [made-up company]" or "Reporting to [made-up person]" style fabrications.

A proposal that fails any of these five guards is silently rejected. We log the rejection bucket on the server (fabricated-date, fabricated-number, etc.) so we can tune the prompt over time — but the client only ever sees the proposals that survived.

What the credit pays for

Smart Tailoring costs 1 credit per generation for Free users (Pro is unlimited). The credit is charged atomically on the server BEFORE the Gemini call, and refunded fully on any of these failure paths:

  • Gemini API rate limit
  • Gemini returns a non-200 status
  • Gemini output isn't valid JSON
  • The output doesn't match the proposal schema

You only ever lose a credit if the call succeeds and proposals are returned (even zero proposals after all five guards rejected the candidates — that still counts as a successful call). The refund logic is deliberate: we want the cost to feel honest, and a failed generation isn't something you should pay for.

What happens when you click Apply

The accept/reject step is entirely local — no credit cost, no AI involvement. You can accept a proposal as-is, reject it, or edit the after text inline before accepting.

When you click Apply N edits, the accepted proposals (with your inline edits) are sent to the server in one batch. The server:

  1. Re-validates each path resolves
  2. Applies the edits in sequence (so two edits on the same bullet compose, last-write-wins)
  3. Re-validates the resulting resume against the full ResumeSchema
  4. Writes a forced "Pre-tailor" snapshot of your previous resume into version history
  5. Persists the updated resume in a single transaction

The pre-tailor snapshot is what makes the whole workflow safe to use aggressively. You can apply a full set of proposals, see how they read together, and roll back the entire session in one click from the history page if the result doesn't land. The credit you spent isn't refunded on rollback — but the work isn't lost either.

Why we built this

The reason Smart Tailoring is the headline feature of Wave 7 — and the reason it was the brick we built last — is that it composes everything else. The job description from Wave 7a's URL fetch feeds the prompt. The bullet scores from Wave 7b guide proposal prioritisation. The version system from Wave 7d makes every tailoring session reversible. The five-guard validator is what makes it safe.

Pieces of resume-builder AI exist elsewhere; we know of no other product that ties the JD, the bullet scoring, the diff infrastructure, and the deterministic safety guards into one workflow. That's the part of the product we're most proud of, and this guide is the receipts.

← All guides