Decisions
25 decision records, newest first. Each one is the context, the options, the choice and the consequences — written when the decision was made, not reconstructed afterwards.
An accepted record is never edited to reverse it. A decision that changes gets a new record that supersedes the old one, and the old one stays exactly as written, because the reasoning that turned out to be wrong is the part worth keeping. ADR 0021 reversing a scope exclusion from ADR 0003 is the worked example.
If you are reading one of these first, read ADR 0012. karani drafts everything and submits nothing, and almost every other decision here is downstream of that one.
| ADR | Decision | Status |
|---|---|---|
| 0025 | Every pass has a deadline Why every pass has a deadline, after a hang silenced the pipeline for 40 hours. | accepted |
| 0024 | Interview prep fires on the state change Why interview prep fires on a state change rather than on a verb. | accepted |
| 0023 | A static submission console, and a write-back that creates labels A static submission console, and the write-back that gives the funnel its labels. | accepted |
| 0022 | A conversion ledger, and promotion that refuses on noise A conversion ledger, and a promotion rule that refuses to crown a winner on noise. | accepted |
| 0021 | Computational biology is in scope; exclusions become liftable Why computational biology is in scope, and how a built-in exclusion becomes liftable. | accepted |
| 0020 | Submission-ready documents: ATS-plain .docx, PDF for humans Why the pack renders to an ATS-plain .docx and a PDF, after 121 packs produced 0 applications. | accepted |
| 0019 | Hosted Claude tiers behind a monthly allocation Why billed work degrades to a local model instead of halting or overspending. | accepted |
| 0018 | Liveness must live outside the process it watches Why the thing that watches the pipeline cannot run inside it. | accepted |
| 0017 | Pluggable LLM providers, local-first qualification Providers as a registry, and why bulk qualification runs on a local model. | accepted |
| 0016 | Production hardening: dedup, locks, ledger, verify gate The hardening pass: cross-run dedup, advisory locks, a run ledger, a verify gate. | accepted |
| 0015 | One namespace, one config file, one CLI — pip-installable One namespace, one config file, one CLI — and why it is on PyPI. | accepted |
| 0014 | Per-job artifacts in object storage + a measured humanizer pass Why each job’s documents live in object storage, and why the humanizer is measured. | accepted |
| 0013 | LangGraph for background orchestration — and nowhere else Where LangGraph is used, and the larger set of places it is not. | accepted |
| 0012 | Autopilot drafts, human sends Why karani drafts everything and submits nothing. The load-bearing decision. | accepted |
| 0011 | Notion board as a karani-owned mirror, not a second store Why the Notion board is a one-way mirror that karani owns the schema of. | accepted |
| 0010 | Slack as the two-way daily surface (Socket Mode bridge) Why Slack is the two-way surface, and what it is allowed to do. | accepted |
| 0009 | Ledger-first memory with mem0 as a derived index Why the memory ledger is the system of record and the vector index is disposable. | accepted |
| 0008 | MCP server as the interactive interface layer Why the MCP server is a thin adapter with no logic of its own. | accepted |
| 0007 | Agent mode is opt-in, not default Why the tool-using agent is opt-in and never the daily batch. | accepted |
| 0006 | In-memory storage fallback as a real code path Why running with no database is a real code path rather than a test shim. | accepted |
| 0005 | Application state machine as columns, not a separate table Why the application state machine is columns on a row and not its own table. | accepted |
| 0004 | Normalized content hash + canonical hash for dedup How a posting is recognised as one already seen, across sources. | accepted |
| 0003 | OpenRouter default, Anthropic optional Which LLM provider is the default, and which is optional. | accepted (supersedes 0.1’s Anthropic default) |
| 0002 | Positioning: SF-band global remote, not Kenya-specific The positioning the whole pipeline exists to serve, and why it is location-agnostic. | accepted (supersedes an implicit v0.1 positioning) |
| 0001 | Tiered filter (deterministic → LLM → agent) instead of one LLM pass Why there are two filter tiers and not one model call per posting. | accepted |
Last updated on