Same workflow-map idea as the Outreach Engine page, for the team's own job applications: discover โ score โ verify โ draft โ human review โ send. The real difference from outreach: discovery has 4 separate channels feeding the same table (one automated-but-quota-limited, one manual-per-session, one automated-and-free, one fully human) โ that resilience is the point, not a redundancy. Everything downstream (scoring, HR verification, resume/cover-letter drafting, sending, reply tracking) works identically no matter which channel a job came from. Every stage below is a real, standalone script โ not a manual/chat step, except drafting review itself (a deliberate human gate).
_shared/ librarybaserow-client.mjs ยท search-profiles.mjs
Proven
search-profiles.mjs pulled out of job-search.mjs on 28 Aug specifically so JobSpy could reuse the exact same locked titles/locations without triggering JSearch's own run as a side effect โ one list, every discovery channel reads it.
๐ญ job-search.mjsJSearch (OpenWebNinja), no fallback
Blocked
Free tier is 200 calls/month โ the original 15 calls/day (450/month, 2.25x over) is the real reason this went dead 24-27 Aug, not a fluke. Fixed 28 Aug to 8 calls/day (240/month, still slightly over โ worth a paid tier or one more trim). Waiting on Imran's fresh API key.
๐ญ Indeed via Claude Code MCPsanctioned, session-only
Available, not yet run
Real Indeed data through Claude's own Indeed MCP tool โ the same class of tool as scrape-leads.mjs, just constrained to only work while a Claude Code session is actually open (no unattended overnight schedule possible). First live test hit repeated tool-level rate-limiting; will retry with real spacing between attempts rather than hammering it.
๐ญ jobspy-import.mjsJobSpy (Python, open-source), site=indeed only
Proven โ first run
Added 28 Aug after real conversion data showed JSearch converts only 12% of what it finds (vs manual research's 100%) โ this is a zero-cost, zero-quota resilience layer, not a volume play. Needed a real Python runtime first (the machine's existing installs were corrupted โ MSI installer kept losing python.exe specifically; fixed via the installer-less embeddable distribution, `job-engine/python-runtime/`). First real run: 71 new UAE listings, zero errors. Deliberately conservative โ top 3 titles/person, Indeed only (skips LinkedIn, JobSpy's own docs call it most block-prone), not yet on a schedule. FreeHire (a sibling recommendation) was evaluated and rejected the same day โ its public API's location/country filters don't actually work (verified live: every query returned the same unrelated US listing regardless of filter).
๐ญ ats-collector.mjsGreenhouse + Lever, company-first not keyword-first
Proven โ v2
v1 (Greenhouse-only, 2 companies) found a real bug in its own Gulf-location regex โ "oman" with no word-boundary matched inside "Romania", falsely counting a Remote-hiring company's Romania-based posting as a Gulf job. v2 (same day) fixed that, added Lever as a second Tier-1 platform (verified live against 6 real companies), and grew to 11 fully-verified companies โ every slug tested against the live API before being added, none guessed on faith. A new location_confidence flag (HIGH/LOW) means an ambiguous "Middle East"/"Remote" posting never auto-counts as Gulf just because the company happens to be Gulf-based. Real run 28 Aug: 90 Gulf-located postings seen, 9 passed the relevance filter (2+ keyword overlap with someone's actual locked title โ same discipline that already rejected Fraud-Investigator/Collections-Lead-style noise in v1), including a genuine Process Automation Engineer role at a real Dubai construction firm (econstruct). New ats-detect.mjs module (unit-tested, 7/7 pass) can identify a company's ATS platform from its real careers-page HTML โ built for future company-list growth, not yet wired into the collector's own run. No target_companies Baserow table โ this session's token can't create Baserow fields/tables (hit the same permission wall trying to add a field earlier 28 Aug) โ data/ats-companies.json holds the same richer schema (industry, careers_url, confidence, last_checked_at, job_count) instead, trivial to migrate once a schema-capable token exists. Workable/SmartRecruiters/iCIMS not started (spec's own phasing: prove 2 platforms first). Not scheduled โ manual runs only, by explicit spec instruction, until reliability is proven over several real runs.
๐ฏ match-jobs.mjsClaude Haiku + Sonnet escalation ยท structural validation
Proven, migrated 29 Aug
29 Aug: migrated off Ollama/DeepSeek/Gemini entirely โ same day, same reason as tailor-and-draft.mjs: both real accounts (Gemini quota, DeepSeek balance) had gone down at once, silently stalling scoring for days. Now runs on Claude Haiku via the Claude Code CLI, Sonnet as a single escalation retry โ same proven mechanism as the rest of today's migrations. A response that doesn't match the SCORE:/REASON: format is rejected and retried on Sonnet rather than trusted as-is โ happened 3 times in the first full 57-row run, Sonnet recovered all 3. Rates 0-100 against JOB_TARGET_STRATEGY.md's locked "AI Automation Lead" positioning. 52 of 117 scored rows pass โฅ60 (44%) โ the pass rate dropped from the earlier 72% as noisier, broader-net channels (JobSpy/ATS) fed in more low-relevance roles; the targeting itself is working as intended, just being tested against a wider net now.
๐ต๏ธ find-recipient-email.mjsClaude (Haiku web search) โ DeepSeek โ Gemini
Proven
3-tier fallback, never fabricates a contact โ if no real email is found, the row stays unverified rather than guessing. 48 real recipient emails found to date. HR Contact Name/LinkedIn/Title fields (added 27 Aug, for the case where no email exists but a decision-maker does) are real fields but genuinely 0% populated โ the ChatGPT research prompt delivered for this hasn't been run yet.
โ๏ธ tailor-and-draft.mjsClaude Haiku + Sonnet escalation ยท LOCKED LaTeX template ยท mechanical fact-check
Proven, migrated 29 Aug
51 real resume+cover-letter+email drafts, mechanically verified 2-page compiles. 29 Aug: migrated off Ollama/DeepSeek/Gemini entirely (Imran's explicit call โ all three had gone down at once, silently stalling the pipeline at "found" for days) โ now runs on Claude Haiku via the Claude Code CLI (Imran's own subscription, no separate API key), with Claude Sonnet as a single escalation retry. Two real bugs found and fixed live-testing this: a stale-PDF-on-failed-compile bug, and a PowerShell `$null`โ`{}` JSON quirk that made CLI errors unreadable. Hard anti-fabrication rules (no B.Tech/PMP claims โ Gulf attestation + PMI public registry would catch a lie instantly, risking deportation/blacklist) are locked byte-for-byte from job_engine.md, PLUS a new mechanical fact-checker that cross-verifies every tool name and number in a draft against the real candidate profile โ added after a worded "don't fabricate" instruction alone failed to stop Haiku/Sonnet inventing a specific wrong metric across 6+ separate attempts the same day. A row that fails validation is left safely untouched (Status stays "found") rather than accepting a fabricated draft โ that's the system working as intended, not a bug.
๐ฎ send-via-smtp.mjsZoho SMTP, "Ready to Send" gate
Proven โ live
One email per 5-min scheduled-task tick, ~50/day Zoho cap. Was silently dead for 3 weeks โ the exact same Windows Task Scheduler "finite repetition duration" bug found and fixed across several other tasks that day โ 34 real, already-approved applications sat unsent the whole time. Fixed 27 Aug (task duration extended to 10 years, StartBoundary reset). Never sends without Imran's own "Ready to Send" tick โ that IS the human-approval gate, just relocated from the old Zoho-Draft plan to Baserow directly.
LinkedIn applicationsmanual โ no automated sender, by design
Manual, by design
When HR Contact LinkedIn exists but no email does, the job-review page shows the contact and the JD link โ Imran (or whoever) connects/applies directly, then clicks "Mark as Applied" to log Status/Applied Date/Applied Via/Send Method exactly the way the automated Email path would. No LinkedIn-scraping/auto-connect tool exists or is planned โ LinkedIn's anti-bot posture makes that a bad trade for a low-volume, high-stakes action anyway.
๐ก check-replies.mjs ยท check-bounces.mjsIMAP, 4 Zoho inboxes
Proven โ live, scheduled
Both were also silently dead ~12 days (same task-duration bug), fixed 27 Aug alongside send-via-smtp.mjs. check-replies.mjs pings Imran on Telegram the moment a real reply lands โ interview, shortlist, rejection, whatever it is; check-bounces.mjs matches real DSN "Final-Recipient" data, not a guess. Gulfisha's own IMAP credentials are separately broken (needs a fresh Zoho app-password from her) โ a pre-existing gap, not something this fix touched.
๐๏ธ 3 dashboardsjob-dashboard ยท job-hunting-engine ยท job-review
Proven โ live
All 3 read the same table 922 directly, no separate database. job-dashboard (engine.arisegulf.com) is the detailed funnel/charts view. job-hunting-engine (this system) is the PersonโSector pipeline-card overview โ this page is one click from there. job-review is the actual approve-and-send working queue, built 28 Aug as this system's exact counterpart to Outreach Review.