# HANDOVER — Fable 5 → Sonnet 4.6 (2026-07-07)

Quality foundation is done. Your job is the multi-day full-catalog run.
**Read `Sites(staging)\skillfactor\auftrag_sonnet.md`, follow
`pipeline/templates/` and `pipeline/prompts/` strictly — do not redesign
anything.** Design contracts: `docs/batch-architecture.md`.

## What Fable built today (all committed)

| Artefact | Where | State |
|---|---|---|
| Baseline inventory | `docs/inventory.md` | done |
| Extraction schema | `pipeline/prompts/extract_schema.json` | final |
| Extraction prompt (Ollama) | `pipeline/prompts/extract_posting.txt` | final, tested |
| Local extractor + validator | `pipeline/extract_local.py` | **done & tested: 20/20 clean, ø 6.5 s/ad on gemma3:27b** |
| Depth templates + style | `pipeline/templates/*.template.md`, `STYLE.md` | final |
| Acceptance bar | `pipeline/templates/QUALITY_BAR.md` | final |
| Gold standard | `skills/recruitment-consultant/` | reviewed & upgraded (Output lines, verified market %, TRAP eval) |
| Budget/resume module | `pipeline/progress.py` | done & tested (hard cap 33 000 JSearch req) |
| QA harness | `pipeline/qa_sample.py` | done & tested |
| Batch runner | `pipeline/batch_run.py` | **skeleton — you implement the TODOs** |
| Architecture design | `docs/batch-architecture.md` | final |
| `.env` | `OLLAMA_URL` / `OLLAMA_MODEL` added | works |

## Your exact start sequence

1. Read `auftrag_sonnet.md`, `docs/batch-architecture.md`,
   `pipeline/batch_run.py` (the TODOs name their own acceptance criteria).
2. Apply the MSSQL change (batch-architecture.md §MSSQL) —
   `occupation_slug` column + backfill + index.
3. Implement `stage_packages` (reuse `p2_generate.py`/`p4_publish.py`,
   throttled ≥ 1 s/repo, check-before-create) and run Phase 1 for all
   3 039 ESCO occupations.
4. Implement `stage_evidence` (generalize p3a per occupation, extraction
   via `extract_local.py` as-is, incremental p3b, per-slug p3c).
   Every JSearch HTTP call goes through `progress.spend_request()` FIRST.
5. After each occupation batch: `qa_sample.py --rate 0.02`; two consecutive
   exit-1 = stop and diagnose. Depth files must pass QUALITY_BAR mechanical
   checks before pushing.
6. Depth tier 1 (top-200) per templates; tier 3 as resumable night batch.

## Hard rules (from the finalize order — not negotiable)

- JSearch lifetime budget 33 000 requests — enforced in code, do not bypass.
- ≤ 2 req/s; cache first; thin market → synonyms → Adzuna → mark failed.
- Mass extraction (~180 k ads ≈ 14 GPU-days) runs as a **detached script**
  (`run_in_background` / scheduled task), never inside your session loop.
- No secrets in code/logs. `.env` stays uncommitted.
- Commits small and conventional.

## Open points / caveats

1. **Git history was squashed today 11:21** into one commit (orphan branch
   `clean-history` → renamed master) — not by Claude. Old history is kept
   as tag `backup/pre-squash-history`. Ask Robert before deleting the tag;
   if the squash was unintended, the old commits are all still there.
2. `ADZUNA_APP_ID/KEY` in `.env` are empty — the finalize order lists
   values (§2); copy them in before the Adzuna fallback is needed.
3. Enrichment templates (curriculum/learning/literature/glossary/
   capabilities) do NOT exist yet — Fable's day covered the four depth
   files per auftrag_fable §3. Derive the enrichment ones from
   STYLE.md + the recruiter examples when Phase 3 starts, same pattern.
4. `p2_generate.py` currently emits a fixed balanced set of 100 — needs the
   per-occupation refactor (stage_packages TODO).
5. SKILL.md trigger descriptions come from crosswalk O*NET tasks and are
   sometimes off-profile (recruiter shows HR-manager tasks). Known
   generator limitation — fix in stage_packages if cheap, else log it.
6. Ollama box (91.184.179.239:11434) is unencrypted/unauthenticated —
   COLOGNE2 firewall must restrict port 11434 to this webserver's IP
   (flagged to Robert earlier, unverified).
7. `data/progress.json` is committed in its empty initial state; it is
   run-state, commit it whenever you checkpoint a batch.

## Verification snapshot (what "working" looked like today)

```
.venv/Scripts/python.exe pipeline/extract_local.py \
    --ads data/raw/jobs/recruiter_ads.json \
    --out data/evidence/testset_fable.jsonl --limit 20
# -> done: 20 ok, 0 failed (0% fail)
.venv/Scripts/python.exe pipeline/qa_sample.py \
    --extractions data/evidence/testset_fable.jsonl \
    --ads data/raw/jobs/recruiter_ads.json --rate 0.10
# -> 2 sampled, 0 mechanical issues
```
