JC → CV consumption bridge — the unbuilt high-value next step

Found 2026-06-04 while the corpus crossed ~13k. The corpus is now real and queryable, but CareerVector cannot yet pull from it. This is the natural next product step and the thing that makes the corpus worth anything.

Verified facts (live)

  • JobCache holds 13k+ postings and is fully queryable:
    • GET https://api.jobcache.corbet.ch/api/postings?limit=N{count, postings[]} with {fingerprint, source, url, title, company, …} per row. Confirmed real data (e.g. "Insurance Advisor … AXA Versicherungen", jobup-ch).
    • GET /api/search?q=…&limit=N{total, results[]}. Works.
    • Plus /api/ads/lookup?url=… and POST /api/ads/resolve.
  • CareerVector's only read of JobCache is GET /api/stats (the corpus health tile, lib/perspective-shared/src/jobcache-health.ts). JOBCACHE_SERVICE_URL is already wired in api/wrangler.toml.
  • The CV→JC direction is write-only: lib/domain/src/jobcache.ts builds ensure_ad / submit_observation commands so workspace-discovered ads propagate into the corpus. There is no read-back.
  • RADAR (lib/domain/src/pipeline/stages/radar.ts) is single-URL scrape (given a URL → scrape/extract into the workspace). It is not corpus-driven discovery.

So: the corpus is built and queryable; nothing consumes it. The North Star's "jobs … eventually through RADAR-style automated discovery" (CLAUDE.md, Product North Star) is exactly this missing bridge.

What a consumption bridge needs — product decisions (for Julian)

These shape the product; not to be defaulted autonomously:

  1. Selection model — how does a workspace pick from 13k jobs?
    • Manual: a search box in the dashboard ("import from corpus") hitting /api/search, user cherry-picks rows → job.create.
    • Semantic: match the workspace's CV-profile / saved search against the corpus (needs embeddings or a structured filter: title, location, industry, salary).
    • Standing query (RADAR-style): a saved filter the pipeline re-runs, auto-adding new matches as they enter the corpus.
  2. Auto vs. manual. Does the workspace pull continuously (a real RADAR loop) or only on user action? (Compute economics §1 + the existing process_request backend model both favor an explicit, claimable job, not a hidden cron.)
  3. Dedup. Corpus posting → workspace job must dedup against existing jobs by url/ad_id (the same normalize+hash already in jobcache.ts).
  4. Import mapping. Corpus row (title, company, url, source + facts) → job.create attributes, with actor_class='system', actor_id like cv-internal:corpus-import, so cell-origins tint correctly (§13).
  5. Filtering quality. A search endpoint over 13k mixed-language Swiss-board ads needs at least location + language + freshness filters to be useful; confirm /api/search supports them or extend it.

Smallest honest first slice (if greenlit)

A manual "Import from corpus" dashboard action: search box → /api/search → result list → multi-select → job.create (deduped). No semantic match, no auto loop. Proves the end-to-end path and surfaces the real UX questions before investing in standing queries / semantic match. Everything else (RADAR loop, profile-match) layers on top.

Status: documented, not started. Gated on decision #1–#2 above.

Source: wiki/content/working-memory/jc-cv-consumption-bridge.md