Development record
abcd ships an OpenAI-compatible API adapter, and a provider serves only the models it lists
Press Release
An OpenAI-compatible API adapter reaches a configured provider for the roles and judgements pointed at it, and serves only the models that provider's list allows.
"I wanted one cheap decision model through OpenRouter, and I wanted to be certain nothing else of mine would ever go through it," said a product thinker configuring the first aggregator. "The adapter takes a base URL and a key name, the provider block lists the models it may serve and nothing I left off it goes through, and the run record shows the model that actually answered."
Why This Matters
adr-25 names an API oracle backend and nothing implemented it. The first need arrived with Jev (TypeSafe AI, September 2026), a decision model reachable through OpenRouter, which speaks the OpenAI-compatible protocol; the same adapter serves a local OpenAI-compatible server with no key. The product thinker's condition, ruled on 2026-09-22 (adr-2609221009491186), is that an aggregator serves only listed models, so a frontier model the person pays for through the host is never billed or routed through a third party unasked; the vendor denylist that ruling put above the list is retired by ruling H9 of 2026-09-29 (adr-2609300107513982), and the list alone decides.
Mechanism
We expect a default-deny list per provider to make the aggregator serve only what the person meant, because a route that must be listed is a route someone wrote down; shown wrong if a frontier model is ever billed through the adapter.
Scope Conditions
- Holds for providers that speak the OpenAI-compatible chat protocol; a provider with its own protocol is its own adapter.
- Holds where the credential can be named in the machine's configuration or the environment; a provider that needs an interactive login is out of reach.
What's In Scope
- Configuration:
oracle.api.<provider>withbase_url,key(a name, resolved from the machine's configuration or the environment), andmodels(the allowlist); roles and judgement types are pointed at<provider>/<model>. - The refusal: a role or judgement configured for a model not on its provider's list is refused when the configuration is read, before any call, naming the list; the list alone decides, so abcd bundles no vendor denylist, and a listed model an
oracle.denylistentry the configuration writes matches is refused the same way, naming the entry. - The call: the same prompt, inputs and output contract the host sub-agent gets, over the protocol; the transcript captured into the same store.
- The record: provider, model asked for and model reported, per call, in the run record.
- Unconfigured: nothing changes and no network call is attempted (adr-25's default).
- The one-time setup through the credential store (itd-2609221017023290, adr-2609221017021499), in itd-63's explain-then-install mode: when
ahoytakes a repository over, or is run bare, and no provider is configured, it explains what an aggregator is, what abcd would use it for (decision models and cheap judgements), what works without it (everything, on the host), and offers the walkthrough; on yes it asks where the key should live, the person's choice of three: a setup accessible separately from abcd (an existing OpenRouter or opencode configuration or a named environment variable; abcd stores only the name), abcd-only (the user-level~/.abcd/store, owner-only permissions), or the platform keychain (macOS Keychain; the secret service on Linux), with the keychain named as the recommendation in the prose above the choice, never as a marked option; then it writes the provider block with the first allowlist and verifies with one call. The key never enters the harness's settings or the repository. - Security review before it ships: it sends prompts to a network endpoint under a credential.
What's Out of Scope
- Provider routing (
:nitro,:floor) and any per-request learned router; the adapter asks for the model it is given. - A model's quality judgement (the tier's, itd-2609170822093401).
- Anything generative through a decision model (itd-2609221009495079).
Decisions
Ruled by the product thinker on 2026-09-21, in the interview that filed and planned this intent (adr-2609221009491186 records the vocabulary rulings it rests on):
- Default-deny per provider with a vendor denylist above it (adr-2609221009491186). Amendment, 2026-09-30: ruling H9 of 2026-09-29 retires the bundled vendor denylist; the provider's allowlist alone decides, and
oracle.denyliststays as an optional extension the configuration writes (adr-2609300107513982, which supersedes adr-2609221009491186 and changes its decision 2 only). - OpenRouter is configuration of this adapter, not code.
- The first models listed are decision models; frontier models stay on the host.
- The setup is a one-time walkthrough at
ahoy, and the key's home is the person's choice of three (ruled 2026-09-22): a setup outside abcd, abcd-only on the machine, or the platform keychain, recommended in prose. Basic by default, the adapter as the optional upgrade.
Taken in the implementing lane (autonomous run A, 2026-09-26), within the rulings above:
- The external and keychain homes are deferred to the credential store (2026-09-26). The key is read through the interim credential source,
internal/core/credential(~/.abcd/credentials.json, mode 0600, owner-only, no symlink), which reads one home. This lane builds the write for that home alone, the abcd-only one. The environment-variable-or-external-tool home and the platform keychain (thesecuritycommand on macOS, the secret service on Linux) are built by itd-2609221017023290, the credential store, which replaces the source's backing and not its interface; until it lands,abcd ahoy connectrefuses either home naming itd-2609221017023290, before any call and any write, and the explanation names all three homes with the keychain recommended in prose. A fourth answer,none, sets up a local server that takes no key. - The walkthrough is a verb the person runs, with the key on stdin (2026-09-26).
ahoyexplains the adapter as an optional gap and onabcd ahoy --providers, and the setup isabcd ahoy connect <provider>, rather than a question the install pass asks: the install prompter echoes every answer into its transcript, a host's question tool would put the key in an agent's context, a flag would leave it in the process listing and the shell history, and a terminal would echo it as it is typed. Declining is not running it, and changes nothing. - Verify, then write (2026-09-26). The verification call is made with the key in memory before anything is written, and a failed verification writes nothing, so a wrong key or an unlisted model never leaves a half-configured provider behind.
- A provider block sits on the machine alone (2026-09-26), and so does a route to a provider that holds a key (amended 2026-09-29).
oracle.api.<provider>names the address a key is sent to, so a repository's.abcd/config.jsondeclaring it is refused; a checkout must never be able to aim the person's key at a server of its choosing. Denylist extensions (oracle.denylist) may sit in either layer. A route (oracle.roles.<agent>,oracle.judgements.<type>) to a provider that holds a key sits on the machine alone: only a route the person set up on their own machine may spend their paid key, so a repository's route to such a provider is skipped when the configuration is read, with a diagnostic naming the route and~/.abcd/config.jsonas where to set it, and the rest of the configuration loads, the machine's own route to that name applying in its place (the technical facilitator's ruling CD2 of 2026-09-29 chose the skip over refusing the whole configuration; a route the denylist matches is still refused). A provider holds a key when its block names akeycredential; that is judged from the block alone, never by reading the credential store, so no secret is read to decide it and a block that names a key counts as keyed before its key is stored. A repository's route to a provider whose block names no key (a local server) is admitted and wins per name, a--routethe person types is unaffected, and a route naming a provider this machine has not configured stays on the host with a diagnostic. Amendment, 2026-09-29: the route half of this decision as ruled on 2026-09-26 said routes "may sit in either layer"; the product thinker's ruling AA(b) of 2026-09-29 reverses that for a provider that holds a key, and this text is the decision as it now stands (adr-2609221009491186 carries the consequence). - A provider claims no tier (2026-09-26). A provider is reached by a role or a judgement type pointed at
<provider>/<model>, or by a--routenaming it, never by a tier alone, soConnections.Servesanswers false for every tier. The bundled denylist isanthropic/*, the minimum ruled, and a reported model it matches discards the answer. Amendment, 2026-09-30: no denylist is bundled (ruling H9, adr-2609300107513982); a reported model anoracle.denylistentry the configuration writes matches discards the answer.
Taken in the wiring lane (autonomous run A, 2026-09-30), within the product thinker's ruling DR5 of 2026-09-29, which the decision log records on its dated entry for that ruling ("file-reading agents on a paid provider: only self-contained agents by default ... plus a central override, a settings list the person keeps, machine-level, not changeable by agents or repos"):
- A paid provider takes only a self-contained agent by default (2026-09-30, DR5). A provider call carries no tools, so an agent that reads files cannot read them there. A provider whose block names a key admits an agent only if it is on a list compiled into the binary, default deny, as ruling AA(a) asked for an allow list: the four cold-reading positions, each handed one assembled, manifest-hashed bundle and nothing else. Every other agent is refused before any call, and before its verb writes anything, naming DR5 and the override. An agent joins the list only with a test proving its request carries all its input. A provider whose block names no key (a local server) spends nothing of the person's and is outside DR5.
- The override is
oracle.bundled_context_providers, on the machine alone (2026-09-30, DR5). It lists the providers that may take bundled-context requests for file-reading agents, read from~/.abcd/config.jsonthrough the same machine-layer seam the provider blocks use; a repository's.abcd/config.jsondeclaring it is refused, as a repository's provider block is, and a name this machine has not configured is a diagnostic that admits nothing. It inherits the machine layer's trust in$HOME, pending iss-2609300012273350. A named provider takes a file-reading agent only once abcd builds that agent's bundle, and none is built: which files travel, a size cap and a scan before sending are choices no ruling makes, so every file-reading agent stays refused with the override too, and the refusal says so. - The verb that emits the request sends it (2026-09-30).
intent audit <itd-N>,intent consistency,intent audit --owed(its head),launch shipandspec close's review re-emit send the request they emitted, with the agent's own prompt from the plugin root, and run the answer through their own ingest; the receipt names the provider as the connection used, with the call record. A cold reading is sent byreading ingest --dispatch <rdg-N>, the parked run's bundle with the position's definition, becausereading assemblekeeps its invocation to a position and a target. A provider that could not be reached leaves the step to the host with one stderr line; any other failure exits 2. - A host payload on a provider route is refused (2026-09-30). An ingest handed a payload the host produced while its agent is routed to a provider refuses it at exit 2, since its receipt would name the provider for work the host did;
--route <agent>=host-decideskeeps one run on the harness. The four disembark agents read the packed lifeboat, and no verb builds a request carrying it, so none of them is sent to a provider and their ingests refuse a provider route this way. - The close stands whatever its review does (2026-09-30).
spec closesends the review it emits when the auditor is routed to a provider and says what came back on stderr; a refusal (DR5 on a keyed provider) or a failed call leaves the review owed, as a warning. A cut the composer answers through a provider stages no--payload-dir.
Open Questions
None open.
Acceptance Criteria
- Given
oracle.api.openrouterconfigured with a base URL, a key name and a model list, when a role or judgement pointed at a listed model runs, then the call goes over the OpenAI-compatible protocol with the host sub-agent's prompt, inputs and output contract; unconfigured, nothing changes and no call is attempted. - Given a role or judgement configured for a model not on its provider's list, when the configuration is read, then it is refused before any call, naming the list.
- Given a model on its provider's list, whichever vendor made it, when the configuration is read, then it is admitted, because the provider's list alone decides and abcd bundles no vendor denylist; a listed model an
oracle.denylistentry in the repository's or the machine's configuration matches is refused the same way, naming the entry. - Given the key, when the adapter reads it, then it comes from the machine's configuration or the environment by name, and no credential is written into the repository.
- Given a call through the adapter, when the run record is read, then it names the provider, the model asked for and the model the provider reported.
- Given a repository abcd takes over with no provider configured, when
ahoyruns, then it explains the aggregator, its use and what works without it, and offers the walkthrough; declining leaves the host as the only route and says so. - Given the walkthrough accepted, when it asks where the key lives, then it offers the three homes (outside abcd; abcd-only, owner-only; the platform keychain) with the keychain recommended in the prose above the choice, writes the provider block with the first allowlist, verifies with one call, and writes nothing into the harness's settings or the repository.
- Given the lane, when it ships, then a security review of the network path and the credential handling is on its record.
Audit Notes
Changed on 2026-09-30 by the technical facilitator's ruling H9 of 2026-09-29, recorded as iss-2609300110451242: criterion 3 read "Given a listed model whose prefix matches the vendor denylist, when the configuration is read, then it is refused the same way, and an allowlist entry does not override it." H9 retires the bundled anthropic/* denylist, so the criterion's reading changes from a vendor refusal to the allowlist alone, and the text above is the criterion as it now stands. adr-2609300107513982 supersedes adr-2609221009491186, whose decision 2 it revises.
- 2026-10-02 — Amendment to the closing clause of decision 8 ("a route naming a provider this machine has not configured stays on the host with a diagnostic"), which stands as written as the decision ruled on 2026-09-26 and 2026-09-29. The technical facilitator's rulings CD3 and CD4 of 2026-10-02 narrow it for a repository's route. CD4, verbatim: "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": a repository's route to a provider this machine has not configured no longer displaces the machine's own route of the same name, which applies in its place, and the route stays on the host with a diagnostic only where the machine has no route for that name. CD3, verbatim: "SKIP THAT ROUTE, WARN — skip with a diagnostic; the machine's route for the role applies; adr-25 amended": a repository's route naming a model a configured keyless provider does not offer is skipped with a diagnostic rather than refusing the configuration, and the machine's route for the role applies. Both are built in lane routeSkip of autonomous run A, not on the default branch at this note's base; recorded by lane rd2.
- 2026-10-02 — Declared mutual pair with itd-2609170822093401 (the technical facilitator's ruling CY2 of 2026-10-02, verbatim: "SAME, DECLARED PAIRS — each direction names the piece it needs"). itd-2609081951381895's builds_on itd-2609170822093401 needs the routing seam: the per-agent route and the invocation-time
--routeoverride that point a role or a judgement type at<provider>/<model>, the only ways a provider is reached (the adapter's decision 9). itd-2609170822093401's builds_on itd-2609081951381895 needs the provider connections its winning rows are resolved against, and the adapter's refusal of a setting its provider does not accept (its out-of-scope list names the adapter for both). Both edges stand. The record has no field record-lint's edge_cycle rule reads as a declared pair, so the linter still reports the cycle at warn until it does (iss-2610020836255174). Each piece is read from the two records' own scope, criteria and decisions; the ruling names none. Recorded by lane rd2 of autonomous run A.
Fidelity review OWED (receipt rcp-ac4127f9199c).
Grounds
- pursued: Jev is reachable only this way and the person's subscription must stay where Opus runs; we expect the listed route to serve only what was meant; shown wrong if a frontier model is ever billed through the adapter
Frontmatter
| id | itd-2609081951381895 |
|---|---|
| type | intent |
| lifecycle | shipped |
| kind | standalone |
| severity | minor |
.abcd/development/intents/shipped/itd-2609081951381895-abcd-ships-an-openai-compatible-api.md
open on GitHub ↗ · commit history ↗
References4
- itd-6RepoPrompt over MCP is one opt-in reviewer route, beside the host's own agentsrelated
- itd-2609170822093401abcd proposes the model each agent deserves, and facilitates it where it canbuilds on
- itd-2609201916056194A role runs through the command-line harness the operator chose, and every fall back to the host is recordedrelated
- itd-2609221009495079abcd's typed judgements can run through a decision adapter, measured in a lab before it decides anythingrelated
Referenced by13
- 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-2609300107513982A provider adapter's allowlist alone decides which models it serves, and abcd bundles no vendor denylistrelated
- iss-2609291925393913The live check of the OpenAI-compatible API adapter against a real paid provider is owed to a person. itd-2609081951381895 may close on tests against a simulated OpenAI-compatible service under the product thinker's ruling of 2026-09-29 on paid services (live site setup, the API adapter, the decision adapter), with the live paid check recorded as owed and done later by a person. Owed: with the person's own key stored through abcd ahoy connect, send one step through the adapter to a real aggregator and confirm that a model the provider block lists answers, that a model it does not list is refused before anything is sent, and that the provider's billing shows only the listed model; record the result on this record and resolve it.related
- iss-2610262043257570itd-1 says Audit Notes fill only when the audit is run by hand; itd-2609081951381895 has spec close send the review and ingest the answerrelated
- iss-2610262044237764The cold-reading draft introduces a cold reading as new, while a shipped record already dispatches cold readings by positionrelated
- iss-2610262044285635Tier routing sends a row to a provider that can serve its tier, but the shipped adapter rules that no provider serves any tierrelated
- iss-2610262045372683itd-6 rules direct model API integrations out and routes everything through RepoPrompt; itd-2609081951381895 ships an OpenAI-compatible API adapterrelated
- itd-2609170822093401abcd proposes the model each agent deserves, and facilitates it where it canbuilt on by
- itd-2609221009495079abcd's typed judgements can run through a decision adapter, measured in a lab before it decides anythingbuilt on by
- itd-2609221017023290abcd keeps every external credential the same wayrelated
- itd-2609301918174237A remote provider takes a file-reading agent only as a fixed, blanked, capped bundlebuilt on by
- spc-2609221011153746abcd-ships-an-openai-compatible-api-oracle-adapter-the-firstimplemented by
mentions23
- adr-25The LLM is host-delegated by default; oracles are opt-in adapters
- dcn-26092200000000012026-09-22 — Model routing, after an independent research pass (product thinker, at an interactive interview). Jev (TypeSafe AI, on OpenRouter) is a typed-decision model, not a router: it fits abcd's closed-option judgements and nothing generative. Rulings: a provider adapter serves only the models it lists under a vendor denylist no listing overrides, everything else on the host (adr-2609221009491186); the OpenAI-compatible API adapter is planned with OpenRouter as configuration, a one-time walkthrough at ahoy and the key kept out of the harness (itd-2609081951381895); a decision adapter for the typed judgements runs in shadow as an abcd lab and a research note is the evidence a ruling turns a judgement type on with (itd-2609221009495079); escalation inside a lane is a rule on a failed fix round, recorded on the model tier (itd-2609170822093401); model per role, the pick and consistency are not routing and stand as ruled; itd-17's learned router is superseded. Every external credential abcd holds goes through one store with three homes the person chooses (adr-2609221017021499, itd-2609221017023290); the API adapter and the site setup read through it. The research is filed as research/notes/2026-09-22-jev-and-model-routing-sota.md.
- dcn-26092900000000072026-09-29 — The product thinker answered twenty-six owed rulings and the published-history question in one interview, asked one at a time by orchestrator abcd-23 of autonomous run A (recorded by lane recRulings for orchestrator abcd-cb). The answers are kept verbatim in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29.md`, dated 2026-09-29, and are restated here because that file is not committed. Published history is left as it is, with no rewrite. The build loop's fidelity audit runs once, on the lane that closes the spec, over the whole delivery (AI). On the vendor denylist the product thinker answered, verbatim: "I think we need an allow list rather than trying to catch a deny list." The interviewer's reading of that answer, recorded as a reading and not as the product thinker's words, is that the per-provider allowlist is the control and the vendor denylist is not extended to chase spellings, with whether the bundled `anthropic/*` entry stays as a backstop left to the technical facilitator (AA(a)). Only a route the person set up on their own machine may use their paid key, and a repository's own route to it is refused, which replaces the route half of itd-2609081951381895 decision 8 (AA(b)). The live site setup, the API adapter and the decision adapter may each close on tests against a simulated service, with the live paid check recorded as owed to a person (iss-2609291925387011, iss-2609291925393913, iss-2609291925398978). itd-111's last criterion is met by an agent's timing check on macOS plus the Linux CI run, so the intent may be finished. Automated dependency updates are switched on, pushed with a personal or app token the person creates and stores as a repository secret (itd-2609221842494980; creating the token is the person's act, and the lane builds everything else and names the secret it expects). itd-6 adds a Go MCP module, proposed for the person's explicit sign-off before it is fetched; closing itd-6 on a fake server was not ruled in this interview. (A later answer the same day, H1b in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md`, dated 2026-09-29, rules that it is not: itd-6 is finished only after running once against the real RepoPrompt app, a check owed to a person.) For itd-148: the store under the home folder wins (adr-2609091248200336); the store draft itd-2609091014076309 owns add, list and clean-up and itd-148 uses them; a session that declares itself the coordinator is exempt from the write block in the primary checkout and every other session is blocked; and the store draft is planned first, with nothing from the store draft, the merged-worktree clean-up included, built before its planning interview (Q4). itd-148's own wait is not part of that ruling: it follows from Q2, because itd-148 uses the store's verbs, and is carried by the `blocked_by` below. itd-148 and spc-42 are rewritten to match in this change, and itd-148 is now `blocked_by` the store draft. A release retrospective is seeded from a release, the intents a tag shipped (AD); itd-24 and its spec are rewritten to the release in this change. An unpointed route is refused naming the one setting to add, as built in 35100512e, so AC11 of itd-2609170822093401 is complete (BR1). A missed target becomes `next`, whatever the following release is numbered (BS1). Spec pieces keep "step" and the lane stages are renamed, a breaking change to the JSON fields `step`, `performed` and `refusal.step` that resolves iss-2609291313276243 and corrects the glossary entry `core/step.md` (BU1), and the old command spellings are removed in that same breaking release (BT1). The text board shows Later as a count only while the site and `--json` keep the full list (BV1), and an intent in progress appears only under Now (BV2). A pause of zero is allowed (BW1); drain stays in the agents' help list until it runs end to end (BX1); a managed repository must hold the drain eligibility decision in its own record, and drain refuses there until it does (BX2); a capture without a remedy is refused (BX3), which tightens the one-line capture friction `commands/capture.md` promises, so the lane that builds it reconciles that page, the principle wording and every caller that files a capture; a run's pick reason keeps the shared `pursued:` kind with its marker (BZ1); and an intent whose blocker was superseded waits on the successor, transitively (BZ2). The five itd-48 follow-ups are planned as one intent, drafted as itd-2609291923559186 (BT2), and all warn rules share one shrink-only baseline file in which a new warning fails, drafted as itd-2609291924469783 (BT3); both drafts wait on their planning interviews. Each ruling that contradicts a shipped behaviour or another record is amended in the change that builds it, not here. itd-7's planning interview stays owed.
- dcn-26093000000000062026-09-30 — The technical facilitator's ruling H9 of 2026-09-29 is applied (recorded by lane denyRetire of autonomous run A; the answer is kept verbatim in the local-tier file `.abcd/.work.local/scratch/reports/rulings-answered-2609-29-b.md`, dated 2026-09-29, and restated here because that file is not committed): the bundled `anthropic/*` vendor denylist is retired and a provider's allowlist alone decides which models it serves. adr-2609300107513982 supersedes adr-2609221009491186, revising its decision 2 and carrying decisions 1, 3, 4 and 5 forward word for word; itd-2609081951381895's criterion 3 and spc-2609221011153746 are amended to the allowlist-alone reading, with the old wording in the intent's Audit Notes (iss-2609300110451242). This answers the follow-up the 2026-09-29 entry above left to the technical facilitator under AA(a), whether the bundled entry stays as a backstop: it does not. Ruling Y (added 2026-09-26, from lane apiadapter: may a person remove a bundled entry on their own machine) closes as moot, since no bundled entry remains to remove. The detail H9 left to the lane, whether `oracle.denylist` survives as an optional repository or machine extension, is decided as keep: the setting already existed in both layers, and removing the bundled list leaves it working with no added code, which is the ruling's condition.
- dcn-26100200000000072026-10-02 — Ruling CD2 of the person as technical facilitator (2026-09-29, same interview and local-tier file as the DR3 entry above; recorded by lane rd2), verbatim: "repository route to a keyed provider: WARN AND SKIP that route (other commands keep working), not a hard LoadAPI refusal." Built: a repository's route to a provider that holds a key is skipped with a diagnostic and the machine's own route to that name applies in its place (`skipKeyedRoute` in `internal/core/oracle/config.go`; a repository's malformed route and malformed route name are skipped under the same ruling); decision 8 of itd-2609081951381895 and adr-2609221009491186 carry it.
- dcn-26100200000000122026-10-02 — Ruling CY2 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: "itd-14<->itd-15 and itd-2609081951381895<->itd-2609170822093401: SAME, DECLARED PAIRS — each direction names the piece it needs." Applied as CY1 above: both edges of each pair stand, and each of the four intents carries a dated Audit Notes line naming its pair and the piece each direction needs; edge_cycle still warns on both pairs until the linter can read a declared pair (iss-2610020836255174). This answers the ruling iss-2609300903551032's remedy waited on.
- 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.
- dcn-26100200000000222026-10-02 — Ruling DR5b-1 of the product thinker (2026-09-30, relayed by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), on the files sent with a file-reading agent to a listed paid provider, verbatim: "A FIXED LIST PER HELPER (e.g. reviewer: changed files + the spec)", with the note "will this be configurable per repo?", answered as DR5b-1b, verbatim: "ONLY YOUR PERSONAL SETTINGS may change a helper's list (machine layer widens or narrows); a repository's setting is ignored with a warning." The DR5b-2 answer below was applied to DR5b-1b without asking again: the per-helper lists change only in the owner's personal settings, per project. Not built at this entry's base, where every file-reading agent stays refused on a provider that holds a key (itd-2609081951381895 decision 11); the bundle these rulings shape is planned only through a planning interview still owed.
- dcn-26100200000000252026-10-02 — Ruling DR5b-4 of the product thinker (2026-09-30, a security-review addendum relayed by abcd-a2 [75597f]; same local-tier file as the H3-0 entry above; recorded by lane rd2), on coverage, verbatim: "TREAT ANY REMOTE LIKE PAID — every provider off this computer, keyed or keyless, needs the owner's personal list and gets the fixed file list, the owner's size cap and secret blanking; only on-machine helpers skip." It widens the scope of DR5's default, which itd-2609081951381895 decision 10 limits to a provider that holds a key, to every provider off the machine. Not built at this entry's base (see DR5b-1 above).
- iss-2609170818061083The oracle choice is one repo-wide value in .abcd/config.json (host-delegated | native | cli | api | mcp), so every delegated step reaches a model the same way. The choice should be configurable per task: some steps want a local model (a cheap, private first pass over a transcript), some want the harness to decide, some want the harness told to use a high-end frontier model (a release gate's semantic review, an intent audit) and some a cheaper one (a slug, a summary). Alongside the backend, the same per-task configuration should say whether the harness may use sub-agents for the step at all, and how many, so a fan-out review can be bounded and a single-pass composition kept to one. Today none of this is expressible: the backend is global, and sub-agent use is whatever the command page tells the host in prose. The task classes the agent trust contract already declares (capability_scope.task_classes) are the natural key; the api adapter draft itd-2609081951381895 would be the first backend such a table could route to.
- iss-2609290448510918The predecessor-store qualifier sweep reaches past the six intents iss-2609261536147903 named: outside drafts/ and those six, 192 citation sites across about forty intents name a spc-N at or below spc-70 that is not the citing intent's own spec, with no '(predecessor store)' on the line. Some are live cross-references (the cold-reading family's intents cite each other's live specs), and some are the predecessor store's (itd-4, itd-6, itd-29, itd-47 and itd-49 describe pre-rebuild work in its terms), so each site needs the same reading against the live spec it collides with; the specs charter's Two spc-N Namespaces section is the rule. Found while sweeping the pattern of iss-2609261536147903 in lane drainDrift3; a census script over intents/{planned,shipped,disciplines} reproduces the count.
- iss-2609300012273350The oracle and credential machine layer is whatever $HOME names: layered.RootsFor (internal/core/layered/layered.go:156) and credential.UserStore (internal/core/credential/store.go:92) both take os.UserHomeDir, which on Unix returns $HOME. An environment a repository can shape (a committed harness settings file whose env block sets HOME into the tree) would let a checkout supply the 'machine' ~/.abcd/config.json, and with it a keyed provider block and the machine routes that keyRoutes admits to spend a key, while the operating-system keychain still answers by the user's login session, so the repository's own route reaches the person's paid key through a machine layer it wrote. keyRoutes did not introduce this; it inherits the trust in $HOME.
- iss-2609300110451242Ruling H9 of 2026-09-29 retires the bundled anthropic/* vendor denylist, which changes the reading of itd-2609081951381895 acceptance criterion 3 (a listed model whose prefix matches the vendor denylist is refused at read, and no allowlist entry overrides it) and of adr-2609221009491186 decision 2: with no bundled list the provider's allowlist alone decides, so a listed model of any vendor is served, and only an oracle.denylist entry the repository or the machine writes refuses a listed model
- iss-2609300903551032Two more builds_on cycles sit in the intent store beside the runner and loop one: the drafts itd-14 and itd-15 each declare builds_on the other, and the planned itd-2609081951381895 (the OpenAI-compatible API oracle adapter) and itd-2609170822093401 (the oracle choice is one repo-wide value) each declare builds_on the other; record-lint's edge_cycle rule reports both
- iss-2610020836255174The intent record has no way to declare a mutual builds_on pair that record-lint's edge_cycle rule honours. The technical facilitator ruled on 2026-10-02 that three two-intent cycles stay as declared mutual pairs, each direction naming the piece it needs (CY1: itd-2609201916056194 and itd-2609201916151817; CY2: itd-14 and itd-15, itd-2609081951381895 and itd-2609170822093401), but the frontmatter offers only builds_on and blocked_by, and edge_cycle reports every strongly connected set whatever the records say, so the three pairs are declared only in each intent's Audit Notes and still read as cycles to the linter, and to anything that orders work by these edges. Until a declared pair is something the linter can read, edge_cycle cannot be promoted from warn to blocker without refusing the ruled pairs.
- iss-2610161734413178abcd cannot hold an OpenRouter call to one named upstream provider, and it records only part of what served it.
- itd-63The Amateur Coder Is Told What Is Being Installed And Why, Not Just Asked To Run A Command
- itd-2610030821294016Connecting a model service from inside your coding session looks up the details and offers the choices
- itd-2610161733316518One task done across a model matrix, re-runnably
- spc-2609180535002478abcd proposes the model each agent deserves, and facilitates it where it can
- spc-2609251028149555A failed fix round escalates one tier, and a provider route stays on its allowlist
- spc-2610031241482088connecting-a-model-service-from-inside-claude-code-works-out