Journal
3 July 2026·4 min readProductEngineeringGrounding

Grounded Plans, and a Nudge That Shows Up

By Esperance Brooks3 July 2026

Two problems, one week. First: plans used to stand alone — now every one is anchored to role benchmarks, so a client is measured against a real role, not a plausible sentence. Second: too many people booked a slot, uploaded nothing, and vanished into inbox purgatory. Here's what we shipped, why it matters, and how it works under the hood.

The problem with unanchored plans

A plan that reads well is not a plan that helps. If two clients say they want to be a "Cloud Engineer" and the model quietly interprets that as two different jobs, the milestones diverge, the skill checklist drifts, and the standard we hold everyone to becomes whatever the LLM felt like that afternoon. That is not mentorship. That is autocomplete with confidence.

So we grounded the plan generator in a benchmark catalogue — a small, curated set of role profiles (skills, tasks, aliases) modelled on the O*NET taxonomy. Every plan now resolves the client's target to a canonical position before the model writes a single milestone.

How grounding actually resolves

The resolver runs three tiers, in order, and stops at the first hit:

  • Exact name match against the benchmark's display name.
  • Alias match — the same role expressed differently ("SRE", "Site Reliability Engineer", "Reliability Engineer").
  • Semantic match — a pgvector cosine search over role embeddings, gated at a 0.65 similarity threshold. This catches near-neighbours the alias list will never cover ("Senior Cloud Platform Engineer" landing on cloud_engineer).

If all three miss, we say so — the plan is generated ungrounded and we flag it. Silent fallback is how you end up with plans that look aligned and aren't.

Measuring whether grounding is doing anything

Grounding is only worth the complexity if we can prove it fires. Every generated plan now writes a sources record — which tier matched, which position, at what similarity, how many skills and tasks came from the benchmark. It's one JSON column on the plans table and it answers the only question that matters:

For plans generated this week, what share hit an exact or alias match, what share leaned on the semantic fallback, and what share fell through entirely?

Now we can tune the threshold, expand the alias list where the semantic tier is doing too much work, and add benchmark rows where we're falling through repeatedly — with evidence, not vibes.

CV and LinkedIn: same path, no special-casing

Grounding tells us the target. The client's own profile tells us where they're starting. We already accept both a CV upload and a LinkedIn profile exported as PDF — both are stored, both are text-extracted, and both feed into the same block of the generation prompt. There's no LinkedIn OAuth path and there doesn't need to be one; the PDF export contains everything the plan needs to reason about experience.

The 24-hour reminder — sent once, and only when needed

The second thing we shipped is much smaller and, honestly, overdue. A meaningful number of signups book their slot, then never come back to complete the workflow — no CV, no target role, no context to plan against. A single reminder, timed right, is enough to bring most of them back.

The rules are deliberately narrow:

  • Trigger: 24 hours after signup.
  • Condition: a booking exists but the workflow is incomplete — no plan, no CV, no assessment data.
  • Frequency: once. Ever. We do not chase people through their inbox.

If the client has already completed the workflow, the reminder never sends. If they've already received it, it never sends again. It exists to remove one specific piece of friction, not to become a drip campaign.

For the engineers reading

The moving parts, briefly:

  • A position catalogue with a pgvector embedding column (1536 dims) and a matching function gated at 0.65 cosine similarity.
  • The plan generator runs the three-tier resolver (name → alias → semantic) and persists the outcome alongside each plan — tier, matched position, similarity, skill and task counts.
  • An existing admin action back-fills embeddings for benchmark rows; ingest has no runtime dependency on the AI gateway.
  • Extracted CV text is the single source of profile context — CVs and LinkedIn PDFs both land in the same place.
  • The reminder is a webhook plus an email template, guarded server-side by a sent-once check keyed on the user.

What this changes for you

If you are a client: your plan is measured against a real role now, not a guess. If you booked and never finished, you'll hear from us once — and only once — with a nudge that tells you exactly what's left to do.

If you are a fellow builder reading this for the pattern: ground your generative output, measure whether the grounding is doing work, and be ruthless about one-shot notifications. Every extra email is a tax on trust.

The workshop continues — the Journal gets the next chapter when it ships.

Want the plan we're describing here? Start with your free Orientation Plan — same three-tier grounding, same standard, no shortcuts.

MORE FROM THE JOURNAL