Skip to content
Concepts

Design decisions

The settled decisions, numbered, and the reasoning that settled them.

Decisions are numbered so they can be cited, and settled so they aren't re-argued every session. Each lives in the knowledge graph as decision:dN, linked to the features it shaped.

A superseded decision is kept, not deleted: the reason it was reversed is part of the record. The biggest reversal is the model strategy — the project began on a local model and moved entirely to hosted models (D18) after local inference made the 8 GB laptop unusable.

The register#

#DecisionIn one line
D1Python, not TypeScriptThe pipeline is Python; the dashboard is Next.js talking to it over REST.
D2A small local model (qwen3:4b)Superseded. reversed by D18
D3No hosted model — local winsSuperseded. reversed by D18
D4A deterministic orchestratorThe conductor is plain code. No LLM supervisor decides what runs next.
D5GitHub commit emails, but skip the code-lessThe spike was bimodal: ~100% hit rate where a company has public code, 0% without. Code-less companies are skipped, not guessed.
D6Free tiers onlyHunter’s 25 lookups a month are spent on learning address patterns, not single people.
D7No SMTP probingAddresses are checked by MX lookup only; RCPT probing is off.
D8Three confidence tiers, never collapsedverified / pattern-guessed / scraped travel with every address.
D9SQLite, one fileNo server database, no vector extension.
D10The knowledge graph lives in SQLiteNodes, edges and full-text search in the same file, analysed with NetworkX — not a graph database.
D11SQLite stays; CSV is an interfaceCSV is for export and import, never the store.
D12LinkedIn only through no-cookies channelsPublic guest pages and Apify’s no-cookies actors under a daily budget. Your own LinkedIn is used by hand only.
D13“Multi-agent” = narrow workersSmall LLM workers under a deterministic conductor. None can send.
D14Regions and pay floors are configAnd the scorer knows visa feasibility: Germany, then the UK, then the US.
D15Two candidates, one pipelineShared companies and people; separate resumes, drafts and inboxes; one of them per contact per 30 days.
D16OpenRouter for writing tasksSuperseded in part. revised by D18
D17Nothing runs without permissionThe permission gate is build step zero.
D18No local model, everOpenRouter is the only provider, through aliases (cheap, judge, writer), one cost row per call, caps, and a model-free lexical fit at the wide end of the funnel.
D19Agents can only proposeWorkers write fact or draft proposals; capabilities and budgets are enforced by the runtime.
D20Three scraping channels, one gateA polite keyless core, Apify no-cookies, and research search — behind one staging area and one audit, driven by the launchd tick.
D21A second review surfaceTelegram for approvals, with atomic pending → processing claims.
D22Underrated companies onlyHyped names are rejected by name. If everybody knows them, a fresher’s ask is lost in the pile.
D23₹40k/month stipend is a hard barUnder ₹40k, the company does not pay ₹20 LPA+ (2026-10-26).
D24Pay tierstier1 ≥ ₹30 LPA, tier2 ₹24–30 LPA, reject below — rejected companies stay in the database.
D25No stated pay is not a rejectionEngineers on staff plus verified hiring make a company a prospect.
D26No alumni targetingThe people layer targets roles, not colleges.

Reading a decision in the graph#

Every decision links to what it constrains. To see one with its neighbours:

python scripts/run.py kg show decision:d18
Where they come from
The register is generated from knowledge/context.yaml into knowledge/BRIEF.md. The plan that produced most of them is system docs/FINAL-PLAN-V3.md.