honor the per-app provider/model pin on every CoS task type, and edit it from one control - #4815
Merged
Conversation
… layered-intelligence (#4783) A per-app `taskTypeOverrides[<taskType>].providerId`/`.model` only reached the spawn for layered-intelligence, because only its buildTaskInput hook read the field. Every other type merged taskMetadata off the same record and then took its provider from the global Schedule pin, so a pin set on Edit App -> Automation silently never ran. - The generic generator now applies the per-app pin over the Schedule pin for every task type, through a shared resolver (`appTaskProviderPin.js`) that also carries the api-harness guard hoisted out of layered-intelligence: an api-typed per-app pin (no file-writing harness) falls back to the Schedule pin instead of reaching an agent that can never do the work. That deletes the whole `providerOverrideCapable` pipeline - server stamp, schedule status, workflow node, client props, and both copy blocks. - One shared `AppProviderPin` control + `providerPinPatch` normalizer replaces the three write sites' three different clears (`model: ''`, `model: null`, '' -> null), so clearing the pin from Automation, the Schedule rows, or the Intelligence tab produces the same stored result. The Schedule/Timeline rows gain a real picker where they previously offered only a "clear" link. - The Timeline tab receives the providers list, so its per-app rows show provider display names instead of raw ids.
…fic pin swaps the provider A model is provider-scoped, and agentProviderResolution honors an explicit metadata.model as a CLI pass-through rather than dropping it. Overriding only the PROVIDER therefore shipped the previous layer's model to a CLI that cannot run it (the `claude --model gemini-…` failure mode), on every retry until the task blocked. Each pin layer now takes its own model or none, so selectModelForTask resolves the new provider's default.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A per-app
taskTypeOverrides[<taskType>].providerId/.modelpin only reached the agent spawn forlayered-intelligence— every other task type mergedtaskMetadataoff the same record and then took its provider from the global Schedule pin, so a pin set on Edit App → Automation silently never ran.server/services/appTaskProviderPin.js), which also carries the api-provider harness guard hoisted out oflayeredIntelligenceHooks.js: an api-typed per-app pin (no file-writing harness, so the agent could never do the work) falls back to the Schedule pin instead of reaching the spawn. That deletes the wholeproviderOverrideCapablepipeline — server stamp, schedule status, workflow node, client props, and both copy blocks.AppProviderPincontrol plus oneproviderPinPatchnormalizer replaces the three write sites' three different clears (model: '',model: null,'' → null), so clearing the pin from Automation, the Schedule/Timeline rows, or the Intelligence tab produces the same stored result. The Schedule and Timeline rows gain a real picker where they previously offered only a "clear" link.WorkflowTabreceives the providers list ChiefOfStaff already owns, so its per-app rows resolve display names like the Schedule tab does.agentProviderResolutionhonors an explicitmetadata.modelas a CLI pass-through — so the leak shipped a CLI a model it cannot run, on every retry until the task blocked.Test plan
server/services/appTaskProviderPin.test.js— the resolution walk: app pin over schedule pin, api-typed fallback (provider and model), refusal to heal onto an unresolvable pin,provider-not-agent-capablewhen nothing has a harness, lazy single read of the schedule pin.server/services/cosTaskGenerator.providerPin.test.js— end to end onux(nobuildTaskInputhook), asserting the generated task's metadata: spawns on the app pin, an api-typed pin does not wedge, an api-only schedule pin is left for the spawn-time error, a model pinned without a provider survives, and a provider swap drops the stale model.client/src/components/cos/tabs/WorkflowTab.providers.test.jsx— Timeline rows render provider display names and write the pin through the shared override mutation.AppOverrideRow,AutomationTab,LayeredIntelligenceTab, andcos/constantssuites to cover the identical clear across all three surfaces.server(32829 passed) andclient(9363 passed) suites green;clientbiome lint clean.Closes #4783