You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(provider): split USAi provider facts from agent config rendering #481
Implement ADR-0030's provider-configuration split: usai-provider exports provider facts, and each agent kit renders those facts into the agent's native config format.
Define the neutral provider facts exported by usai-provider: endpoint, key environment variable, model catalog, and any required metadata.
Stop treating usai-provider as the owner of every agent's rendered config format.
Have the OpenCode agent kit render the OpenCode-specific provider config from those facts.
Keep agent config merge semantics inside the agent layer; acq must not deep-merge agent config files.
Deferred Decisions
Additional agents beyond OpenCode can be added incrementally once the fact/render split exists.
Exact model-catalog refresh behavior remains governed by existing USAi model-sync decisions unless this increment proves a gap.
Acceptance Criteria
The provider facts are represented once in neutral form.
OpenCode config is rendered by the OpenCode agent kit.
Existing provider behavior remains stable for users.
Tests cover fact export and OpenCode rendering without requiring network access.
Orchestration Notes
Implementation should be done by an authoring sub-agent and reviewed by an independent adversarial review sub-agent. Review findings must be addressed before the increment is accepted.
Status check against what's already landed on refactor/acq-devenv-base-image (ADR-0030 PR #474), so this issue's scope stays accurate:
Already shipped on that branch (commit 31d0588f, "feat(provider): centralize usai provider facts"): acq.backends/common.sh now exposes named USAi provider facts — USAI_PROVIDER_HOST, USAI_PROVIDER_BASE_URL, USAI_PROVIDER_KEY_ENV, USAI_PROVIDER_MODELS_URL, USAI_PROVIDER_KEY_MGMT_URL — replacing scattered hardcoded constants. A follow-up commit (77ee43df) also defines a concrete artifact contract for the usai-provider kit to publish these facts to acq: provider-facts/usai.env, parsed as inert data, with explicit precedence (--host/--env flag > artifact > acq fallback).
Scope this covers: endpoint/host/key-env-NAME facts consumed by acq for its own lifecycle and credential plumbing (secret binding, key validation, network/DNS diagnostics).
Scope this does NOT cover, and is still open: the model catalog itself — which models exist, their context/output limits, and pricing. That's still owned entirely inside the usai-provider kit today, which renders opencode.jsonc directly (agentic-coding-patterns#417, just merged, refreshes that catalog under the current architecture). The "each agent kit renders provider facts into its own config format" half of this issue's scope — specifically for the model catalog — hasn't started yet.
I looked at going further and proposing a 3-tier split (facts / cross-harness defaults / live-polling adapter per harness) and ran it through a 7-role adversarial consensus review before writing anything. Unanimous reject (7-0) — not on the facts/render idea itself, which several voters said they'd approve, but on: (a) live in-guest polling trading a determinism/reproducibility guarantee for a freshness gain that a maintainer-run sync + PR already gets at zero new runtime surface, (b) a harness-agnostic permission vocabulary designed against exactly one consumer, (c) sequencing — holding a CI-green user-facing fix (#417) behind a speculative refactor, and (d) pulling #485's install/entrypoint scope into this issue.
Given that and what's already landed, I'd suggest this issue's remaining scope stay narrow: extend the existing facts artifact (or a sibling one) to include the model catalog, and have the OpenCode agent kit render it — no new runtime-fetch pattern, no new cross-harness vocabulary, both deferred until a second harness kit actually needs them.
@mogul — found a concrete shape mismatch between your two increments here and our patterns-side producer (GSA-TTS/agentic-coding-patterns#436, merged), while checking in on this issue.
Your acq_provider_facts_load_from_kit() (commit 08a00b4) fetches the pinned usai-provider kit ref host-side and looks for:
<fetched-kit-dir>/provider-facts/usai.env
...a flat KEY=value file with keys ACQ_PROVIDER_FACTS_SCHEMA, ACQ_PROVIDER_ID, ACQ_PROVIDER_HOST, ACQ_PROVIDER_BASE_URL, ACQ_PROVIDER_MODELS_URL, ACQ_PROVIDER_KEY_ENV, ACQ_PROVIDER_KEY_MGMT_URL, optional ACQ_PROVIDER_BIND_HOSTS — read at the pinned kit ref, before any sandbox exists.
usai-provider's actual producer (#436, Layer 1 of ADR 0003 — GSA-TTS/agentic-coding-patterns#423) writes /var/lib/acq/models/providers/usai.json — JSON, inside the running guest, at sandbox startup. Different path, different format, different producer timing entirely. Your loader is fully wired into acq run's dispatch path (confirmed) and currently finds nothing, silently falling back to the transitional defaults you built for exactly that case — which is working as designed, just not yet doing anything real.
These need to converge on one artifact. Given your loader already fails closed on a malformed file and is tested (101/101), and it's the piece other things (secret binding, USAI_PROVIDER_BIND_HOSTS) already depend on, I'd lean toward making usai-provider ship a static, kit-tree provider-facts/usai.env file in your exact shape (in addition to or instead of the current runtime JSON write) rather than asking your loader to also understand a guest-runtime artifact it can't reach pre-create anyway. Want me to open a patterns-side issue to add that file in your exact format, or do you have a preference on which side changes?
Implemented and shipped in v4.0.0 via #474 (with corrective #549). Provider facts are split via acq_provider_facts_load_from_kit reading provider-facts/usai.env, with fallback. The PR's Closes: footer did not auto-close this because the collapsed-stack squash merge dropped the closing keyword references; closing manually now that the work is on main and released.
Activity
wz-gsa commentedon Sep 17, 2026
Status check against what's already landed on
refactor/acq-devenv-base-image(ADR-0030 PR #474), so this issue's scope stays accurate:Already shipped on that branch (commit
31d0588f, "feat(provider): centralize usai provider facts"):acq.backends/common.shnow exposes named USAi provider facts —USAI_PROVIDER_HOST,USAI_PROVIDER_BASE_URL,USAI_PROVIDER_KEY_ENV,USAI_PROVIDER_MODELS_URL,USAI_PROVIDER_KEY_MGMT_URL— replacing scattered hardcoded constants. A follow-up commit (77ee43df) also defines a concrete artifact contract for theusai-providerkit to publish these facts toacq:provider-facts/usai.env, parsed as inert data, with explicit precedence (--host/--envflag > artifact > acq fallback).Scope this covers: endpoint/host/key-env-NAME facts consumed by
acqfor its own lifecycle and credential plumbing (secret binding, key validation, network/DNS diagnostics).Scope this does NOT cover, and is still open: the model catalog itself — which models exist, their context/output limits, and pricing. That's still owned entirely inside the
usai-providerkit today, which rendersopencode.jsoncdirectly (agentic-coding-patterns#417, just merged, refreshes that catalog under the current architecture). The "each agent kit renders provider facts into its own config format" half of this issue's scope — specifically for the model catalog — hasn't started yet.I looked at going further and proposing a 3-tier split (facts / cross-harness defaults / live-polling adapter per harness) and ran it through a 7-role adversarial consensus review before writing anything. Unanimous reject (7-0) — not on the facts/render idea itself, which several voters said they'd approve, but on: (a) live in-guest polling trading a determinism/reproducibility guarantee for a freshness gain that a maintainer-run sync + PR already gets at zero new runtime surface, (b) a harness-agnostic permission vocabulary designed against exactly one consumer, (c) sequencing — holding a CI-green user-facing fix (#417) behind a speculative refactor, and (d) pulling #485's install/entrypoint scope into this issue.
Given that and what's already landed, I'd suggest this issue's remaining scope stay narrow: extend the existing facts artifact (or a sibling one) to include the model catalog, and have the OpenCode agent kit render it — no new runtime-fetch pattern, no new cross-harness vocabulary, both deferred until a second harness kit actually needs them.
mogul commentedon Sep 17, 2026
Implemented the quickstart-side provider-facts consumer path on
refactor/acq-devenv-base-image.Commit:
c8150e3 feat(provider): load usai facts artifactWhat landed:
acq_provider_facts_load FILEto parseprovider-facts/usai.env-style metadata as data, not shell.USAI_PROVIDER_BIND_HOSTSso future provider facts can distinguish API host from credential binding hosts.USAI_PROVIDER_BIND_HOSTS, preserving current defaults and existing explicit--host/--envsidecar precedence.Verification:
bash -n acq.backends/common.sh acq.backends/sbx.sh acq.backends/msb.shgit diff --checkprintf %s\\n acq.backends/common.sh acq.backends/sbx.sh acq.backends/msb.sh test/bats/50-kit-list-completeness.bats | xargs -r -n8 shellcheck --severity=warning./scripts/test-acq-bats test/bats/50-kit-list-completeness.bats test/bats/40-secret-set.bats test/bats/71-msb-provision-secrets.bats test/bats/77-usai-rotate.bats test/bats/30-dispatch-routing.bats(98/98)Still deferred:
usai-providerkit ref and calling the loader automatically.mogul commentedon Sep 17, 2026
Added the second quickstart-side provider-facts consumer increment.
Commit:
08a00b4 feat(provider): load facts from usai kitWhat landed:
acqnow callsacq_provider_facts_load_from_kit "$USAI_KIT"after backend resolution.provider-facts/usai.envis absent in the pinnedusai-providerkit,acqkeeps the transitional fallback defaults.acqrefuses to continue rather than partially applying bad provider facts.Verification:
bash -n acq.backends/common.sh acq.backends/sbx.sh acq.backends/msb.shgit diff --check./scripts/test-acq-bats test/bats/50-kit-list-completeness.bats test/bats/40-secret-set.bats test/bats/71-msb-provision-secrets.bats test/bats/77-usai-rotate.bats test/bats/30-dispatch-routing.bats(101/101)Still deferred:
usai-providerartifact exists at the pinned ref.wz-gsa commentedon Sep 21, 2026
@mogul — found a concrete shape mismatch between your two increments here and our patterns-side producer (GSA-TTS/agentic-coding-patterns#436, merged), while checking in on this issue.
Your
acq_provider_facts_load_from_kit()(commit08a00b4) fetches the pinnedusai-providerkit ref host-side and looks for:...a flat
KEY=valuefile with keysACQ_PROVIDER_FACTS_SCHEMA,ACQ_PROVIDER_ID,ACQ_PROVIDER_HOST,ACQ_PROVIDER_BASE_URL,ACQ_PROVIDER_MODELS_URL,ACQ_PROVIDER_KEY_ENV,ACQ_PROVIDER_KEY_MGMT_URL, optionalACQ_PROVIDER_BIND_HOSTS— read at the pinned kit ref, before any sandbox exists.usai-provider's actual producer (#436, Layer 1 of ADR 0003 — GSA-TTS/agentic-coding-patterns#423) writes/var/lib/acq/models/providers/usai.json— JSON, inside the running guest, at sandbox startup. Different path, different format, different producer timing entirely. Your loader is fully wired intoacq run's dispatch path (confirmed) and currently finds nothing, silently falling back to the transitional defaults you built for exactly that case — which is working as designed, just not yet doing anything real.These need to converge on one artifact. Given your loader already fails closed on a malformed file and is tested (101/101), and it's the piece other things (secret binding,
USAI_PROVIDER_BIND_HOSTS) already depend on, I'd lean toward makingusai-providership a static, kit-treeprovider-facts/usai.envfile in your exact shape (in addition to or instead of the current runtime JSON write) rather than asking your loader to also understand a guest-runtime artifact it can't reach pre-create anyway. Want me to open a patterns-side issue to add that file in your exact format, or do you have a preference on which side changes?chore(kits): pin patterns v1.11.0
chore(kits): pin patterns v1.11.0
chore(kits): pin patterns v1.11.0
mogul commentedon Oct 6, 2026
Implemented and shipped in v4.0.0 via #474 (with corrective #549). Provider facts are split via acq_provider_facts_load_from_kit reading provider-facts/usai.env, with fallback. The PR's
Closes:footer did not auto-close this because the collapsed-stack squash merge dropped the closing keyword references; closing manually now that the work is onmainand released.