Skip to content

fix: thread ProviderModelSelector's loading gate to the remaining provider pickers - #6106

Merged
atomantic merged 1 commit into
atomantic:mainfrom
Bryandero98:fix/provider-picker-loading-gate
Sep 3, 2026
Merged

fix: thread ProviderModelSelector's loading gate to the remaining provider pickers#6106
atomantic merged 1 commit into
atomantic:mainfrom
Bryandero98:fix/provider-picker-loading-gate

Conversation

@Bryandero98

Copy link
Copy Markdown
Contributor

Summary

  • ChiefOfStaff.fetchData now settles apps on its own read (appsRead, mirroring providersRead) instead of holding it hostage inside secondaryRead's Promise.all, with a sameJsonShape guard to keep array identity stable on an unchanged poll.
  • providersLoaded now flows from ChiefOfStaff down through TasksTabTaskAddForm/TaskItem/SortableTaskItem, AgentsTabRelaunchAgentModal/ResumeAgentModal, and WorkflowTabAppOverridePanelPerAppOverrideList (which already accepted the prop from the Schedule-tab fix, just wasn't fed by Workflow).
  • TaskAddForm's provider-reset effect was clearing a legitimately pinned provider on every mount, because enabledProviders is always empty mid-fetch — it's now gated on providersLoaded.
  • ResumeAgentModal renders its own <select>s rather than ProviderModelSelector; applied the same "Loading providers…" + disabled treatment inline instead of restructuring the modal (no dedicated test file existed for it, so I kept the change surgical).
  • The 5 useProviderModels consumers named in the issue (LoomEpisodeFeedback, LoomSeriesPlan, LoomEditorialAutomation, FableLoom, LoomEpisodeOutlinePlanner) now pass the hook's loading flag into ProviderModelSelector alongside the disabled prop they already wired.

Follow-up to the Schedule-tab loading-gate fix, per #6087.

Test plan

  • client/src/components/cos/tabs/AgentsTab.test.jsx
  • client/src/components/cos/tabs/RelaunchAgentModal.test.jsx
  • client/src/components/cos/tabs/schedule/AppOverrideRow.test.jsx
  • client/src/components/cos/tabs/TaskItem.test.jsx
  • client/src/components/cos/tabs/TasksTab.test.jsx
  • client/src/components/cos/tabs/WorkflowTab.providers.test.jsx
  • client/src/components/cos/TaskAddForm.test.jsx
  • client/src/components/fableloom/LoomEditorialAutomation.test.jsx
  • client/src/components/fableloom/LoomEpisodeFeedback.test.jsx
  • client/src/components/fableloom/LoomEpisodeOutlinePlanner.test.jsx
  • client/src/components/fableloom/LoomSeriesPlan.test.jsx
  • client/src/pages/FableLoom.test.jsx
  • biome lint --error-on-warnings on every changed file

🤖 Generated with Claude Code

@atomantic atomantic left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved

A clean, well-tested follow-up to #6087 that threads the providers-loaded gate and ProviderModelSelector's loading flag into the remaining COS and FableLoom provider pickers. The patch applies cleanly against main, all 14 covering test files pass (236 tests), every new prop defaults to a backward-compatible value, and the new self-committing apps read mirrors the already-shipped applyProviders pattern without introducing a new failure mode. No blocking findings; one non-blocking note on the shared wipe-on-transient-failure fallback.

Scope: Client-only: threads providersLoaded/loading from ChiefOfStaff through the Tasks/Agents/Workflow tabs, the task/agent modals, and five FableLoom ProviderModelSelector consumers.

💡 Non-blocking (1)

  • client/src/pages/ChiefOfStaff.jsx:249 — apps fetch failure clears last-good list, same as providers

Test evidence

  • NODE_ENV=test npx vitest run src/components/cos/tabs/AgentsTab.test.jsx src/components/cos/tabs/RelaunchAgentModal.test.jsx src/components/cos/tabs/schedule/AppOverrideRow.test.jsx src/components/cos/tabs/TaskItem.test.jsx src/components/cos/tabs/TasksTab.test.jsx src/components/cos/tabs/WorkflowTab.providers.test.jsx — 6 files, 106 tests passed
  • NODE_ENV=test npx vitest run src/components/cos/TaskAddForm.test.jsx src/components/fableloom/LoomEditorialAutomation.test.jsx src/components/fableloom/LoomEpisodeFeedback.test.jsx src/components/fableloom/LoomEpisodeOutlinePlanner.test.jsx src/components/fableloom/LoomSeriesPlan.test.jsx src/pages/FableLoom.test.jsx — 6 files, 59 tests passed
  • NODE_ENV=test npx vitest run src/pages/ChiefOfStaff.test.jsx src/components/ProviderModelSelector.test.jsx — 2 files, 71 tests passed (the ChiefOfStaff caller and the unchanged ProviderModelSelector contract)
  • ⏭️ npm test -w client — Full client workspace suite deliberately not run as review evidence: the sandbox denies network binds, GPU, and background services a minority of suites need, so a from-zero full run reports thousands of environment-driven failures unrelated to this patch; the 14 targeted files covering every patched component were run instead.

Notes

  • The PR description carries a Claude Code attribution footer, which the repo convention says PR descriptions should not include; a maintainer may ask the author to drop it.
Claims verified against the code
  • ProviderModelSelector's loading prop disables the provider, model, and effort selects and swaps the empty option for a Loading providers placeholder (client/src/components/ProviderModelSelector.jsx:212).
  • providersLoaded is stamped true only inside applyProviders, the single provider-list write path, so the flag can never be true without the list present (client/src/pages/ChiefOfStaff.jsx:189).
  • The new appsRead self-committing read is added to the settle barrier alongside healthRead and providersRead (client/src/pages/ChiefOfStaff.jsx:284).
  • LoomSeriesPlan destructures the hook's loading flag (client/src/components/fableloom/LoomSeriesPlan.jsx:384) and threads it into ProviderModelSelector (client/src/components/fableloom/LoomSeriesPlan.jsx:457); the other four FableLoom consumers do the same with their respective loading variables.
  • providersLoaded is passed from ChiefOfStaff into WorkflowTab, the tab that previously accepted the prop but was never fed it (client/src/pages/ChiefOfStaff.jsx:1247).

.then(applyProviders);
// Same rationale as providersRead above: apps commits on its own settle
// instead of waiting on the slower siblings in secondaryRead.
const appsRead = api.getApps().catch(() => []).then(applyApps);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Non-blocking — apps fetch failure clears last-good list, same as providers

The catch fallback on appsRead turns a transient fetch failure into an empty array, and applyApps (line 201) then overwrites the last-good apps state with an empty list instead of preserving it, so one failed poll blips the app pickers empty until the next successful fetch. This is not new: the providers path in applyProviders already has identical behavior and this PR mirrors it deliberately. The same function already preserves last-good for insights specifically to avoid this flicker, so a follow-up could make both the apps and providers self-commit reads keep the last-good list on a failed fetch instead of resetting to empty.

…vider pickers (atomantic#6087)

apps and providers now settle on their own read in ChiefOfStaff.fetchData
instead of waiting on the whole secondaryRead batch, and providersLoaded
flows down to every picker that was still rendering a lone
emptyProviderOption during the initial fetch: TaskAddForm (which also
stopped clobbering a pinned provider mid-fetch), TaskItem/SortableTaskItem,
RelaunchAgentModal, ResumeAgentModal, and the Workflow tab's per-app
override pickers. The five FableLoom components on useProviderModels now
pass its loading flag through as well.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@atomantic
atomantic force-pushed the fix/provider-picker-loading-gate branch from 3ab486d to b39637d Compare September 3, 2026 22:05
@atomantic
atomantic merged commit f8bf6bc into atomantic:main Sep 3, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants