Where we are
Source: SOURCE-OF-TRUTH.md · synced 2026-06-12
For each step: the design, the implementation plan, where the code lives, and current status. Sub-steps (decimal-numbered, e.g. Step 5.1, Step 5.1.1) sit inside each step.
Status words used:
| Word | Meaning |
|---|---|
| Built — shipped | Code is written, tested, and merged. Done for now. |
| Built — awaiting next step | Code is written and tested. Waiting on a later step to use it. |
| Design done — build not started | A design document exists. No code yet. |
| Plan approved | The plan or amendment has been signed off. Ready to consume. |
| Plan drafted — awaiting approval | A first-draft plan exists. Needs review before build. |
| Blocked — gating later steps | This phase must ship before downstream steps can move. |
| Not started — no plan yet | No design, no implementation plan, no code. Earliest stage. |
| Live | An ongoing piece (docs site, sync pipeline) that is in production now and continues to receive small updates. |
Step 1 — JD ingested (raw upload + text extraction)
- Step 1.1 — JD upload + text extraction
- Design: Inherits the CV extractor pattern. The JD parser plan reuses
src/lib/cv-parser/extractor.tsfor PDF/DOCX/DOC text extraction. No separate design doc — covered in Step 2’s design. - Implementation plan: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-impl.md Tasks 1–3.
- Code: Not built.
- Status: Design done — build not started.
- Design: Inherits the CV extractor pattern. The JD parser plan reuses
Step 2 — JD parsed (Claude tool-use → structured ParsedJD)
- Step 2.1 — JD parser build
- Design: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-design.md §“JD Parser — Output Schema”.
- Implementation plan: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-impl.md Tasks 1–3.
- Code: Not built. Target:
calibre-app/src/lib/jd-parser/. - Status: Design done — build not started.
Step 3 — JD normalised + tagged (3-level taxonomy, bootstrapped vocab)
-
Step 3.1 — Tag-vocab bootstrap (run a lean LLM-driven match across all 41 JDs × ~107 CVs (raw text, no normalisation yet). Cluster the categorical terms Claude keeps using to describe fits. Cluster + name → locked tag vocab.)
- Design: plans/step-3.1-vocab-bootstrap-design.md — plan approved.
- Implementation plan: plans/step-3.1-vocab-bootstrap-impl.md — Tasks 1–10 built; Task 11 (live pipeline run, ~USD 5–10 in API costs) and Task 12 (Calibre-team ratification session) still to run.
- Code:
calibre-app/feat/vocab-bootstrapbranch —src/lib/vocab-bootstrap/+scripts/run-vocab-bootstrap.ts+scripts/review-vocab-candidate.ts. 19 files, 47 tests passing. - Status: Built — awaiting live run + ratification session. This is the critical path — once the vocabulary is locked, Step 3.2, Step 5.2, and Step 6.1 all unblock in parallel.
-
Step 3.2 — JD normaliser build (Claude tool-use call: ParsedJD → NormalisedJD with function, vertical, tag list, seniority tier, must-have tags, nice-to-have tags)
- Design: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-design.md §“JD Normaliser — Output Schema” — schema superseded by plans/amendment-3.2+5.2+6.1-taxonomy-3level.md §“Schema 1”.
- Implementation plan: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-impl.md Tasks 4–6 — needs an impl-plan amendment after Step 3.1 locks the vocabulary.
- Configs: reference/rubric-configs/ (4 stubs — become defaults in the new rubric resolution chain) + reference/verticals/ (4 stubs — same gap).
- Code: Not built. Target:
calibre-app/src/lib/jd-normaliser/. - Status: Design done — build not started. Sequence: run Step 3.1 → vocabulary locks → amend Step 3.2 impl plan → build.
Step 4 — Sourcing (candidate + employer scraping)
-
Step 4.1 — Apify candidate scraping
-
Step 4.2 — Apollo enrichment
-
Step 4.3 — Anymail Finder
-
Step 4.4 — Employer-side BD scraping (sourcing the other side — hiring agencies)
-
Design: grant/scope.md §“AI-Powered Resourcing” — scope only, not detailed.
-
Implementation plan: Not written yet.
-
Code: Not built.
-
Status: ⏸️ Deferred 2026-06-11. Design plan exists at plans/pipeline-4-sourcing-design.md. Build deferred — orchestrate against existing 41 JDs × 107 CVs first. Opens after the matching engine (Steps 5–8) proves itself end-to-end on existing data.
Step 5.0 — Candidate-record merge (bridge between sourcing and parsing)
Surfaced 2026-06-11. Sits between Step 4 (scraping) and Step 5.1.1 (CV parsing). Merges (a) scraped LinkedIn / Apollo profile JSON with (b) any uploaded CV file blob into one CandidateRecord that downstream sub-steps consume. Without this, Step 5.1.1 only knows how to parse file blobs — scraped JSON has no defined ingestion path.
- Step 5.0 — Candidate-record merge
- Design: Not written yet. Open: define conflict resolution (which side wins when CV vs scrape disagree on current employer / title / etc.) + source-of-truth rules.
- Implementation plan: Not written yet.
- Code: Not built. Target:
calibre-app/src/lib/candidate-merge/. - Status: Not started — no plan yet. New gap, surfaced this session.
Step 5 — CV parsed + normalised + matched 1:1 to JD
-
Step 5.1.1 — CV parser core (extracts raw fields)
- Design: plans/step-5.1.1-cv-parser-design.md.
- Implementation plan: plans/step-5.1.1-cv-parser-impl.md.
- Code:
calibre-app/src/lib/cv-parser/(built onfeat/parser-core, merged). - Status: Built — shipped. 66+ CVs batch-tested.
-
Step 5.1.2 — CV parser hardening (BOM handling, stale-CV detection, career-gap signals, short-tenure clusters)
- Design: plans/step-5.1.2-cv-parser-hardening-design.md.
- Implementation plan: plans/step-5.1.2-cv-parser-hardening-impl.md.
- Code:
calibre-app/src/lib/cv-parser/(hardened onfeat/parser-hardening, merged). - Status: Built — shipped. Full re-batch over ~107 CV set queued for after the normalisers + Layer 1 ship. Produces the red-flag-penalty inputs that feed Step 6.1 rubric.
-
Step 5.2 — CV normaliser (raw fields → controlled taxonomy)
- Design: plans/amendment-3.2+5.2+6.1-taxonomy-3level.md §“Schema 2” (canonical). Earlier
step-5-phase-2-cv-normaliser-design.mdwas archived 2026-06-11 to_archive/2026-06-11-superseded-plans/. - Implementation plan: Not written yet.
- Code: Not built. Target:
calibre-app/src/lib/cv-normaliser/. - Status: Blocked — gating Steps 6–8. Build after Step 3.1 locks the vocabulary.
- Design: plans/amendment-3.2+5.2+6.1-taxonomy-3level.md §“Schema 2” (canonical). Earlier
-
Step 5.3 —
Industry-expert filterRenumbered 2026-06-12 → Step 6.0 + Step 6.2. The Step 5 numeric ID misrepresented runtime order (it never touched CVs at parse time — it gated and adjusted Layer 1 scoring).dropgates now fire at 6.0 (before Layer 1); boost/penalty + L2 flags at 6.2 (after Layer 1). See Step 6 below. Design filename keeps the 5.3 prefix: plans/step-5.3-industry-filter-design.md.
Step 6 — Hard-fit filter (gates + Layer 1 + overlay — deterministic, composite ≥4 passes)
Restructured 2026-06-12 into three sub-steps in execution order: 6.0 entry gates → 6.1 rubric scoring → 6.2 rules overlay. The former Step 5.3 industry-expert filter was split into 6.0 + 6.2.
Layer 1 fires rubrics at the sub-vertical granularity defined in §3b — an LNG energy operator and a fertilizer agri operator both fall under cargo-ops but score against different weights and signals. 22 sub-vertical rubric configs will be emitted by the extended bootstrap mine per plans/amendment-3.1+5.3+6.1-bootstrap-rubric-extension.md. The 4 grant-vertical stub configs that used to sit at reference/rubric-configs/{commodities,maritime,offshore,tech-gaming}.json were archived 2026-06-11 to _archive/2026-06-11-rubric-stubs-4-vertical/.
Rubric config keying: the rubric file is selected by (function, vertical). Examples:
cargo-ops.energy→ energy rubric (LNG / LPG / crude / petrochem signals)cargo-ops.agri→ agri rubric (grain / sugar / cocoa signals)ship-ops.tanker→ tanker rubric (chemical / LNG / LPG carrier signals)
Each rubric produces a 4-dimension hard-fit score with default weights tag overlap 0.40 / seniority delta 0.20 / years of experience 0.20 / red-flag penalty 0.20 (Dan tunes per sub-vertical at ratification). Sub-function match is NOT a weighted dimension — it is the 6.0 entry gate (locked 2026-06-12; as a binary 5-or-0 with a drop on 0, weighting it added no discrimination). Composite ≥ 4 after the 6.2 overlay → passes to Step 7.
-
Step 6.0 — Entry gates (new 2026-06-12)
- What: Sub-function gate (JD vs CV
sub_functionmust match; adjacency may salvage) + ratifieddrop-type rules from the mined ruleset. Fires BEFORE any rubric scoring — eliminates non-starters with rule id as drop reason. - Design: plans/step-5.3-industry-filter-design.md (rules) + matching-engine design (gate semantics).
- Code: Not built. Target:
calibre-app/src/lib/matching/entry-gates.ts. - Status: Content drafted (bootstrap xlsx) — awaiting ratification. xlsx needs re-emit: drop rules split from L2-flag rules.
- What: Sub-function gate (JD vs CV
-
Step 6.1 — Rubric loader + composite scorer
- Design: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-design.md §“Layer 1 — Hard Fit” (formulas) + plans/amendment-3.1+5.3+6.1-bootstrap-rubric-extension.md §4c (per-sub-vertical content schema).
- Implementation plan: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-impl.md Tasks 9–10. Needs an amendment: rubric loading must key on
(sub_function, sub_vertical), not just function. - Configs: 22 sub-vertical rubrics will land at
reference/rubric-configs/{sub-function}.{sub-vertical}.jsonafter the bootstrap mine fires. See reference/rubric-configs/README.md. - Code: Not built. Target:
calibre-app/src/lib/matching/layer1-hard-fit.ts. - Status: Design done — build not started. Depends on Step 5.2 + vocabulary lock + bootstrap mine ratification. xlsx needs re-emit for the 4-dim weight scheme before ratification.
-
Step 6.2 — Rules overlay (new 2026-06-12)
- What: Fires AFTER the Layer 1 composite. (1) Boost/penalty rules — per-rule deltas sum, then clip to net ±0.5 on the composite (locked 2026-06-12: rules nudge borderline candidates, never overturn the rubric — anything stronger belongs as an L1 dimension). (2) Attaches
block_at_l2/require_evidenceflags consumed by Step 7.2. (3) Threshold re-check: adjusted composite < 4.0 → drop with reasoncomposite_below_4_after_rules. - Design: plans/step-5.3-industry-filter-design.md (rules) + matching-engine design.
- Code: Not built. Target:
calibre-app/src/lib/matching/rules-overlay.ts. - Status: Content drafted (bootstrap xlsx) — awaiting ratification. xlsx delta values need update for the ±0.5 net cap (was ±0.3–1.5).
- What: Fires AFTER the Layer 1 composite. (1) Boost/penalty rules — per-rule deltas sum, then clip to net ±0.5 on the composite (locked 2026-06-12: rules nudge borderline candidates, never overturn the rubric — anything stronger belongs as an L1 dimension). (2) Attaches
Step 7 — Deep assessment (Layer 2 — qualitative, evidence-grounded)
-
Step 7.1 — Adjacency resolver
-
Step 7.2 — Evidence-grounded LLM assessment
-
Design: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-design.md §“Layer 2 — Deep Assessment” + §“Adjacency Resolver”.
-
Implementation plan: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-impl.md Tasks 11–13.
-
Code: Not built. Targets:
calibre-app/src/lib/matching/layer2-deep-assessment.ts,calibre-app/src/lib/matching/adjacency/*. -
Status: Design done — build not started. Depends on Step 6.
Step 8 — Shortlist (four fit groups by composite score)
Locked 2026-06-11:
| Band | Score range | What happens |
|---|---|---|
| Strong yes | ≥ 4.5 | Primary recommendation → Step 9 outreach |
| Soft yes | 4.0–4.49 | Backup → Step 9 outreach |
| Soft no | 3.5–3.99 | Skips Step 7 LLM verification. Parked, re-pool for future JDs. |
| Strong no | < 3.5 | Parked. No re-pool by default. |
- Step 8.1 — Layer 3 verdict synthesis
- Design: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-design.md §“Layer 3 — Verdict Synthesis”. Numeric bands locked here per §8 change log 2026-06-11.
- Implementation plan: plans/pipeline-1.1+2.1+3.2+6.1+7.1+7.2+8.1-matching-engine-impl.md Task 14.
- Code: Not built. Target:
calibre-app/src/lib/matching/layer3-verdict.ts. - Status: Design done — build not started.
Step 9 — Personalised outreach
-
Step 9.1 — Personalisation engine
-
Step 9.2 — Email send
-
Step 9.3 — LinkedIn sequencing
-
Step 9.4 — Response handling
-
Design: grant/scope.md §“AI-Driven Candidate Outreach” — scope only.
-
Implementation plan: Not written yet.
-
Code: Not built.
-
Status: Not started — no plan yet. Opens after Step 8 ships shortlists.
Step 10 — Productisation surface (the product Calibre uses and sells)
-
Step 10.1 — Multi-tenant database (Supabase row-level security)
-
Step 10.2 — Marketing landing page
-
Step 10.3 — Signup + onboarding wizard
-
Step 10.4 — Stripe checkout (test mode is acceptable for audit)
-
Step 10.5 — Demo tenant(s) — at least one fictional agency tenant to defend the “marketable to other agencies” claim
-
Step 10.6 — Admin (super-admin for 3NMP to manage tenants)
-
Design: grant/architecture.md §“Dual-surface architecture” — high-level only.
-
Implementation plan: Not written yet.
-
Code: Not built.
-
Status: Not started — only the architecture sketch exists. Opens after Steps 7 + 8 prove the matching engine end-to-end.
Step 11 — Audit prep (the deliverables EnterpriseSG reviews)
-
Step 11.1 — Project report on Calibre letterhead
-
Step 11.2 — Training materials
-
Step 11.3 — Recordings + attendance log
-
Step 11.4 — Productivity measurement (before / after metric for audit)
-
Design: grant/deliverable-checklist.md.
-
Implementation plan: Not written yet.
-
Code: N/A — this step produces documents, not code.
-
Status: Not started. Opens October 2026.
Step 12 — Infra (the project tooling that ships everything else)
-
Step 12.1 — Docs site (
docs-site/→calibredocs.3nm.io) -
Step 12.2 — Manifest → sync pipeline (
scripts/inventory-site-manifest.py+scripts/sync-docs-site.py) -
Step 12.3 — Dev environment (branches, agent skills, CI)
-
Step 12.4 — Documentation governance (this file, PLANS-LOG, STATE-LOG, CLAUDE.md, the project → docs-site routing map at
_internal/workspace-to-docs-site-map.md) -
Status: Live. The manifest → sync pipeline has been running since 2026-06-01. Documentation governance was overhauled on 2026-06-03 (nomenclature unification + docs-site outside-in rewrite).