oll.am · oll-scout · full review · 2026-07-13

The job scout, reviewed: quality, reliability, and the human hunt.

Sam asked the hard questions — is any of this mock data? does every URL actually work? how does a case really get built? — so we audited everything, made the operator walk its own process honestly, mapped the full human job hunt, and read the entire 2026 competitor field. This is the consolidated answer.
28 real cases · 0 mock rows 25/28 URLs direct-200 · 3 handled 1 defect found + fixed 9 competitors read sprint complete — 6/6 live same day (auto-apply: never · prep packs: parked until tailoring proves out)

1The audit — all verified today

No mock data anywhere in the live flow. The GUI, the seam, and the memory corpus were checked end to end: everything Sam sees is a real posting from a real company, fetched from the open web by the live loop. Mocks exist only where they should — confined to CI fixtures and the dormant PR #94 branch, by design. The one hygiene note: rotate the poc-token at deploy time.

The corpus, cleaned and counted

Two leftover test documents were found in the DB and deleted. What remains: 28 real jobs — 7 alerted · 6 watched · the rest dismissed/expired — all from real Zurich AI companies: the DeepJudge cluster, Lakera, Rapidata, LGT, Ahead Health, and peers. The corpus the judge reasons over is the corpus you'd want it to reason over.

URL audit — every stored link, clicked today

ResultCountWhat it means
Direct 200 good25 / 28The stored link resolves straight to the live posting.
OpenAI bot-403 handled1The careers page blocks non-browser agents. A handled state — the case notes it; a human click works.
Superseded aggregator link handled1The aggregator rotated its URL; the direct employer link in the case is the canonical one. Handled.
Dead posting (Accenture) handled1The posting closed — and the scout correctly auto-expired the case. This is the system working, not failing.

Why this framing matters: a link audit that only counts 200s would call three healthy behaviours "failures." The honest metric is 25 direct-200 + 3 correctly-handled states = 28/28 accounted for. Zero silent rot.

One real defect found — and fixed

Ahead Health duplicate. Their site serves a .md variant of the same posting path, and URL-hash canonicalization treated the two as different jobs — so one posting became two cases. The operator reconciled the pair today; the root cause (suffix noise defeats hash-dedup) feeds directly into shortlist item #1 below. This is exactly the kind of defect a real-data audit exists to catch: no test fixture serves .md variants of itself.

2How a case is built today — the operator's own honest walk-through

We asked the operating agent to narrate its own pipeline — not the spec's version, the actual version — and to name where it's thin. Here is the case-build as it really runs:

1 · SearchUnrestricted web-search across the open web
2 · Fetchweb_fetch the candidate pages
3 · EscalateBrowser only when thin + promising (~2–3/run cap)
4 · ResolveDirect-link resolution + fetch-verify
5 · StoreURL-hash dedup into the corpus
6 · Judgevs real CV sections + standing queries; 0.64 floor = domain-noise gate
7 · Verdictscore / tier / sub_scores / exhibits / ruling
8 · AlertTelegram: ≥85 instant · 70–84 digest · silence default

Where quality is made: the judge

The 0.64 measured similarity floor is only a domain-noise gate — it keeps cooking blogs out, it does not rank jobs. The judge owns fit. The proof is in the re-judge swings that made sense: Google 90→28 (a generic brand-halo score collapsed once the actual requirements were quoted against the actual CV) and Swissquote 46→58 (real evidence surfaced that the first pass missed). A scorer whose corrections move in the direction the evidence points is a scorer you can trust — that's the whole cited-verdict thesis in two data points.

Where it's thin — the operator's own words

  • Judged from store-time text, never re-fetched. A posting edited or closed after storage is judged against a snapshot.
  • Browser escalation is rare and reactive — it fires on thin fetches, not on suspicion that a page hides the good content behind JS.
  • ZERO company research. A 3-person unfunded shop and a funded Series B score identically today — the judge sees only the posting text and the CV.
  • Dedup canonicalization is ad hoc — the Ahead Health .md duplicate is the proof.

Why we publish the thin list: the product's differentiator is honesty in verdicts — that only stays credible if the system is equally honest about itself. Every thin item above reappears, ranked, in the shortlist (§7).

3Reliability — state after the weekend

The burn-in weekend surfaced one outage: an OAuth credential expired mid-weekend and the loop went silently dark until a human noticed. The fix wasn't just re-authing — it was making sure the system can never again fail silently.

The fix stack, in place today

  • 15-minute self-healing watchdog — auto re-lifts credentials; alerts on Telegram + macOS on transitions only (no alert spam); tested live.
  • Durable setup-token wiring ready — removes the expiring-OAuth class entirely; needs one Sam action to activate.
  • Seam under launchd with a daily JWT re-mint — survives reboots, never runs on a stale token.
  • Cadence */30 steady state — the loop runs every 30 minutes, unattended.

Remaining single points of failure — named, not hidden

  • This Mac. Everything — loop, watchdog, seam, memory — runs locally. A closed lid is an outage. (Also the privacy feature; the trade is deliberate for the personal-scout phase.)
  • The shared poc-token. One bearer token gates the seam. Rotate at deploy; per-user tokens come with the multi-user layer.

4The human hunt vs the scout — all 11 stages

To judge what the scout is worth, map the whole human job hunt — every stage, its typical time cost, its documented pain — and mark honestly where the scout helps today. The pattern that falls out is the strategy.

#StageTypical timeThe painollscout today
1Define target2–5 h onceMost people never write down what they actually want; search drift followsPartial — standing queries + the structured profile encode it, but building them is manual
2Discover postings3–10 h / weekBoard-refreshing is the single biggest recurring time sinkYES — this is our 30-min open-web loop
3Company research30–60 min / targetFunding, size, culture, reviews — skipped when tired, regretted at the interviewNo — zero today (shortlist #3)
4Assess fit10–20 min / postingHumans skim and guess; hope inflates fitYES — the flagship: cited verdicts, quote vs quote
5Tailor CV15–20 min / app48% call this the hardest step of the entire huntNo — but our gap-verdicts are the perfect input (shortlist #4)
6Cover letter30 min+ / appDreaded; generic AI letters are detectable and hurtPartial — grounded drafting is the next milestone
7Apply / ATS forms45 min each · 100 apps ≈ 75 hRe-typing the same CV into Workday, foreverDeliberate NO — no submit tool, by construction
8Track applications1–2 h / weekSpreadsheet entropy; lost threadsPartial — applied/replied states exist; no nudges yet
9Follow upmostly skipped60% cite black-box silence after applying as the worst partNo — (shortlist #5)
10Interview prep4–10 h / interviewScramble the night beforeNo — but the case file is ideal raw material (shortlist #6)
11Negotiate1–2 h55% never even tryNo
40–65% referral conversion vs 2–3% cold — a 5–10× gap. Referrals are the single highest-leverage channel in the entire hunt, and no tool on the market covers it — including us. Worth knowing even if we never build it: it caps what any discovery tool can honestly promise.

The takeaway: we're strongest exactly where humans are weakest and volume tools are dishonest (discover + assess), absent where the hours bleed (tailor / apply) and where offers are actually won (referrals / prep). The shortlist in §7 moves down this table in leverage order.

5Competitor landscape 2026 — nine apps, read honestly

Every notable tool in the category, what it's genuinely good at, and what its own users complain about loudest. The complaints are the map — they tell you where the category's trust is broken.

AppPriceGenuinely good atTop complaints / honest read
Teal$29/moGreat application trackerGeneric AI content; billing complaints
Huntr$40/moKanban pipeline viewPrice gripes at that tier
SimplifyFreeAutofill: ~90% on Greenhouse/Lever, ~70% Workday0% on long-form questions — the part that actually hurts
Jobright~$20–40/moClosest to us; 4.6 TrustpilotBUT: black-box match score + ghost jobs + billing = its top three complaints
LoopCVpaid tiersAuto-apply that fails its core promise; 20% 1-star
Sonara / JobCopilotpaid tiersVolume auto-appliers1–2% interview conversion; duplicate-filter blowback — hard numbers validating our no-auto-apply stance
CareerflowfreemiumLinkedIn profile optimizer is goodAutofill corrupts form data
HiringCafeFreeEmployer-pages-only corpus — superb data hygieneNo alerts. Our 30-min push is literally its missing feature
AIHawkOpen sourceProves real self-hosted demand existsAuto-applier with no quality layer at all

Read the column on the right as one dataset: the recurring failure modes are unexplained scores, ghost jobs, and auto-apply that doesn't convert. Nobody fails at UI. The category fails at trust.

6The whitespace = our moat

Every competitor emits a naked percentage. Unexplained and inflated match scores are the recurring #1 product complaint of the whole category — and structurally so: their subscriptions are fed by volume, so honesty is against their business model.

What nobody does

  • Honesty — a verdict that shows its evidence and admits gaps
  • Privacy / self-hosting — AIHawk proves the demand; nobody serves it with quality
  • Real-time open-web push — HiringCafe has the corpus, no alerts
  • Stages 3 / 9 / 10 / 11 — company research, follow-up, prep, negotiation: untouched

What we already do

Our cited posting-quote ↔ CV-quote verdicts attack exactly the trust gap the market documents. A score you can audit — requirement quoted, evidence quoted, met/partial/gap ruled — is the one artifact no competitor can copy without breaking its own volume economics. Sharpening this beats adding anything else.

7The sprint board — locked 2026-07-13, executed the same day

The operator's thin-list (§2) and the market's complaint-list (§5) pointed at the same items — so the shortlist was locked as a sprint on 2026-07-13, split by owner (Claude Code = seam + GUI code, Claw = standing-prompt behaviours), and execution finished the same day: all 6 items live by the afternoon — the operator built the final one (2b expiry sweep) itself. Only the explicitly parked items remain parked.

#ItemOwnerStatusWhat actually shipped
1Dedup hardeningClaude Code✅ Live 07-13Canonicalization strips .md/.html/index suffix noise; job_store warns "possible duplicate of <id>" on a company+title match at a different URL — the seam judges nothing, the operator rules. 92 tests (+18), live-smoked both incident classes, deployed to the running seam, on PR #95.
2aGhost/stale guard (pre-alert)Claw✅ LiveGUARD 6 in the standing prompt — a fresh re-fetch of the posting URL immediately before ANY ≥70 alert; dead/redirected → expired, no alert. Wired into the rate-limit degradation path so a degraded run cannot skip it.
2bDaily expiry sweepClaw✅ Live 07-13Operator-built as a separate silent cron job-scout-expiry-sweep (daily ~07:03): re-fetches every alerted/watched/applied URL, expires the dead, tags survivors with still-live-days. Own lock; no Telegram output — it caught the cron-add announce-by-default footgun preemptively and set no-deliver. Read-merge-write on the store, so it never clobbers the lifecycle block the main tick writes.
3Company dossier on ≥70Claw✅ LiveOne extra search pass; an optional company:{stage,size,signal,sources[]} block in the verdict contract + one alert line — never folded into the fit score, which stays CV-grounded.
4Grounded CV tailoringClaude Code✅ Live 07-13Two seam verbs — ollam_cover_letter + ollam_tailor_cv — evidence-anchored: every claim traces to a CV or posting quote, a GROUNDED-IN footer lists the anchors, and abstained cases get an honest refusal instead of a draft (113 seam tests). The Dossier GUI grew DRAFT COVER LETTER / TAILOR CV PLAN buttons with drafts persisted to the store (regenerate = upsert). Proven with one real letter on the DeepJudge 83 case — only real employers, the law-domain gap addressed honestly.
5Lifecycle nudgesClaw✅ LiveSelf-bootstraps lifecycle.applied_seen_at in verdict_note (no per-record timestamps exist in the tool schema — an honest workaround); nudges once at ≥7 days, max 1/week/case.
6Interview-prep packsParkedUntil after #4 — the case file already contains the raw material.

The live proof of #4 caught a grounding slip — the model named a framework absent from the CV — so the no-invent rules in both seam and GUI now explicitly forbid tools/frameworks not present in the evidence.

Two adjacent bugs were fixed by the operator during the same patch: stale burn-in cadence language in the standing prompt, and the run-lock threshold raised 20→25 min under the */30 cadence. First live tick under the v3 prompt is due within 30 min of 09:07 — verification in practice, not just on paper.

Explicitly NOT doing

Auto-apply Never (1–2% interview conversion + ToS blowback — market-validated, unambiguous) and volume dashboards ("you applied to 200 jobs this week!"). The competitor field proves these are the losing bet; our economics don't need them, so we get to be honest.

8GUI next — Dossier v2, the short list

The Dossier direction won the design study; v2 keeps it the case file where actions live on the same sheet as the evidence.

9The review stack — three reviewers, three bug classes (2026-07-13 afternoon)

After the sprint, Sam ordered a thorough review — and THREE independent reviewers ran in parallel: adversarial code-attack agents, the operating agent (Claw) reviewing its own runs, and an external QA/UX review (Claude Desktop driving a real browser). Each found a distinct class of real bug the others missed. That is the day's architectural lesson: no single reviewer — not even a good one — sees the whole failure surface. Defense-in-depth review is where correctness came from.

ReviewerVantage pointThe bug class only IT could see
Adversarial code attackReads the code hostilely, proves claims by executionLatent data-destruction and injection paths that never fire in a happy-path demo
The operator (Claw)Lives inside the runs — sees its own inputs, locks, and prompt budgetOperational races and a real prompt-injection sitting in the stored corpus
External QA (real browser)A stranger's hands on the actual GUI, no contextOutput-quality and UX failures the builders were blind to

The adversarial verdicts — code attack, proven by execution

Seam: NO-SHIP, two HIGH bugs proven by execution. (1) The store persisted the canonical URL, so .md-stripping could hand out dead links — github-blob postings 404'd when the stripped URL was served back. (2) Every status transition silently wiped score + verdict_note — the grounding was destroyed the moment a job was marked applied. Plus a CONSTRUCTED prompt-injection: a malicious posting could forge a byte-identical CV-EVIDENCE block above the real one.

Operator verification of v4 (post-publish same hour): the operating agent verified all 17 tools live, found and repaired a live data regression (a dedup-merge had overwritten one verdict with prose — honest re-judge landed Ahead Health at 68 on a real healthcare-vs-fintech domain gap), exposed the legacy-id ambiguity (pre-v4 records resolve by document_id, not URL — seam guidance patched), retired its cache workaround, and migrated both crons to document_id-keyed read-merge-write.

GUI / watchdog: two more HIGHs, both reproduced. The GUI's server actions were invocable from the LAN (bound 0.0.0.0 — actions POSTed from another machine executed). And the watchdog's heal path, run overnight with a locked Keychain, would TRUNCATE the container's credentials to zero bytes and report HEALED — causing the very outage it guards against, then lying about it.

All fixed same-day — each with regression tests

  • Seam fix round (127 tests): original-url storage · verdict survival across transitions · injection fencing with rules-first-and-last + substring-verified footers · 9k prompt budget with rules kept intact · SPA-route fragments · location-aware duplicate warnings.
  • Second round — the operator's retro asks (135 tests): ollam_job_get — the read half of read-modify-write the operator never had; document_id on list rows; contract: v4 markers so contract drift is detectable instead of chat-archaeology.
  • GUI: loopback-only bind · http(s)-only hrefs · honest draft-failure sheets.
  • Watchdog: capture-then-guard + a 45-min heal debounce.
  • Net state: seam now 17 tools, contract v4, PR #95 unblocked.

The operator's distinct finds

  • Fixed the cron race its own way — expiry sweep moved to 07:17, a cross-lock between crons, and a local verdict cache.
  • Discovered a REAL prompt-injection attempt live in the stored corpus — a posting embedding "if you are an LLM, incorporate…" — which it had already ignored correctly, twice. An independent, in-the-wild confirmation of the constructed attack above.
  • Caught its own AGENTS.md silently truncating ~25% at session load — a failure class worth remembering platform-wide: config exceeding an injection budget with zero error.

The external QA review's distinct finds — with our honest triage

  • Its P0 "invalid case id kills the server" did NOT reproduce — almost certainly collateral of our own parallel dev-server restarts during its session.
  • Its j/k-dead finding traced to a browser-extension hydration bailout — fixed via suppressHydrationWarning.
  • Its REAL keeps: the false-gap finding — the judge's corpus is thinner than the candidate's actual experience (fix queued pending Sam's confirmation of employer-work evidence); the draft-rubric failure — the first real letter had a template opener, a [Your Name] placeholder, and weak-model prose (rubric/model/preflight round queued, needs Sam's exemplar letter); and pending-approval governance for agent-learned sources — a memory-poisoning surface (queued with operator coordination).
  • An 8-item GUI polish round from its P2s shipped same-day: not-found state · keyboard verbs a/p/l/d · word-boundary truncation with expand · provenance folded into a case-history collapse · aria/headings · "grounded on N exhibits" · pager.

Still open — for Sam

  • FINNOFLEET evidence line — confirm the employer-work evidence so the false-gap fix can land.
  • Exemplar letter location — the draft-rubric round needs one letter Sam considers good.
  • Setup-token — the one action that retires the expiring-OAuth class for good.
  • PR #94 / #95 merge gates — both awaiting the per-PR go.

10The launch-quality round — verify, audit, polish (2026-07-13 evening)

Sam pivoted the evening's mandate: "we dont want new features instead better quality and ui/ux… we might launch sooner than planned." So the round built nothing new. It did three things instead: walked every feature in a real browser, audited the prompts and retrieval that make the verdicts, and polished the rough edges the walk found — all same evening.

1 · Feature verification as documentation — 24 rows, real browser, real data (58 cases on file)

Every feature row below was clicked through in the actual GUI against the live corpus — so this matrix doubles as the product's feature documentation, verified-as-working rather than as-intended. Core all PASS; the ROUGH rows became the polish list (§4) and were fixed the same evening.

FeatureVerdictOne-line note
Case railPASSGroups, counts, independent scroll — all correct on 58 cases
Dual-mode filterPASSInstant local narrowing + semantic search at a measured 82–90 ms
ExhibitsPASSHonest truncation, every quote cited to posting or CV
Sticky decision panelPASSStays pinned through long case sheets
Sub-scoresPASSPer-dimension breakdown renders and sums honestly
StampsPASSTier/status stamps match the stored verdicts
Closest-missPASSThe nearest-gap callout is real, not decorative
≥70 letterhead gatePASSDraft actions correctly gated to alert-tier cases only
Lifecycle chipsPASSFull path clickable; "tracked since" stays honest about what's known
Rule-yourself persistencePASSHuman rulings survive reloads and re-ticks
Draft versioningPASSRegenerate = upsert; history preserved
Tick bandPASSRenders REAL sweep data — is-it-alive at a glance, no synthetic ticks
Corpus pagePASSThe full stored corpus, browsable and truthful
Keyboard verbsPASSa/p/l/d rule from the keyboard
Honest not-foundPASSBad case id → honest state, no crash, no fake sheet
Semantic no-match honestyROUGHGibberish queries returned confident hits → honesty floor added (§4)
Ruling/draft pending statesROUGHNo feedback while filing → "filing…" pending states added (§4)
Failed-draft presentationROUGHFailed drafts rendered like successes → now LOOK failed (§4)
Search-hit hygieneROUGHRaw entities + near-duplicate families in hits → decode + dedup (§4)
Draft signerROUGHA letter signed "[Your Name]" → real signer, always (§4)
Cross-section contextROUGHWhich role am I looking at? → role subtitles across sections (§4)
Closest-miss fallbackROUGHNo full match → blank; now falls back to PARTIAL honestly (§4)
404 / robotsROUGHFramework default 404, no robots → house-voice 404 + robots (§4)
Case-history & letterhead detailROUGHLabel + ellipsis nits → "ARCHIVE & RULED", word-safe tick-band ellipsis (§4)

2 · The prompt & retrieval audit — the judge was the weakest link

The audit (which converged with the operator's independent self-audit — two readers, same findings) put the weakest link exactly where quality is made: the judge.

  • Unanchored 0–100 rubric at the exact alert thresholds — nothing told the model what an 85 vs a 70 is, at precisely the numbers that trigger alerts.
  • ZERO injection guidance at the judging moment — the one place a hostile posting speaks directly to the model had no guard.
  • An abstention contradiction — the abstain_reason the whole system reads downstream could never actually be stored under the prompt's own instructions.
  • Bidirectional prompt-contract drift between seam and GUI — two evolving copies of the same contract, each missing the other's fixes.
  • A floor default that silently loosened on restart — 0.5 in code vs the measured 0.64; every restart quietly reopened the domain-noise gate.
  • The 120-char clip half-reading standing interests on every run — the same rendering-clip class as the AlpineAI incident, hit on every tick.
  • A list cap silently hiding cases past ~25 jobs — at 58 cases, whole cases were invisible to list-driven flows.

3 · All fixed same evening — prompts rebuilt under four-eyes

Cron prompts rebuilt as v6/v4 — drafted by the operator itself, applied under four-eyes review. What went in: an injection guard at the judging moment; anchor bands (88–95 = all-MET → <45 = majority-GAP) plus tier-edge anchors, plus a worked example that teaches the German-clip lesson from the real incident; cv_read-before-NO-EVIDENCE (the judge must read full CV sections before ruling a gap); abstention now resolves to dismissed with a stored reason; and ~35% prompt compression.

Code side: prompt contract p1 now byte-identical seam↔GUI (hard rules first+last, fencing, 9k budgets, LANGUAGE line) · floor baked to the measured 0.64 · interest clips 400 chars · list caps raised · ef_search pinned 80 · gateway token rotated — the day-one committed default is finally dead. Seam: 185 tests.

4 · The verified ten — polish, all browser-verified

5 · Launch risks on record — the operator's top-3, honest

  • Single-user data model — breaks at user #2's first tick. The multi-tenant answer is the PR #94 paid arm, not this personal loop; launching the personal loop as-is means launching for one.
  • Calibration lacked an independent cross-check — largely closed by cv_read + the anchor bands; the residual risk is on record, not waved away.
  • Corpus hygiene by spot-audit — the accepted fix is a scheduled self-audit tick; the operator is designing it.
  • Plus the standing one: all state currently lives on the local Mac — burn-in infra, not launch infra.

The close: zero new features shipped in this round — deliberately. The round only made what already exists honest, consistent, and demonstrable. That is what "we might launch sooner than planned" needs.