Problem
ProviderModelSelector now takes a loading prop that disables its selects and renders "Loading providers…" instead of the caller's emptyProviderOption while the provider list is in flight. Without it, an empty providers array renders a picker whose only option is "Default (active provider)" / "Inherit (…)" — indistinguishable from a broken control.
The prop is wired for the CoS Schedule tab only (card quick-pins, plus all three pickers in the task config drawer). Every other picker still shows the bare sentinel during its own fetch window.
Sites still unwired
CoS page — same providers state, same in-flight window, already available at the render site as providersLoaded:
client/src/pages/ChiefOfStaff.jsx — TasksTab, AgentsTab, WorkflowTab receive providers but not providersLoaded.
TasksTab → TaskAddForm (~9 providers= call sites via TaskItem/SortableTaskItem) — note TaskAddForm also clears a pinned provider whenever enabledProviders is empty, which mid-fetch it always is; the flag prevents that by construction.
AgentsTab → RelaunchAgentModal, ResumeAgentModal (emptyProviderOption="Auto (default)").
WorkflowTab → AppOverridePanel → AppProviderPin (already accepts loading, just needs threading).
Pickers that fetch through useProviderModels: the hook already returns a loading flag for free at ~40 call sites; only 5 consume it (LoomEpisodeFeedback, LoomSeriesPlan, LoomEditorialAutomation, FableLoom, LoomEpisodeOutlinePlanner), and all 5 reach only disabled, never the label. Pass loading={loading} instead.
Also worth doing
getApps() and getCosLearningSummary() in ChiefOfStaff.fetchData still sit in the Promise.all whose tail is getCosActionableInsights (which fans out to cos.runHealthCheck() and detectIdleLeftoverBranches() — git work across repos). apps feeds the Schedule/Tasks/Agents app pickers, so it has the same user-visible empty-control symptom. The fix is the same .then(applyX) split; reuse the sameJsonShape identity guard so the earlier commit doesn't add a re-render per poll.
Acceptance
- No provider picker in the app renders a lone
emptyProviderOption while its list is still fetching.
apps commits on its own settle, with a sameJsonShape guard.
Follow-up to the Schedule-tab fix.
Problem
ProviderModelSelectornow takes aloadingprop that disables its selects and renders "Loading providers…" instead of the caller'semptyProviderOptionwhile the provider list is in flight. Without it, an emptyprovidersarray renders a picker whose only option is "Default (active provider)" / "Inherit (…)" — indistinguishable from a broken control.The prop is wired for the CoS Schedule tab only (card quick-pins, plus all three pickers in the task config drawer). Every other picker still shows the bare sentinel during its own fetch window.
Sites still unwired
CoS page — same
providersstate, same in-flight window, already available at the render site asprovidersLoaded:client/src/pages/ChiefOfStaff.jsx—TasksTab,AgentsTab,WorkflowTabreceiveprovidersbut notprovidersLoaded.TasksTab→TaskAddForm(~9providers=call sites viaTaskItem/SortableTaskItem) — noteTaskAddFormalso clears a pinned provider wheneverenabledProvidersis empty, which mid-fetch it always is; the flag prevents that by construction.AgentsTab→RelaunchAgentModal,ResumeAgentModal(emptyProviderOption="Auto (default)").WorkflowTab→AppOverridePanel→AppProviderPin(already acceptsloading, just needs threading).Pickers that fetch through
useProviderModels: the hook already returns aloadingflag for free at ~40 call sites; only 5 consume it (LoomEpisodeFeedback,LoomSeriesPlan,LoomEditorialAutomation,FableLoom,LoomEpisodeOutlinePlanner), and all 5 reach onlydisabled, never the label. Passloading={loading}instead.Also worth doing
getApps()andgetCosLearningSummary()inChiefOfStaff.fetchDatastill sit in thePromise.allwhose tail isgetCosActionableInsights(which fans out tocos.runHealthCheck()anddetectIdleLeftoverBranches()— git work across repos).appsfeeds the Schedule/Tasks/Agents app pickers, so it has the same user-visible empty-control symptom. The fix is the same.then(applyX)split; reuse thesameJsonShapeidentity guard so the earlier commit doesn't add a re-render per poll.Acceptance
emptyProviderOptionwhile its list is still fetching.appscommits on its own settle, with asameJsonShapeguard.Follow-up to the Schedule-tab fix.