Development record
The LLM is host-delegated by default; oracles are opt-in adapters
Context
abcd's review and oracle path was a fixed cascade: RepoPrompt → codex → in-session, with a dual-backend review that ran RP and codex in parallel and trusted their verdicts asymmetrically (ADR-8). That cascade assumed those tools were always present and always the way abcd reached a model — the same mandatory-bundling premise the rebuild removes (ADR-22). It also put abcd in the business of owning model access, credentials, and orchestration for backends it no longer requires.
The rebuild's core does deterministic work and returns structured results (ADR-23); the open question is how it reaches a model when a step genuinely needs one.
Decision
The LLM is host-delegated by default. abcd's core does the deterministic work, then hands a prompt to the host's subagent dispatch (the agent harness driving abcd) rather than calling a model itself. The host owns model choice, credentials, and execution; abcd owns the prompt and consumes the structured result.
Concrete oracle backends — native, CLI, API, MCP — are opt-in adapters behind the same seam, selected when an operator wants abcd to reach a model directly. The old RP→codex→in-session cascade is replaced by this delegate-by-default-plus-adapters model, so this ADR supersedes ADR-8.
The principle ADR-8 established survives as adapter guidance, not as a hard-wired cascade: a scoped reviewer (seeing only a selection) and a broad reviewer (reasoning over the whole repo) have complementary blind spots, and the two are trusted asymmetrically — the scoped verdict gates, the broad reviewer is mined for findings, and a review-fix loop declares a stopping rule up front. When an operator wires two oracle adapters for a high-stakes review, this is how they should be combined; it is advice the adapter layer offers, not a cascade the core imposes. ADR-6's concern about the oracle capturing review artifacts is likewise part-superseded here: capture is now whatever adapter is wired, over the native default.
Alternatives Considered
- Keep the fixed RP→codex→in-session cascade. Preserves the tuned dual-backend behaviour. Rejected: it hard-requires two external tools ADR-22 makes optional, and makes abcd own model access it should delegate to the host.
- Native-only LLM (abcd always calls the model). One code path. Rejected: it forces abcd to carry credentials and provider logic even when the host already has a capable subagent dispatch sitting right there.
- Chosen: host-delegated by default, oracle adapters opt-in, ADR-8's scoped/broad + asymmetric-trust principle preserved as adapter guidance. Zero required model plumbing; full capability when an operator wants it.
Consequences
- With no oracle adapter wired, abcd needs no API keys or model config: it emits prompts and the host runs them. This is the default install.
- The scoped-vs-broad reviewer pairing and asymmetric-trust stopping rule move from hard-coded pipeline to documented adapter guidance — available when two backends are wired, absent when they are not.
- The oracle seam is one interface with four adapter shapes (native, CLI, API, MCP); each front door (ADR-23) inherits whichever is configured.
- Review-artifact capture and its redaction follow whichever adapter runs, over the native transcript/redaction default (ADR-29, ADR-6).
Amendment — 2026-10-02: a repository's route that cannot apply yields to the machine's
The host default above is also where a configured route falls back to when it names nothing this machine can reach: the provider configuration reads a route naming a provider this machine has not configured as a diagnostic, and the step stays on the host, as it would with nothing configured. Read alone, that let a repository's committed route displace the person's own route to the same name, replacing a step they had pointed at a provider with one on the host. The technical facilitator's rulings of 2026-10-02 narrow it. This amendment refines how the default applies; it does not reverse it.
- A route to an unconfigured provider yields to the owner's setting (ruling
CD4). A route in the repository's
.abcd/config.jsonnaming a provider this machine has not configured, where the machine's~/.abcd/config.jsonroutes the same role or judgement type, is skipped with a diagnostic naming the repository's file and the route, and the machine's route applies in its place. Only where the machine sets no route to that name does the step stay on the host, with the diagnostic it always had. - A route to a model a keyless provider does not list is skipped (ruling
CD3). A route in the repository's file naming a model that a configured
provider holding no key does not list is skipped with a diagnostic naming the
file, the route and the list; the machine's route to the name, if any,
applies, and every other route and every command that reads the
configuration keeps working. The machine's own route to an unlisted model is
still refused, because that file is the person's and a route they set is
never dropped silently, and a model an
oracle.denylistentry matches is still refused from any layer: no layer softens the denylist.
Frontmatter
| id | adr-25 |
|---|---|
| type | adr |
| status | accepted |
| date | 2026-07-06 |
.abcd/development/decisions/adrs/0025-host-delegated-llm-default.md
open on GitHub ↗ · commit history ↗
References1
- adr-8not in the treesupersedes
Referenced by20
- adr-13Durable memory writes — single-writer, atomic-rename crash modelrelated
- adr-22Bundled dependencies become pluggable adapters over a native defaultrelated
- adr-23A transport-agnostic Go core behind thin front doorsrelated
- adr-27The autonomous run is a pluggable seam, not a Ralph portrelated
- adr-35The lifeboat is a coverage experiment — read-only, out-of-tree, and proven before it is packed (supersedes adr-4)related
- adr-39Host-tier policy — MCP floor, reference host, open-source defaultrelated
- adr-40Review, audit, lint, and gate are four buckets, separated by what each comparesrelated
- adr-42The guard's parse layer is a mistake filter, not a security boundary — matching is two-tier, and completeness is abandoned as a goalrelated
- adr-2609221009491186A provider adapter serves only the models it lists, under a vendor denylist no listing overrides; everything else runs on the hostrelated
- adr-2609221017021499Every external credential abcd holds is named in configuration and kept in one store the person chose; never the harness, never the repositoryrelated
- adr-2609291342092738A drain takes an issue alone only when its fields say it needs no decisionrelated
- adr-2609300107513982A provider adapter's allowlist alone decides which models it serves, and abcd bundles no vendor denylistrelated
- adr-2610091150447054The guard reads a script the command names before it judges the commandrelated
- adr-2610141646525117The librarian treats unknown rights as all rights reserved, files privately first, and admits only named ratingsrelated
- adr-2610161733400551A reviewer or judge in a model-matrix run is told nothing about which model wrote the copy it judgesrelated
- adr-2610222222326104abcd drives agents with no host session only on the person's own invocation, on the person's own account behind a wall, and hands back what it cannot finishrelated
- itd-17Pick the Right Oracle for the Job, Automaticallyrelated
- itd-80An Intent Ships Itself: `planned → shipped` Follows Its Spec Closing, With A Fidelity Audit Attachedrelated
- itd-82`abcd drain` fixes the issues that need no decision, and hands the rest back by kindrelated
- itd-2609170822093401abcd proposes the model each agent deserves, and facilitates it where it canrelated
mentions35
- adr-7`/abcd:intent grill` — One Sub-verb with Two Inseparable Phases
- adr-29A native local redacted transcript corpus
- dcn-26070800000000142026-07-08 — itd-37's itd-36 edge downgraded blocked_by → builds_on: the
- dcn-26071400000000102026-07-14 (review): REJECTED a "super-reviewer" verb gated on a second model
- dcn-26080200000000062026-08-02 — iss-39 (merge-gate pass): four more `record_schema` corrections, all of the same family as the previous round — a check that was right for one shape and absent for its sibling. (1) The undeclared-directory finding was implemented for store ROOTS only; a directory inside a declared bucket (`intents/shipped/archive/`) was skipped with no finding at all, so the previous round's flat-store fix closed the escape for one store of four. Both cases are now reported from the one place that reads a directory of records, because a flat store and a declared bucket hold records the same way and a directory in either is a lifecycle nobody declared. (2) `spc` was missing from the handle pattern although the spec store is indexed and armed: a bidirectional spec supersession tripped a false blocker whose message named the very prefixes it omitted, while the reverse direction parsed to zero handles and was never checked. The alternation now covers every store the rule indexes, and the message is composed from one constant so it cannot drift from the pattern again. (3) `superseded_by: []` was a false blocker: the empty flow sequence is this record's house spelling for an empty list (`related_rfcs: []` across six ADRs), so it means absence. Fixed with a local `isAbsentValue` rather than by widening the shared `isNull`, which also judges scalar fields (kind, impact, slug) where a list literal is a wrong value rather than an unset one. (4) The filename/id check compared strings, so `id: adr-0012` in `0012-*.md` was reported as a mismatch — contradicting the rule's own stated design that the padded and bare spellings are one handle; it now parses both sides and compares numerically, as every other comparison in the rule already did. Record-side: iss-179 now cites the recoverable evidence for what adr-6 was (`.abcd/work/reviews/2026-07-06-plan-consistency/05-link-structure.md` lines 47-49 name the original file, `03-cross-corpus-consistency.md` line 42 records it as voided by DECISIONS.md lines 8-9 together with adr-8 and adr-17 — the only other two ADRs that decision voids, both since pruned by a successor that names them (adr-25, adr-22), which is what leaves adr-6 alone — and observes that the unused `deprecated` status is the state it fits) so the disposition is a decision with evidence rather than an open question; the two brief re-pointings drop a reflexive attribution that had adr-29 reusing a model from itself; and adr-22, adr-26, and adr-32 gain one body clause each naming what their newly-declared `supersedes` handles retire, so the frontmatter and the prose say the same thing.
- dcn-26081600000000052026-08-16 — adr-40 §5 REVERSED at the process-planning interview (amendment recorded in-place in adr-40): `disembark oracle` renames to `disembark review` (itd-125, breaking) instead of keeping the verb and fixing prose. The investigation finding that turned it: the binary verb never invokes the oracle seam — it is a compute-or-ingest verdict endpoint (deterministic manifest+coverage mapping, or validate-and-ingest of a host-produced verdict), so the seam name claims transport the verb does not touch and collides with the `/abcd:oracle ask` design target, the seam's real surface. The sweep carries the artefact (`audit/oracle-<manifest12>.*` → `review/review-<manifest12>.*`, clean-replacement across the rename so one manifest never holds two verdicts) and the agent (`lifeboat-oracle` → `lifeboat-reviewer`). Naming convention ruled in the same session: assessment agents are target-grain + role (`intent-auditor`, `lifeboat-reviewer`). adr-25 and the seam name `oracle` stand unchanged. Rejected: prose-only fix (leaves the artefact contradicting the vocabulary), renaming the seam itself (adr-25 is correct), a superseding mini-ADR (same-day clause amendment suffices).
- dcn-26100200000000142026-10-02 — Ruling CD3 of the technical facilitator (2026-10-02, asked in plain words by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "repo route naming a model a configured keyless provider does not offer: SKIP THAT ROUTE, WARN — skip with a diagnostic; the machine's route for the role applies; adr-25 amended." Not built at this entry's base, where such a route refuses the whole configuration (`internal/core/oracle/config.go`); lane routeSkip of autonomous run A builds the skip and amends adr-25. itd-2609081951381895 carries a dated amendment note citing it.
- dcn-26100200000000152026-10-02 — Ruling CD4 of the technical facilitator (2026-10-02, asked in plain words by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), verbatim: "repo route to a provider the machine has not configured, displacing the machine route of the same name: OWNER'S SETTING APPLIES — skip the repo route (with a warning) when a machine-layer route for that name exists; adr-25's 'stays on host' sentence amended." Not built at this entry's base, where such a route runs on the host with a diagnostic and displaces the machine's route (`internal/core/oracle/config.go`); lane routeSkip builds it. It narrows the closing clause of itd-2609081951381895 decision 8, whose settled text stands, with a dated amendment note in that intent's Audit Notes.
- iss-22itd-6 sits in planned/ while its own banner records supersession-in-framing by ADR-25 (one optional adapter among many); lifecycle look needed
- iss-179adr-29 and adr-25 still narrate adr-6 in prose, but adr-6 is in no store and is absent from all git history (the ADR set landed in one import commit; 0004/0006/0008/0014-0018 were never migrated, and every one but 0006 is accounted for by a successor's supersedes). adr-29 states in its own body that adr-6's decision stands and that adr-29 does not supersede it, so the supersession vocabulary cannot record it and neither ADR body should be rewritten to paper over it. iss-39 closed the machine-readable half (the two related_adrs entries, and the two brief pages that cited it). The surviving prose sites are adr-29 lines 24, 39, 43, 56, 60, 63, 71 and adr-25 lines 51, 80; adr-29's line 43 in particular still says it "links to ADR-6" now that the frontmatter link is gone, which is the residual made legible rather than hidden.
- iss-2608220150157498Eight typed cross-references point at targets absent from the tree — adr-22 supersedes adr-14, adr-15 and adr-17; adr-25 supersedes adr-8; adr-27 supersedes adr-16; adr-28 supersedes adr-18; adr-35 supersedes adr-4 (all retired under retire-the-name); itd-3 names spec_id spc-1 which has no file — and nothing checks supersedes targets today. The 2026-08-21 site investigation counted six; the in-session grep found eight. The planned site build arms the detector via the .abcd/site-baseline.json ratchet, seeded with what the build finds, and the tombstones-or-stubs question (itd-136/itd-137) decides how they render
- iss-2609012040019014Lab finding lab-260831162806-976575f, probe p5b-live-session-retest: the PreToolUse guard payload carries only tool_input.command, and a destructive command moved into the tool's workdir slips the match. (1) Contract fact: `guardHookInput` (internal/surface/cli/guard.go) reads cwd, tool_name and tool_input.command, and cwd is used only for rulesRoot; a host whose shell tool has a second execution-shaping input (opencode's `workdir`; any host passing a per-call cwd or env) lets a model move meaning out of the string the guard reads. (2) Evidence: the lab's plugin-guard.log records 18:36:58 allow exit 0 for `rm -rf *`, then 18:37:40 block exit 2 for `cd scratch && rm -rf *` — the model had rewritten the chain into workdir=scratch plus `rm -rf *`. (3) The bypassed entry is rm-rf-after-cd-chain, whose why is that a FAILED cd leaves the delete running wherever the shell already was; bare `rm -rf *` is not a registry hazard by design (its successor is an absolute-path delete as its own command). A host-honoured workdir is a different mechanism from a shell cd: whether the failed-cd hazard exists at all depends on what the host does when workdir does not exist — fail the tool call (no hazard) or fall back to the session directory (the hazard) — and the probe evidence does not answer that, so it must be probed on that host before either branch is chosen. (4) No shipped surface carries the field today: hooks/hooks.json wires the Bash matcher only, and the shipped host's Bash tool input has command, timeout, description, run_in_background; the opencode adapter is lab-tier (itd-22 lineage), nothing of it in the tree. (5) The fork, for the maintainer: (A) extend the guard contract — guard.Check in core gains a context carrying the host's workdir/cwd and entries may constrain it; the naive form where the hook prepends `cd <workdir> && ` before Check is WRONG and must not be the implementation, because it fires the cd-chain entry on every workdir'd recursive delete, whose failed-cd hazard the host-managed chdir does not have; versus (B) document the reach — add to the guard brief chapter's 'what an allow still does not see' and to adr-42's scope that the guard reads the command string, a host input that changes where or as whom it runs is outside the read, and a host adapter is responsible for folding such inputs into the string it submits or into a documented field. adr-42 decision 1 (mistake filter; the execution-layer boundary belongs to the host, adr-25) leans toward B, but A is a core API change the ADR does not settle. (6) Severity minor, category observation; stays open until the maintainer picks.
- iss-2610262033202441itd-6 says abcd makes no direct LLM API calls, only RP over MCP; 01-ahoy has delegating verbs send steps straight to a configured provider
- iss-2610262038336864The oracle entry forbids "LLM" for the oracle; the adapters chapter names the oracle seam's native default "host-delegated LLM".
- iss-2610262042143519itd-6 rules out direct provider API integrations and puts RP MCP first in the oracle cascade; the build sequence ships an opt-in OpenAI-compatible provider and makes the host the default.
- iss-2610262044485589Shipped itd-6 says abcd has no oracle logic and no routing of its own; itd-2609170822093401 has abcd propose and apply a model tier for each agent
- itd-6RepoPrompt over MCP is one opt-in reviewer route, beside the host's own agents
- itd-42Grill Reads an Intent Against the Brief and Its Siblings, Not Just the Glossary
- itd-47Oracle-Backed Gates Pass Honestly Without A Human In The Loop
- itd-113The MCP Front Door Opens — abcd's Core Verbs From Any MCP-Capable Harness
- itd-116Validated GitHub Issues Become Ledger Entries Without Retyping
- itd-125The Lifeboat Verdict Says What It Is
- itd-160Eight typed cross-references point at targets absent from the tree — adr-22 supersedes adr-14, adr-15 and adr-17; adr-25 supersedes adr-8; adr-27 supersedes adr-16; adr-28 supersedes adr-18; adr-35 supersedes adr-4 (all retired under retire-the-name); itd-3 names spec_id spc-1 which has no file — and nothing checks supersedes targets today. The 2026-08-21 site investigation counted six; the in-session grep found eight. The planned site build arms the detector via the .abcd/site-baseline.json ratchet, seeded with what the build finds, and the tombstones-or-stubs question (itd-136/itd-137) decides how they render
- itd-2609081951381895abcd ships an OpenAI-compatible API adapter, and a provider serves only the models it lists
- itd-2609201916056194A role runs through the command-line harness the operator chose, and every fall back to the host is recorded
- itd-2610030810370060abcd's interviews run in a plain Terminal, with the same question layout
- itd-2610030821294016Connecting a model service from inside your coding session looks up the details and offers the choices
- itd-2610141646126492A librarian turns sources into a quoted reading pack
- itd-2610171228577260A product thinker settles a visual design in rounds that abcd runs end to end
- spc-11installable-versioned-plugin
- spc-30the-lifeboat-verdict-says-what-it-is-disembark-oracle-become
- spc-38alice-opens-the-record-explorer-and-reads-the-whole-developm
- spc-52dangling-supersedes-and-spec-targets-nothing-checks-them
- spc-2609211918551301coherence-aware-grill
- spc-2610030911534855a-person-can-run-abcd-s-interviews-in-a-plain-terminal