feat(spawn): three-level provider selection, skip-layer resolution, one searchable select (ADR-0030) #67
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/coding-lab!67
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/66"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #66
What ships
Three-level agent-CLI selection (per-spawn pick → repo override → global default, AFK-symmetric, ADR-0030 amending ADR-0021):
0006(sqlite + postgres):repos.providernullable (stamped rows reset to NULL — never operator-chosen), newrepos.afk_provider_default.provider_default(seeded to the first registered provider) andspawn_provider_default_afk(empty = inherit).reposvc.DefaultProviderdeleted.POST .../instancesaccepts optionalprovider(strict);PATCH /repos/{id}+POST /reposacceptprovider/afk_provider_default(validated, null = inherit); settings PATCH validates the new keys.Skip-layer resolution (
ResolveProvider+ reworkedResolveModelEffort): a default-layer value missing from the effective provider's catalog (registry, for provider ids) is treated as unset and falls through; final fallback = the catalog's first entry; an empty catalog resolves to""and omits the CLI flag. Explicit request values stay strict (400). This defuses the seeded claude-shapedopus[1m]default 400-ing every AFK launch on a second provider's repo, and theHasOption([], "") == falseempty-efforts trap. Backend now mirrors the SPA'sresolveSpawnOptionexactly.One searchable select (
web/src/components/Select.tsx, no new deps): chip + form-field skins, ARIA listbox with full keyboard nav, automatic search input at ≥8 options (case-insensitive over label+value), prefer-below flip+clamp placement measured againstvisualViewport— fixes the repo panel clipping off-screen above the composer. Absorbs CatalogSelect's inherit + "(not in catalog)" semantics and the repo picker's disabled/status rows;CatalogSelectdeleted, all call sites migrated.UI wiring: composer Agent chip only at ≥2 registered providers (single-provider UI stays pixel-identical); ephemeral per-spawn pick resets on repo change; model/effort picks reset when the effective provider changes (fixes the latent foreign-pick 400); effort chip hidden on an empty catalog; AddRepo + RepoSettings agent selects with inherit entries; RepoSettings base model/effort free-text → catalog selects (stale "M3" hint removed); global Settings renders base + AFK defaults against the drafted default providers instead of
providers[0]; nothing auto-clears on a provider flip — foreign values show "(not in catalog)" and stay reversible.Docs: ADR-0030 (amends ADR-0021, touches ADR-0025, references ADR-0026 unchanged); CONTEXT.md provider/AFK-default entries updated.
Verification
CGO_ENABLED=0 go test ./...green (only pre-existing sandbox-environmentalinternal/tmuxxintegration failures, identical on pristine main);go vet+gofmtclean.eslintclean,prettier --checkclean,tsc --noEmit && vite buildgreen; embedded-UI binary builds (go build -tags ui)."", and THE two-provider scenario (AFK on provider B with the claude-shaped global default resolves B's first model + empty effort, no 400) at unit and HTTP level.🤖 Generated with Claude Code
https://claude.ai/code/session_012iM5UvodpD714c2ASt9WHt