Files
jobtrackingapp/docs/career-workspace-product-strategy.md
cesnimda aedd6e32ad docs: recover Career Workspace research + strategy from feature/career-workspace
Bring the four Career Workspace documents onto main as the target architecture
for Phases 2-4, and point MASTER_IMPLEMENTATION_GUIDE.md at them. Taken from the
branch tip (later commits refined them). Pure additions — none previously existed
on main.

- cv-builder-competitor-deep-research.md (Novoresume, Reactive Resume, FlowCV,
  Teal, Enhancv, Canva, Resume.io, Kickresume; matrix; pricing intelligence).
- cv-builder-product-teardown.md
- career-workspace-product-strategy.md
- career-workspace-implementation-roadmap.md (F0-F5)

MASTER_IMPLEMENTATION_GUIDE.md v1.1: adds a Source-Of-Truth Documents section and
restates the "profile is the source of truth; documents reference snapshots" rule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 17:06:46 +02:00

30 KiB
Raw Permalink Blame History

Career Workspace — Product Strategy & Roadmap

Date: 2026-07-12 Inputs: docs/cv-builder-competitor-deep-research.md (market), docs/cv-builder-product-teardown.md (as-is audit), CV Builder Architecture Proposal (target design). Nature: This is a decision document, not a summary. Where the research allowed multiple directions, this document picks one and says why. Intended as the foundation for Fable 5 product planning, the engineering roadmap, UX design, and architecture decisions.


1. Product Vision

The one-sentence vision

Jobbjakt is the workspace where your career data lives once and works everywhere — every CV, cover letter, application, and interview prep session is generated from, and feeds back into, one structured career profile.

Evaluating "the CV is not the product; the profile is"

The premise is correct but incomplete. Correct: the teardown proved every current defect traces to documents-as-primary-objects, and the research proved no competitor owns the profile-first position. Incomplete: a profile sitting still is a database, not a product. What users pay attention to (and would pay money for) is what the profile does under pressure — during an active job search.

Refined thesis: the product is the loop, and the profile is its engine:

Career Profile → tailored application (CV + letter, gap-driven)
      ↑                    ↓
  learns from ← application outcome (tracked, email-observed)

Every competitor owns at most one arc of this loop. Teal has profile→tailor but weak rendering and stops at "Applied." Design-led builders have rendering but no career data. Reactive Resume has clean documents but zero context. Nobody closes the loop — and we already own its rarest arc: the outcome-observation side (Gmail intelligence, status suggestions, tracking). That asymmetry is the strategy. We don't build a CV builder and add tracking; we already have the tracking-and-intelligence layer competitors can't cheaply replicate, and we're adding the one commodity piece (a good CV builder) they all have.

The problems we solve

  1. Fragmentation: the modern search runs across 57 tools (builder, tracker, spreadsheet, keyword checker, letter writer, prep notes) with career data re-typed into each. One profile, one workspace.
  2. Tailoring cost: serious applicants need 35 tailored variants; today that means duplicated documents that rot independently. Variants inherit from the profile; the profile updates everywhere.
  3. Blind applications: applicants don't know what the ATS sees or what the JD wants. Match scoring + gap-driven tailoring + ATS-view make it visible.
  4. Career amnesia: achievements evaporate between searches. A durable, versioned profile means the next search starts warm.
  5. Trust: the incumbent market monetises desperation (subscription traps, resume hostage-taking, secret AI caps). We are structurally incapable of it (self-hostable, export-always-free) and say so.

Unique value proposition

"Other tools build you a document. Jobbjakt runs your search: one career profile that generates every tailored CV and cover letter, scores you against every job you track, reads the recruiter's reply, and preps you for the interview it lands — without ever holding your data hostage."


2. Product Positioning

Landscape verdict (from the research, compressed to decisions)

Cluster Their strength Their structural weakness Our exploit
Design-led (Novoresume, Resume.io, Kickresume, Enhancv) Template quality, polish, distribution Predatory billing = trust vacuum; zero career context; PDF-only lock-ins Fair-exit guarantee + career context they'd have to rebuild their revenue model to match
Free/OSS (Reactive Resume, FlowCV) Trust, editor UX, price Document-centric; no job context; thin AI Match their fairness, exceed them on the loop
Workspace (Teal) The loop's left half; tracker distribution Weak rendering; stops at the application; shallow profile Deeper profile + real rendering + post-application intelligence
Canvas (Canva) Design freedom 72% ATS failure — architecturally unfixable "ATS-safe by construction," provable

Why choose us over each

  • Over Novoresume/Resume.io: same-or-better output quality, no watermark, no hostage, and your CV knows about your job search.
  • Over FlowCV: everything FlowCV's editor does, plus the variant you're editing is scored against the actual job and updated from your profile.
  • Over Reactive Resume: same data-ownership ethos (self-hostable, schema published), plus tailoring, tracking, and email intelligence a document tool can't have.
  • Over Teal: your tailored CV actually looks professional, your profile is deep (provenance, versions), and the workspace doesn't go silent after you click Apply — it reads the interview invite and preps you for it.
  • Over Canva: structured data → deterministic parse order → every theme ATS-safe by construction, with a "view as ATS" proof.

Positioning statement

For active job seekers who apply to many roles, Jobbjakt is the AI career workspace that turns one structured career profile into every tailored application — unlike resume builders that produce disconnected documents and trackers that abandon you after you apply, Jobbjakt closes the loop from profile to interview, and never holds your data hostage.

Two positioning disciplines that follow:

  1. Never market as "resume builder." In that category we have 6 templates against Novoresume's brand; we'd be comparison-shopped on our weakest axis. The category is career workspace — young enough (GigForge/ResumeTrakr-tier entrants only) that a quality product can define it.
  2. Trust is a feature with a spec: export always free (PDF+JSON minimum), no watermark, visible AI quotas, published profile schema, one-click full data export. Each is cheap for us and revenue-model-breaking for incumbents — the definition of a durable wedge.

3. Target User Personas

Priority order is a decision, not a list: build for P1/P2 first — they exercise the loop hardest and match the product's existing DNA (the current user is P2).

P1 — "Marcus," the high-volume applicant (primary)

Mid-career, applying to 3080 roles across 23 title families. Goals: volume without quality collapse; know which applications are alive. Frustrations: re-tailoring is an hour per application so he stops tailoring; loses track of threads; every builder wants $25/mo at his most broke moment. Workflow: job boards → save → tailor (or guiltily don't) → apply → chaos of follow-ups. Needs most: variants with cheap tailoring (gap chips, one-click fixes), tracker + email auto-linking (exists), follow-up nudges (exists), match score triage ("which of these 12 saved jobs am I actually competitive for?").

P2 — "Dana," the technical professional (primary; the current user)

Developer/engineer, deliberate search, 515 applications. Goals: precision-target roles; CV that survives both ATS and senior-engineer skim; own her data. Frustrations: builders dumb down technical content; canvas tools break ATS; distrusts SaaS lock-in. Workflow: deep JD reading → heavy per-role tailoring → tracked follow-ups. Needs most: structured editor with real skill taxonomy, ATS-view, self-hosting/schema/JSON export, constrained AI that never invents seniority, diff-on-every-AI-edit.

P3 — "Sofia," the career changer (secondary)

Moving between fields; same history must tell two different stories. Goals: reframe, not fabricate. Frustrations: single-CV tools force one narrative; AI rewrites drift into fiction. Needs most: multiple free-standing variants from one profile (the sharpest validation of profile/variant separation), transferable-skills surfacing, fact-constrained rewriting with visible diffs, cover letters that carry the reframing story.

P4 — "Tom," the recent graduate (secondary)

First real CV, thin content, no existing document. Goals: credible one-pager fast. Frustrations: import-only tools (our current dead end — teardown §2) assume a CV exists; blank-page paralysis. Needs most: from-scratch guided creation, content prompts ("what did you build at university?"), one great simple theme, honest bullet suggestions. Strategic note: Tom is the acquisition persona (students share tools; Kickresume's student program precedent) but must not drive architecture — his needs are a subset of P1P3's editor.

P5 — "Priya," the international applicant (secondary)

Cross-border applications; conventions differ (photo/no-photo, page norms, spelling, market-specific sections). Needs most: per-variant conventions (photo toggle exists; page mode exists), multilingual content support (rewrite language knob exists — rare head start), theme conventions per market, visa/eligibility custom sections. Mostly configuration breadth on top of the variant model, not new architecture.

P6 — "Elena," the experienced executive (tertiary)

20+ years, 3-page history, selective applications. Needs most: selective inclusion per variant (long profile, curated projections — again the variant model), discreet public profile, quality typography. Buys or self-hosts on trust and polish. Serve architecturally, don't design for first.

Pattern worth noticing: P3, P5, P6 all reduce to "one deep profile, many selective projections." The personas independently re-derive the core architecture — good sign the architecture is right.


4. Core Product Model

CareerProfile                     ← the durable asset (one per user; N later)
 │  everything you've ever done: jobs, bullets, skills, education, projects,
 │  certs, languages; stable item IDs; normalized dates; provenance metadata
 │  (confidence, source, review state); versioned; structure canonical
 │
 ├──< CvVariant                   ← a persistent *lens* on the profile
 │     │  "Backend-focused" / "Team-lead-focused" / "Career-change: data"
 │     │  selections + overrides by item ID (inherits; profile edits flow in;
 │     │  overrides tracked, revertible)
 │     ├──< CvVersion             ← history: every save/generation; diff/restore
 │     └── ThemeRef → Theme       ← SIBLING input: declarative manifest
 │                                  (tokens, layout, section styles, page-break
 │                                  rules, ATS rating). Never welded to content.
 │
 ├──< TailoredApplication         ← the *event*: variant × JobApplication
 │     │  gap analysis (match score), per-application tweaks, its own versions
 │     └── outcome feedback ← tracker status + Gmail intelligence
 │
 └──> Outputs (adapters; each = projection of profile/variant/application + theme)
       PDF CV · DOCX CV (scoped) · ATS plain-text view · Cover letter
       Public profile (live, not snapshot) · Portfolio/personal site
       LinkedIn content · Interview prep (persisted; email-thread-aware)

Relationships, precisely:

  • Profile → Variant is inheritance with selection: a variant names which profile items appear, in what order, with what per-item overrides. Edit a job title in the profile → every non-overridden variant reflects it. This single mechanism serves Marcus (volume), Sofia (two narratives), Elena (selective depth).
  • Variant → TailoredApplication is instantiation against a job: the variant is durable and reusable; the tailored application is per-job, driven by the match-score gap list, and versioned so regeneration never destroys manual work (fixes the teardown's overwrite-anxiety root cause).
  • Theme is orthogonal to all content. Any variant/application renders in any theme; switching is non-destructive by construction.
  • Outputs are stateless projections through IOutputAdapter<T>. New output type ≈ one adapter + (sometimes) one theme. This is what makes Horizon-3 features (portfolio, LinkedIn, site) cheap instead of new products.
  • The loop closes at TailoredApplication ← outcome: tracked status + email signals accumulate on the application, feeding analytics ("last 15 rejections wanted Kubernetes") and, eventually, tailoring suggestions.

Cover letters hang off TailoredApplication (they're per-job by nature), generated from profile + JD + (uniquely) the email thread context.


5. Feature Prioritisation

MVP — "the loop works" (next major version)

Feature User value Business value Complexity MoSCoW
Fix OAuth CV lockout (isLocal bug) Unblocks all Google/MS users Removes a dead-end for every new OAuth signup Trivial Must (ship now, pre-MVP)
CareerProfile + CvVariant + CvVersion migration (stable IDs, normalized dates) Invisible now; everything later The architecture bet Large Must
Structured profile editor (+ extraction review queue) Career data becomes maintainable; provenance visible Core differentiator vs. document tools Large Must
Theme engine port — best 34 of 6 templates as manifests Non-destructive theme switching; quality floor Unblocks marketplace/premium later Large Must
Tailoring workspace (JD gaps ↔ variant ↔ live preview ↔ rescore, full page) The killer screen; ends modal editing The demo that sells the product Large Must
Import (upload exists + paste-text) AND from-scratch creation No user dead-ends at entry Doubles addressable entry funnel (P4) Medium Must
Diff + accept/reject on every AI mutation Trust; no silent fabrication Anti-hallucination brand plank SmallMed Must
Fair-exit set: free PDF+JSON export, no watermark Table stakes vs. OSS; trust wedge Positioning proof Small Must
Live paginated preview (<300ms on 3-page CV) FlowCV-bar editor feel Retention; perceived quality Medium Should
Template gallery w/ visual previews + ATS rating per theme Informed choice; ATS trust Marketing surface Small Should
Persist interview prep / fit outputs Work stops evaporating Cheap retention Small Should
UI vocabulary cleanup (kill "reprocess/runs") Comprehensibility Polish Trivial Should
DOCX export (scoped single-column) Loudest market complaint Checklist parity Medium Could
Cover letter v1 (profile + JD) Completes the application Expected feature Medium Could
LinkedIn import Onboarding speed Funnel Medium Not now (parse fragility; paste-text covers 80%)

Version 2 — "the loop compounds"

Feature User value Business value Complexity MoSCoW
Cover letters w/ email-thread context Letters that reference the actual conversation Unique-data moat begins Medium Must (V2)
ATS plain-text "what the parser sees" view Anxiety-killer; provable claim Marketing weapon vs. Canva/Enhancv Small Must (V2)
Skills-gap analytics across tracked JDs "Your market wants X; you lack it" Nobody has it; pure aggregation SmallMed Must (V2)
Email-aware interview prep (persisted, thread-fed) Preps you for this interview The post-application moat Medium Should
Public profile / share link (theme over live profile) Always-current link for recruiters Viral surface; premium candidate Medium Should
Fact-constraint validator (novel-entity flagging) on generation Career integrity guarantee Trust plank #2 Medium Should
Variant refresh/diff when profile changed (staleness UX on CanonicalProfileVersion) Safe propagation Completes inheritance story Medium Should
Published profile schema + JSON Resume import/export Interop; technical-user trust OSS goodwill (P2) Small Should
User-defined theme tokens (fonts, spacing) Personalization Premium candidate Medium Could
Multi-language variant support (leans on existing rewrite lang) P5 unlock Market breadth Medium Could

Future Vision — "the platform"

Feature User value Business value Complexity MoSCoW
Portfolio / personal-site generation (adapters + themes) Whole web presence from one profile Category-defining Large Should (V3)
LinkedIn content generation (summary, about, posts) Consistency across surfaces Engagement between searches SmallMed Should (V3)
Career timeline & skills matrix visualizations Self-knowledge; review prep Differentiator; needs normalized dates (done in MVP) Medium Could
Theme marketplace (manifest sandbox enables it) Choice explosion w/o our design time Revenue share model Large Could
MCP/agent endpoint over profile User's own AI agents read/write career data Agent-native future (RR precedent) Medium Could
Multiple CareerProfiles per user Portfolio careers, consultants Niche but architecture-ready Small (post-M1) Not now
Coaching / marketplace of humans Off-mission; different business Not now
Auto-apply / one-click mass application Reputation poison (research: spam arms race) Never

6. UX Strategy

First-time user: "I need a CV" → professional PDF, one session

Target: first rendered PDF < 10 minutes (FlowCV bar), while quietly building a profile, not a document.

Sign up (OAuth, one click — bug fixed)
  → "How do you want to start?"   [Upload CV] [Paste text] [Start fresh]
  → Import path: extraction runs live; user lands in REVIEW flow:
     confidence-flagged cards ("We read this as… confirm/fix") —
     provenance metadata finally earns its keep as visible trust
  → Fresh path: guided mini-wizard (contact → most recent job w/ bullet
     prompts → education → skills) — enough for a one-pager, expandable later
  → Theme picker: 34 quality themes, visual gallery, ATS badge on each
  → Live preview appears WITH the user's real content immediately
  → Download PDF (free, no watermark) + nudge: "Track a job you're
     applying to — we'll score this CV against it."

That final nudge is the workspace conversion moment: the PDF is the hook; the score-against-a-real-job is the "oh, this is different" beat. Teal's lesson (research §2.4): workspace-first onboarding with no artifact feels disorienting — so we produce the artifact first and reveal the system second.

Returning user

  • Update profile: Profile is a top-level destination (never again a settings card). Structured sections, inline edit, per-item provenance. Edits show a "3 variants use this item" ripple indicator.
  • New variant: from profile or by cloning: pick items, name the lens ("Platform-eng focus"), pick theme. Variants list shows which jobs each has been used for.
  • Apply to a job: job gets a Tailor action → tailoring workspace: JD + gap chips left, variant editor center, live preview right; one-click gap fixes (constrained rewrite + diff); export/attach; tracker updates.
  • Track progress: existing dashboard/kanban continues; applications now show attached tailored version + match score at application time.
Dashboard · Jobs (kanban/table) · Inbox (correspondence + review queue)
Career [NEW: Profile · Variants · (later) Public profile] · Settings

CV ceases to exist as a noun in the nav. Career is the pillar; documents are things you export from it. Tailoring workspace is a route (/jobs/:id/tailor), reached from a job — full page, never a modal (teardown's hardest UX finding).

Dashboard design

Keep tracker widgets (pipeline, reminders, analytics). Add two career widgets: Profile health (completeness, unreviewed low-confidence fields, variants stale vs. profile) and Match radar (saved jobs ranked by score — Marcus's triage). Dashboard answers "what should I do next in my search?", not "here are your documents."


7. AI Strategy

Doctrine, from research §5's useful-vs-gimmick line: AI operates on the user's real data (profile, JD, email thread), shows its work (diff, source), and never invents facts. Anything that generates from nothing, or hides its edit, is out.

Feature User problem AI solution Complexity Priority
Extraction + confidence review Getting existing CV into structure is tedious Parse → normalize → classify w/ per-field confidence; user confirms flagged fields (exists; needs the review UI) UI only P0 (MVP)
Gap-driven tailoring Tailoring is an hour per job Match gaps → one-click constrained rewrite per gap → live rescore (wires existing scorer + rewrite) Medium (UI + orchestration) P0 (MVP) — the flagship
Bullet improve w/ diff Weak bullets; distrust of rewrites Per-bullet improve, before/after diff, accept/reject; select-and-rephrase constraint SmallMed P0 (MVP)
Fact-constraint validator Hallucinated seniority/numbers = career damage Generation limited to profile facts; novel named-entity/number flagging Medium P1 (V2)
Cover letter from profile+JD+thread Blank-page letters; generic AI letters Grounded generation citing actual profile items and, in V2, the actual recruiter conversation Medium P1 (V2)
Skills-gap analytics "Why am I being rejected?" Aggregate JD demands across tracked jobs vs. profile skills SmallMed P1 (V2)
Email-aware interview prep Prep is generic; the invite says what the panel covers Prep generated from profile + JD + thread; persisted; STAR stories from user's own bullets Medium P1 (V2) — the moat
From-scratch content prompts Blank-page paralysis (P4) Section-aware questions ("what did you build?") → drafted bullets user edits Small P2
LinkedIn summary generation Surface consistency Another projection of the profile Small P3
Career advice chat Rejected as flagship: unbounded scope, generic output, hallucination surface; revisit only as thin UI over the grounded features above Not now
Resume "score out of 100" theater Rejected: research shows these are engagement gimmicks; our match score is per-job and actionable instead Never

Operational: provider router stays (Gemini/Groq cloud default in prod, Ollama local fallback); visible quota in UI from day one of any metering (Kickresume's secret-cap backlash is the cautionary tale); all CV-content calls remain through the delimiter-fenced, injection-hardened sidecar.


8. Technical Direction

Confirms the Architecture Proposal with the teardown's amendments. Decision summary:

Rebuild (replace):

  • Master-CV storage: ApplicationUser.ProfileCvText/ProfileCvStructureJson columns → CareerProfile table (+ CareerProfileVersion). Raw text demotes to derived artifact (search corpus, export). Structure is canonical — one truth, stated in code.
  • TailoredCvDraftCvVariant + CvVersion + TailoredApplication(job-linked variant use). Presentation leaves the content row: ThemeRef + per-variant render tokens.
  • CvTemplateRenderer's six C# string-builders → Scriban theme manifests (declarative: tokens, layout slots, section styles, explicit page-break rules, ATS rating). Port best 34; retire the rest.
  • Tailored-CV UI out of JobDetailsDialog → dedicated routes.

Keep (assets, per teardown §3):

  • Extraction pipeline (artifacts, versioned runs, provenance metadata) — becomes the review-queue engine.
  • JobCvMatchService + SkillTagger — becomes the tailoring loop's engine (retarget corpus to read from structure, not raw text).
  • Playwright PDF exporter — stays as the PDF adapter behind IOutputAdapter<T>; RR's Chromium-cost lesson says keep the boundary swap-clean, not swap now.
  • FastAPI sidecar with fencing + provider router.
  • All tracker/Gmail/analytics infrastructure — untouched; it's the moat.

Migrate gradually:

  • Schema via the raw-SQL reconciler in additive steps: create new tables → backfill from user columns + drafts (assign stable item IDs, normalize dates during backfill — one-time cost, teardown amendment) → dual-read period → cut over → drop columns last.
  • Endpoints: new /career/* API grows beside /profile-cv/*; old routes proxy then deprecate. Frontend adopts per-screen (profile editor first, tailoring workspace second).
  • Versioning: append-only version rows (profile + variant), content-hash deduped; diff computed, not stored.

Scalability posture: current scale is single-server self-hosted; don't over-build. The two future-proofing investments that are cheap now and brutal later: stable item IDs and normalized dates (schema), and the adapter/theme boundaries (code). Everything else (queue-based rendering, multi-tenant sharding) is Not now.


9. Monetisation Opportunities

Context decision first: this is currently a self-hosted personal/OSS-style product; Stripe work (Wave 5) is deferred pending product decisions. Monetisation strategy is therefore designed now, implemented only if/when the product goes multi-user SaaS. Design it now anyway — pricing architecture shapes feature boundaries.

The model, if/when SaaS: FlowCV's seam, our loop. Free = full quality, singular. Paid = multiplicity + intelligence depth.

Free forever Plus (~£46/mo — undercut Teal/Novoresume 35×)
Profile Full, versioned, provenance Same
Variants 1 Unlimited
Tailored applications 3 active Unlimited
Themes All core themes Same (+ future marketplace)
Export PDF+JSON, unlimited, no watermark — always + DOCX
AI Metered monthly allowance, visible quota High allowance, still visible
Tracker + Gmail Full Full
Public profile Custom-slug live profile

Monetise: variant multiplicity (the proven seam — value scales with search intensity, exactly when willingness-to-pay peaks, without degrading free quality), AI volume (real marginal cost; honest metering), public profile (ongoing hosted value), later marketplace themes (rev-share).

Never monetise (the trust spec): export of your own data, watermark removal (never watermark), the tracker (Teal proved free-tracker acquisition; ours feeds the loop), re-access to documents after cancellation (the anti-Novoresume guarantee — put it on the pricing page verbatim: "Cancel and keep everything you made."), secret AI caps (Kickresume's one-star engine).

Not now: coaching/human services (different business), auto-apply (never), premium template tiers before a marketplace exists (6 themes is too thin to split).


10. Final Recommendation

Executive summary

What it becomes: the AI Career Workspace — one structured, versioned, provenance-aware career profile that generates every output of a job search (tailored CVs, cover letters, ATS views, public profile, interview prep) and learns from every outcome (tracking, email intelligence, match analytics). The CV builder is the visible front door; the loop is the product.

Why: the research shows a market that is huge (55k reviews on a single incumbent), broken on trust (F BBB ratings, hostage patterns), and architecturally stuck — design-led tools can't add career context without rebuilding their revenue model, and the one workspace player (Teal) has weak rendering and stops at the application. The teardown shows our codebase already owns the hardest, least-replicable half: tracking, Gmail intelligence, match scoring, hardened AI, extraction provenance. Every audited defect shares one root cause (documents-as-primary), fixable with one architecture (profile-as-source-of-truth) that four competitor architectures each validate a quarter of.

How we win: (1) close the loop nobody closes — profile → gap-driven tailoring → tracked outcome → interview prep from the actual recruiter thread; (2) make trust a spec, not a slogan — export-always-free, diff-on-every-AI-edit, visible quotas, ATS-view proof, published schema; (3) sequence ruthlessly — invisible data migration first, then the structured editor, then the tailoring workspace as the demo that defines the category.

  1. Fix the OAuth isLocal CV lockout (ProfilePage.tsx:356) — split identity-gates from feature-gates. Ship immediately; P0 bug independent of redesign.
  2. Freeze the CareerProfile schema v1 — profile/variant/version entities, stable item IDs, normalized dates (YYYY-MM + isCurrent), provenance carried over; publish as JSON Schema doc in docs/. (Design task; gates everything.)
  3. Write the migration + backfill in the raw-SQL reconciler: new tables, backfill from ProfileCvStructureJson + TailoredCvDraft rows (IDs + date normalization during backfill), dual-read flag. Test against a prod DB copy.
  4. Retarget JobCvMatchService to read from structure (not raw text) — kills the dual-truth divergence and validates the new model with an existing consumer.
  5. Author the Scriban theme-manifest schema (tokens, layout, section styles, page-break rules, ATS rating) and port ats-minimal end-to-end through IOutputAdapter<Pdf> as the proving thread. Then port the next 23 best templates; retire the rest.
  6. Build the structured profile editor (new /career/profile route): section forms, per-bullet rows w/ reorder, provenance-flagged review queue for low-confidence fields.
  7. Add from-scratch + paste-text entry paths feeding the same editor/normalize pipeline; wire the onboarding flow of §6 (first PDF < 10 min).
  8. Ship diff/accept-reject on all AI mutations (rewrite, improve, generation) — the trust primitive, small enough to land while 56 are in flight.
  9. Build the tailoring workspace route (/jobs/:id/tailor): gap chips ↔ variant editor ↔ live themed preview ↔ rescore; retire the modal editor.
  10. Ship the fair-exit set + template gallery: free PDF+JSON export everywhere, no-watermark guarantee stated in UI, visual theme gallery with ATS badges — the positioning made tangible in the product.

Tasks 14 are backend-quiet and parallelizable with 5; 69 are the visible product; 10 is polish that carries the strategy. This sequence matches the Architecture Proposal's phases with the teardown's amendments applied, and lands the MVP of §5 in full.