Repository navigation
Conversation
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Parameterized models, glob-based aliases, and empty pricing entries can bypass propagation or produce incorrect diagnostics.
Review effort: Balanced
Findings: 3
Open (3)
What changed in this PR
Adds compile-time model pricing propagation and diagnostics to prevent AWF proxy failures for unpriced models.
Changes:
- Registers exact catalog pricing resolution during compilation.
- Warns when configured models lack pricing or fallback configuration.
- Adds pricing propagation and warning tests.
| File | Description |
|---|---|
pkg/workflow/compiler_types.go |
Clarifies pricing resolver behavior. |
pkg/workflow/compiler_mutators.go |
Exposes resolver configuration. |
pkg/workflow/compiler_model_pricing.go |
Updates pricing resolution documentation. |
pkg/cli/model_costs.go |
Adds exact catalog lookup. |
pkg/cli/compile_model_validation.go |
Adds missing-pricing diagnostics. |
pkg/cli/compile_development_test.go |
Tests pricing warnings. |
pkg/cli/compile_compiler_setup.go |
Registers pricing resolver and validator. |
pkg/cli/compile_compiler_setup_test.go |
Tests catalog-price injection. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| for _, target := range targets { | ||
| targetProvider, targetModel, ok := configuredModelPricingID(&workflow.WorkflowData{ | ||
| EngineConfig: &workflow.EngineConfig{LLMProvider: workflow.LLMProvider(provider)}, | ||
| }, target) | ||
| if !ok || !configuredModelHasPricing(targetProvider, targetModel, aliases, visited) { |
There was a problem hiding this comment.
Handled in b2742c01: pricing checks now match alias glob targets against priced catalog models, with built-in sonnet and haiku regression coverage.
| for name := range models { | ||
| if strings.EqualFold(name, model) { | ||
| return true |
There was a problem hiding this comment.
Handled in b2742c01: both compiler and workflow pricing predicates now require a non-empty cost map; regression tests cover absent and empty pricing entries.
| initModelPrices() | ||
|
|
||
| normalizedProvider := modelsdev.NormalizeProvider(provider) | ||
| comparableModel := modelsdev.NormalizeComparableModelID(model) |
There was a problem hiding this comment.
Handled in b2742c01: query parameters are removed before exact catalog lookup and before workflow overlay injection, with a ?effort=high regression test.
|
@copilot address the following outstanding work in one pass:
Push the necessary fixes, reply to each listed review thread and resolve it when addressed. Ignore feedback already answered or resolved. Use the pr-finisher skill and stop when only human review or CI remains; do not trigger CI. Sous-chef head: 2732e85
|
|
🔬 Test Quality Sentinel is analyzing test quality on this pull request... |
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.
|
|
🧠 Matt Pocock Skills Reviewer is reviewing this pull request using Matt Pocock's engineering skills... |
|
✅ PR Code Quality Reviewer completed the code quality review. review submitted via overall review; existing inline comments already covered the other blockers
|
🏗️ Design Decision Gate — ADR RequiredResult: ❌ No Architecture Decision Record found for this PR. A draft ADR has been generated and committed to this branch for your review. Why this PR is gated
Draft ADR📄 Decision captured from the diff:
Next actionReview the draft, correct anything the gate inferred incorrectly (especially the alternatives and the negative consequences), and change Status from
|
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
…dle-models-missing-pricing-table Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
|
@
|
There was a problem hiding this comment.
✅ Test Quality Sentinel: 84/100 (Excellent). 12 design tests (86%) vs 2 implementation tests (14%). No violations. Strong edge-case coverage with 28+ scenarios across table-driven tests. Comprehensive model pricing feature testing with 7-scenario pricing warning test, all error paths covered.
🧪 Test quality analysis by Test Quality Sentinel · copilot · haiku45 · 55.4 AIC · ⌖ 7.4 AIC · ⊞ 8.2K
Comment /review to run again
There was a problem hiding this comment.
Impeccable review — harden + audit (bug-fix change)
This PR adds compile-time warnings for models missing AI-credits pricing. I verified the three edge-case correctness issues already flagged by the automated Copilot review are still present and reproducible against the current diff:
- Built-in alias glob targets (
sonnet,haiku, etc.) trigger false-positive warnings —configuredModelHasPricingtreats alias targets likecopilot/*sonnet*as literal model IDs, so ordinary workflows using built-in aliases will see a spurious "no AI credits pricing" warning. - Query-parameter model identifiers (e.g.
gpt-6.1-sol?effort=high) are not stripped infindExactModelPricing, so valid Model-Alias-Format identifiers silently miss catalog pricing. hasModelCostOverlayreturns true for a frontmatter model entry with no actualcost, suppressing the new warning exactly in the case it's meant to catch.
All three were reproduced locally with small standalone test snippets (see inline comments for exact repro code). These are correctness bugs in the new warning logic itself — the warning will misfire (false positives for common built-in aliases) and under-fire (false negatives for stub entries), undermining the PR's stated goal of catching unpriced models before the AWF API proxy rejects them at runtime.
Requesting changes to fix these before merge.
🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet50 · 69.3 AIC · ⌖ 15.8 AIC · ⊞ 8.1K
| for _, target := range targets { | ||
| targetProvider, targetModel, ok := configuredModelPricingID(&workflow.WorkflowData{ | ||
| EngineConfig: &workflow.EngineConfig{LLMProvider: workflow.LLMProvider(provider)}, | ||
| }, target) |
There was a problem hiding this comment.
Alias glob patterns break configuredModelHasPricing and emit false-positive warnings for every built-in model alias.
Built-in aliases such as sonnet and haiku resolve to glob targets like copilot/*sonnet* (see pkg/workflow/model_aliases.go), but configuredModelPricingID (and the exact-match lookup it feeds into) treats each target as a literal model ID. A glob pattern never matches any catalog record, so configuredModelHasPricing returns false and the new warning fires for every ordinary workflow using a built-in alias, even though AWF resolves these at runtime.
Reproduced locally:
aliases := workflow.MergeImportedModelAliases(nil, nil)
data := &workflow.WorkflowData{Model: "sonnet", EngineConfig: &workflow.EngineConfig{ID: "copilot"}, ModelMappings: aliases}
configuredModelPricingWarning(data) // => "Model sonnet has no AI credits pricing..."This fires spuriously for any workflow with model: sonnet or model: haiku, which is likely very common.
Please either skip/short-circuit glob targets (treat them as "has pricing" since AWF resolves them dynamically) or expand the glob against the catalog before declaring no pricing. @copilot please address this.
There was a problem hiding this comment.
Handled in b2742c01: alias glob targets are matched against priced catalog models, and built-in sonnet/haiku cases are covered by tests.
| initModelPrices() | ||
|
|
||
| normalizedProvider := modelsdev.NormalizeProvider(provider) | ||
| comparableModel := modelsdev.NormalizeComparableModelID(model) |
There was a problem hiding this comment.
Query-parameter suffixes are not stripped before the exact-pricing lookup.
configuredModelPricingID strips a ?effort=... suffix from the configured model before calling findExactModelPricing, but the pricing resolver wired up in compile_compiler_setup.go (findExactModelPricing) is also called directly by resolveModelPricingIfMissing via the injected modelPricingResolver, and findExactModelPricing itself does not strip query parameters from model.
Reproduced locally:
findExactModelPricing("openai", "gpt-6.1-sol?effort=high") // => (nil, false)
findExactModelPricing("openai", "gpt-6.1-sol") // => (pricing, true)Any workflow configuring model: openai/gpt-6.1-sol?effort=high (a valid Model Alias Format identifier per model_alias_validation.go) will silently lose the catalog pricing match. Strip the query suffix (e.g. strings.Cut(model, "?")) at the top of findExactModelPricing, mirroring what configuredModelPricingID already does. @copilot please address this.
There was a problem hiding this comment.
Handled in b2742c01: the workflow resolver and exact catalog lookup strip query parameters; regression coverage verifies the base model is injected.
| } | ||
| for name := range models { | ||
| if strings.EqualFold(name, model) { | ||
| return true |
There was a problem hiding this comment.
hasModelCostOverlay returns true for an entry with no cost field, suppressing the new pricing warning incorrectly.
The schema permits a frontmatter model entry such as models.providers.openai.models.custom: {} (no cost key, or an empty cost map). hasModelCostOverlay only checks that the model key exists under providerMap["models"], not that it actually carries pricing data:
costs := map[string]any{"providers": map[string]any{"openai": map[string]any{"models": map[string]any{"custom-model": map[string]any{}}}}}
hasModelCostOverlay(costs, "openai", "custom-model") // => true (should be false — no cost present)This means a frontmatter stub entry with no actual price silently suppresses configuredModelPricingWarning, defeating the purpose of this PR (catching models the AWF proxy will reject with HTTP 400). Check that cost is present and non-empty before returning true. @copilot please address this.
There was a problem hiding this comment.
Handled in b2742c01: an overlay only counts as pricing when the model has a non-empty cost map, covered for missing and empty maps.
There was a problem hiding this comment.
Request changes
The new pricing-warning path still misclassifies several valid model configurations and misses some genuinely unpriced ones, so it is not safe to ship yet.
Blocking themes
- Parameterized model IDs such as
gpt-6.1-sol?effort=highmiss the new exact catalog lookup, so compilation still omits pricing for a model the local catalog already knows. - Alias handling is too strict for documented model maps: glob-backed builtins like
sonnet/haikuare treated as unpriced, and same-workflow aliases are not even present inWorkflowData.ModelMappingsduring this check. - The overlay check only looks for a matching model key, so placeholder entries without usable
costdata suppress the warning even though the AWF proxy can still reject the model at runtime.
🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 91.9 AIC · ⌖ 6.68 AIC · ⊞ 19.6K
Comment /review to run again
| if !ok || hasModelCostOverlay(data.ModelCosts, provider, model) { | ||
| return "" | ||
| } | ||
| if configuredModelHasPricing(provider, model, data.ModelMappings, make(map[string]struct{})) { |
There was a problem hiding this comment.
This alias pricing check depends on WorkflowData.ModelMappings, but that field is populated from imports only, so a workflow that defines models.preferred-model: [gpt-6.1-sol] in its own frontmatter still trips the new has no AI credits pricing warning.
💡 Why this blocks
workflow_builder.go currently calls MergeImportedModelAliases(importsResult.MergedModels, nil), so same-file aliases never reach this helper. Merge the main frontmatter aliases into WorkflowData.ModelMappings, or pass the parsed frontmatter alias map into this check instead of relying on the imported-only field.There was a problem hiding this comment.
I did not change this: workflow aliases under models are not supported by the current schema (main_workflow_schema.json:3055-3104 sets additionalProperties: false), and the existing import test documents that aliases now come only from the built-in map (model_aliases_import_test.go:18-20). Such frontmatter is rejected before the pricing warning runs.
Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>
|
@copilot run pr-finisher skill |
…dle-models-missing-pricing-table # Conflicts: # .github/workflows/agentic-token-trend-audit.lock.yml # .github/workflows/audit-workflows.lock.yml # .github/workflows/avenger.lock.yml # .github/workflows/changeset.lock.yml # .github/workflows/cloclo.lock.yml # .github/workflows/commit-changes-analyzer.lock.yml # .github/workflows/copilot-centralization-optimizer.lock.yml # .github/workflows/daily-awf-spec-compiler-surfacing.lock.yml # .github/workflows/daily-cli-performance.lock.yml # .github/workflows/daily-doc-updater.lock.yml # .github/workflows/daily-evals-report.lock.yml # .github/workflows/daily-go-test-parallelizer.lock.yml # .github/workflows/daily-regulatory.lock.yml # .github/workflows/daily-spending-forecast.lock.yml # .github/workflows/daily-windows-defender-scan.lock.yml # .github/workflows/dependabot-go-checker.lock.yml # .github/workflows/eslint-monster.lock.yml # .github/workflows/front-page-copy-guard.lock.yml # .github/workflows/github-remote-mcp-auth-test.lock.yml # .github/workflows/grumpy-reviewer.lock.yml # .github/workflows/issue-triage-agent.lock.yml # .github/workflows/metrics-collector.lock.yml # .github/workflows/outcome-collector.lock.yml # .github/workflows/poem-bot.lock.yml # .github/workflows/purelock.lock.yml # .github/workflows/repo-audit-analyzer.lock.yml # .github/workflows/schema-feature-coverage.lock.yml # .github/workflows/sighthound-security-scan.lock.yml # .github/workflows/smoke-otel-backends.lock.yml # .github/workflows/update-astro.lock.yml # .github/workflows/windows.lock.yml Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
The three requested pricing fixes and regression cases were already present in |

Models without AI-credit pricing can be rejected by the AWF API proxy at runtime. This change supplies known catalog prices during compilation and warns when a configured model has no price or fallback.
gpt-6.1-sol.