Skip to content

Add gh aw models for catalog pricing, alias resolution, and observed automation models - #55148

Merged
pelikhan merged 4 commits into
mainfrom
copilot/add-command-listing-models
Aug 23, 2026
Merged

Add gh aw models for catalog pricing, alias resolution, and observed automation models#55148
pelikhan merged 4 commits into
mainfrom
copilot/add-command-listing-models

Conversation

Copilot AI commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

This adds a dedicated gh aw models command to make model selection fast and reliable: it surfaces catalog pricing, alias resolution targets, and models actually seen in automation artifacts. It also attempts a lightweight artifact refresh so observed-model output includes recent AWF reflect data when available.

  • Command surface

    • Adds gh aw models to the CLI and registers it in the analysis command group.
    • Supports machine-readable output via --json.
    • Adds knobs for observed-model discovery scope:
      • --logs-dir
      • --refresh-observed
      • --refresh-count
      • --repo
  • Catalog + pricing view

    • Reads embedded catalog pricing and renders a provider/model table with token-price dimensions (input, output, cache_read, cache_write, reasoning).
    • Normalizes provider/model identifiers for stable matching and cross-provider comparability.
  • Alias intelligence

    • Exposes built-in alias map and ordered resolution targets so agents can quickly choose alias vs concrete model ID.
    • Adds alias hinting for observed models by matching observed IDs against alias wildcard targets.
  • Observed-model intelligence from automation

    • Aggregates observed models from:
      • summary.json token usage (token_usage_summary.by_model)
      • per-run token usage artifacts
      • awf-reflect.json endpoint model lists
    • De-duplicates and merges provenance (summary, token-usage, awf-reflect), tracks occurrence counts, and marks catalog presence.
gh aw models --json --refresh-count 50

Run: https://github.com/github/gh-aw/actions/runs/32664768328> Generated by 👨‍🍳 PR Sous Chef · gpt54 · 7.75 AIC · ⌖ 9.32 AIC · ⊞ 9.5K ·

Comment /souschef to run again

…overy

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title Add gh aw models command for catalog pricing and observed models Add gh aw models for catalog pricing, alias resolution, and observed automation models Aug 23, 2026
Copilot AI requested a review from pelikhan August 23, 2026 19:14
@pelikhan
pelikhan marked this pull request as ready for review August 23, 2026 19:56
Copilot AI balanced review requested due to automatic review settings August 23, 2026 19:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds gh aw models for catalog pricing, alias resolution, and automation-observed model discovery.

Changes:

  • Adds human-readable and JSON model reports.
  • Refreshes and aggregates model observations from workflow artifacts.
  • Registers the command in the analysis group.
Show a summary per file
File Description
pkg/cli/models_command.go Implements model reporting and artifact discovery.
pkg/cli/models_command_test.go Tests catalog sorting, observation aggregation, and aliases.
cmd/gh-aw/main.go Registers and groups the new command.

Review details

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 3/3 changed files
  • Comments generated: 3
  • Review effort level: Balanced

Comment thread pkg/cli/models_command.go
if refreshCount <= 0 {
refreshCount = 20
}
return DownloadWorkflowLogs(ctx, LogsDownloadOptions{
Comment thread pkg/cli/models_command.go Outdated
Comment on lines +422 to +426
func modelExistsInCatalog(index map[string]struct{}, fullID, model string) bool {
_, hasFullID := index[modelsdev.NormalizeComparableModelID(fullID)]
_, hasModel := index[modelsdev.NormalizeComparableModelID(model)]
return hasFullID || hasModel
}
Comment thread pkg/cli/models_command.go Outdated
Comment on lines +221 to +223
warnings = appendObservedCollectionWarning(warnings, collectObservedFromSummary(logsDir, addObserved), "summary.json")
warnings = appendObservedCollectionWarning(warnings, collectObservedFromRunDirs(logsDir, addObserved), "run directories")
warnings = appendObservedCollectionWarning(warnings, collectObservedFromAWFReflect(logsDir, addObserved), "awf-reflect artifacts")
@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ failed during design decision gate check.

Warning

Threat Detection Engine Failure — The analysis engine could not complete. This is a tooling failure, not a security finding.

What happened

The threat detection engine failed to produce results.

Review the workflow run logs for details.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Caution

agentic threat detected
Threat detection flagged this output in warn mode. Manual review is REQUIRED before any follow-up automation.

Details

Potential security threats were detected in the agent output.

Review the workflow run logs for details.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Ponytail Reviewer completed successfully!

Generated by Ponytail Reviewer for #55148

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-08-23T20:19:00Z
review_event: REQUEST_CHANGES
top_themes:
  - output contamination from default artifact refresh
  - double-counted observed model occurrences
  - provider-insensitive catalog membership
files_reviewed:
  - cmd/gh-aw/main.go
  - pkg/cli/models_command.go
  - pkg/cli/models_command_test.go
comment_count: 3

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · gpt54 · 17.6 AIC · ⌖ 6.97 AIC · ⊞ 7K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Request changes

This adds useful surface area, but the current implementation ships broken output semantics and misleading observed-model data.

Blocking themes
  • the default refresh path writes logs output into models, which can corrupt both human-readable output and --json
  • observed request counts are double counted from summary.json plus the same run-* directories
  • catalog membership is overstated because provider-qualified observations fall back to providerless model-name matches

🔎 Code quality review by PR Code Quality Reviewer · gpt54 · 17.6 AIC · ⌖ 6.97 AIC · ⊞ 7K
Comment /review to run again

Comment thread pkg/cli/models_command.go
}

func refreshObservedArtifacts(ctx context.Context, logsDir string, refreshCount int, repoOverride string) error {
if refreshCount <= 0 {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This command refreshes observed artifacts before printing its own report, but DownloadWorkflowLogs emits its compact run summary to stdout by default. As written, gh aw models will prepend unrelated logs output ahead of the catalog/alias sections, and --json mode can no longer guarantee clean JSON when the refresh finds runs.

💡 Keep the refresh side effect from corrupting command output

Either call the downloader in a silent mode (for example by adding an option that skips rendering) or route the refresh through an internal API that only materializes artifacts. Right now the implementation uses the same public downloader path that is designed to print human-readable summaries:

return DownloadWorkflowLogs(ctx, LogsDownloadOptions{
    Count:        refreshCount,
    OutputDir:    logsDir,
    RepoOverride: repoOverride,
    ArtifactSets: []string{string(ArtifactSetFirewall), string(ArtifactSetUsage)},
})

That breaks both the plain-text UX and any scripting that expects gh aw models --json to return only a single JSON document.

Comment thread pkg/cli/models_command.go Outdated
}

warnings = appendObservedCollectionWarning(warnings, collectObservedFromSummary(logsDir, addObserved), "summary.json")
warnings = appendObservedCollectionWarning(warnings, collectObservedFromRunDirs(logsDir, addObserved), "run directories")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The observed-model counter double counts the same requests whenever summary.json and the corresponding run-* directories are both present, which is the normal logs layout produced by the downloader. That makes the Seen column systematically inflated and turns the command's main ranking signal into fiction.

💡 De-duplicate summary-vs-run usage before aggregating counts

collectObservedModelRows currently adds request totals from both sources independently:

warnings = appendObservedCollectionWarning(warnings, collectObservedFromSummary(logsDir, addObserved), "summary.json")
warnings = appendObservedCollectionWarning(warnings, collectObservedFromRunDirs(logsDir, addObserved), "run directories")

But summary.json is already derived from those run directories, so a refreshed logs directory usually reports each run twice. Prefer one authoritative source for request counts, or key counts by run ID and merge sources without adding the same run twice. The current test even encodes the bad behavior by asserting >= 8 from a 7-request summary plus one reflect observation.

Comment thread pkg/cli/models_command.go Outdated
}

func modelExistsInCatalog(index map[string]struct{}, fullID, model string) bool {
_, hasFullID := index[modelsdev.NormalizeComparableModelID(fullID)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

InCatalog falls back to a providerless model-name lookup even when the observed provider is known, so any provider that happens to expose the same slug as a catalog entry is reported as catalog-backed. That quietly mislabels unknown or unsupported providers as valid and undermines the point of this compatibility signal.

💡 Only use bare-model fallback when the provider is actually unknown

The current check indexes both full IDs and naked model names:

index[NormalizeComparableModelID(record.id)] = struct{}{}
index[NormalizeComparableModelID(record.model)] = struct{}{}

and then accepts either match:

_, hasFullID := index[NormalizeComparableModelID(fullID)]
_, hasModel := index[NormalizeComparableModelID(model)]
return hasFullID || hasModel

That means other/gpt-5.4 becomes InCatalog=true just because some other provider ships gpt-5.4. Keep the bare-model fallback for missing/empty providers only; once a provider is known, require the provider-qualified ID to match.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /diagnosing-bugs, /codebase-design, and /tdd — requesting changes on correctness issues.

📋 Key Themes & Highlights

Key Themes

  • Occurrence double-counting: summary.json and run-* directories cover the same data; aggregating both inflates the Occurrences count.
  • False-positive InCatalog: bare-model fallback in modelExistsInCatalog incorrectly marks models from unknown providers as catalog-present.
  • Stdout interleaving: DownloadWorkflowLogs writes a compact status report to stdout before the models tables render (default behaviour since --refresh-observed is true).
  • Alias deduplication gap: inferAliasHints can append the same alias multiple times if multiple wildcard patterns in its target list match.
  • Test coupling to a bug: the gpt-5.4 InCatalog: true assertion in the test validates the false-positive path; fixing the catalog lookup will break the test.

Positive Highlights

  • ✅ Clean command structure and well-named flag set.
  • ✅ Graceful handling of missing summary.json and non-existent logsDir.
  • ✅ Warnings propagated to stderr rather than swallowed.
  • ✅ Good use of slices.SortFunc for deterministic output.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 · 39.6 AIC · ⌖ 11.5 AIC · ⊞ 7.6K
Comment /matt to run again

Comment thread pkg/cli/models_command.go
for _, modelID := range modelIDs {
if wildcardMatch(entry, modelID) {
matches = append(matches, alias)
break

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/diagnosing-bugs] Duplicate alias hints are possible: break exits the inner modelIDs loop but not the outer entries loop, so a single alias whose target list contains two wildcard patterns that both match can appear twice in AliasHints.

💡 Deduplicate with a seen-set
seen := make(map[string]struct{})
for alias, entries := range aliasMap {
    for _, entry := range entries {
        if !strings.Contains(entry, "/") {
            continue
        }
        for _, modelID := range modelIDs {
            if wildcardMatch(entry, modelID) {
                if _, already := seen[alias]; !already {
                    seen[alias] = struct{}{}
                    matches = append(matches, alias)
                }
                break
            }
        }
    }
}

@copilot please address this.

Comment thread pkg/cli/models_command.go

warnings = appendObservedCollectionWarning(warnings, collectObservedFromSummary(logsDir, addObserved), "summary.json")
warnings = appendObservedCollectionWarning(warnings, collectObservedFromRunDirs(logsDir, addObserved), "run directories")
warnings = appendObservedCollectionWarning(warnings, collectObservedFromAWFReflect(logsDir, addObserved), "awf-reflect artifacts")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/diagnosing-bugs] Double-counting of occurrences when both summary.json and the matching run-* directory are present. collectObservedFromSummary adds per-run request counts from the aggregated file, then collectObservedFromRunDirs re-adds the same per-run counts from the individual directories that built that summary. A model seen in 5 runs of 7 requests each would be credited 70 occurrences instead of 35.

💡 Options
  1. Skip collectObservedFromRunDirs when summary.json exists and already covers the same runs.
  2. Use run-* as the only per-run source and rely on summary.json only for fields unavailable in individual run dirs.
  3. Count each source separately and note in the Sources field rather than summing them.

@copilot please address this.

Comment thread pkg/cli/models_command.go
_, hasFullID := index[modelsdev.NormalizeComparableModelID(fullID)]
_, hasModel := index[modelsdev.NormalizeComparableModelID(model)]
return hasFullID || hasModel
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/codebase-design] modelExistsInCatalog indexes every catalog model by bare model name (without provider), so InCatalog can be a false positive for observed models that share a model name with a completely different provider. For example, if anthropic/claude-3 is in the catalog, an observed my-provider/claude-3 would incorrectly show InCatalog: true.

💡 Suggested fix

Prefer the full-ID check; fall back to bare-model only when the observed provider is empty or unknown:

func modelExistsInCatalog(index map[string]struct{}, fullID, model string, provider string) bool {
    if _, ok := index[modelsdev.NormalizeComparableModelID(fullID)]; ok {
        return true
    }
    // Only allow bare-model fallback when provider is unknown
    if provider == "" {
        _, ok := index[modelsdev.NormalizeComparableModelID(model)]
        return ok
    }
    return false
}

@copilot please address this.

Comment thread pkg/cli/models_command.go
if refreshCount <= 0 {
refreshCount = 20
}
return DownloadWorkflowLogs(ctx, LogsDownloadOptions{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/codebase-design] refreshObservedArtifacts calls DownloadWorkflowLogs, which renders a compact status report to stdout (see logs_orchestrator_render.go). This output is interleaved with — and appears before — the models table output, producing confusing UX when --refresh-observed is true (the default).

💡 Options
  1. Pass a no-op io.Writer for the render output when called from the models command.
  2. Add a Quiet bool field to LogsDownloadOptions that suppresses the compact report.
  3. Move the refresh call after the tables are rendered, or gate it behind an explicit --refresh-observed flag default of false.

@copilot please address this.

}

func TestInferAliasHints(t *testing.T) {
t.Parallel()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[/tdd] The test asserts gpt.InCatalog == true, but gpt-5.4 from provider copilot is only in the catalog as a bare model name match. This test is actually validating the false-positive path identified in the modelExistsInCatalog comment — if that bug is fixed, this assertion will break. The test should either explicitly use a model+provider pair that is genuinely in the catalog, or assert InCatalog == false for an unknown model to verify the negative path.

@copilot please address this.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ponytail review: over-engineering pass only.

net: -25 lines possible.

Generated by ✂️ Ponytail Reviewer for #55148 · auto · 25.3 AIC · ⌖ 6.94 AIC · ⊞ 7.3K
Comment /ponytail to run again

Comment thread pkg/cli/models_command.go
}

func wildcardMatch(pattern, value string) bool {
matched, err := filepath.Match(pattern, value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

L405: native: wildcardMatch wraps filepath.Match and swallows its error. Call filepath.Match directly at the two call sites, 0 lines.

Comment thread pkg/cli/models_command.go

func collectObservedFromRunDirs(logsDir string, addObserved func(provider, model, source string, occurrences int)) error {
entries, err := os.ReadDir(logsDir)
if err != nil {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

L303-308: yagni: appendObservedCollectionWarning is a 6-line wrapper around a 2-line if err != nil { append(...) }, used only 3x. Inline it at each call site.

Comment thread pkg/cli/models_command.go
return nil
}
var payload struct {
Endpoints []struct {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

L310-381: shrink: collectObservedFromSummary and collectObservedFromRunDirs duplicate the same provider/requests-default-1 extraction from usage. Extract one helper, ~10 fewer lines.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review: gh aw models command

The implementation is well-structured and covers catalog pricing, alias resolution, and observed model discovery. The three existing inline comments flag the most important issues:

  1. stdout pollution (line 143) — DownloadWorkflowLogs emits a compact report to stdout before the models output, breaking --json piping and polluting structured output.
  2. double-counting (line 223) — summary.json and the run-* token-usage dirs overlap, inflating Occurrences for models already aggregated in the summary.
  3. catalog lookup false negatives (line 426) — the bare-model fallback in modelExistsInCatalog can produce false positives when a short model name matches unrelated catalog entries from a different provider.

No additional blocking issues found beyond those already commented. Once those three are resolved, this is ready to merge.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · sonnet46 · 25.6 AIC · ⌖ 9.02 AIC · ⊞ 6.2K

@github-actions

Copy link
Copy Markdown
Contributor

Caution

agentic threat detected
Threat detection flagged this output in warn mode. Manual review is REQUIRED before any follow-up automation.

Details

Potential security threats were detected in the agent output.

Review the workflow run logs for details.

Test Quality Sentinel 🧪

Overall Score: ✅ 90/100 — Excellent

Summary

3 new test functions added in pkg/cli/models_command_test.go (100 lines). All tests cover behavioral contracts with strong design guarantees. No mock libraries or build-tag violations detected. Test:code ratio 0.23:1 is healthy and well within acceptable bounds.

Test Breakdown

Test Classifications (3 new tests analyzed)
Test Design Invariant Value Type Assertions Status
TestBuildModelCatalogRowsSorted Ordering guarantee high_value design_test 2
TestCollectObservedModelRowsFromSummaryAndReflect Data aggregation high_value design_test 7
TestInferAliasHints Alias resolution high_value design_test 2

Test Details

1. TestBuildModelCatalogRowsSorted

Verifies catalog rows are sorted by provider and model name (ordering design invariant). Uses LessOrEqual assertions to validate consecutive ordering across provider boundaries. ✅ Behavioral contract.

2. TestCollectObservedModelRowsFromSummaryAndReflect

Strongest test. Validates data aggregation from summary.json and awf-reflect.json:

  • Sets up realistic file structure with JSON payloads
  • Verifies sources are tracked ("summary", "awf-reflect")
  • Confirms occurrence counts are aggregated (≥8 from multiple sources)
  • Checks catalog membership tracking
  • Uses 7 assertions covering success and integration paths
    ✅ High-value integration test.

3. TestInferAliasHints

Validates model ID to alias mapping ("claude-sonnet-4.6" → "sonnet"). Limited to single example. ⚠️ Could benefit from additional edge cases.

Quality Signals

Strengths:

  • All tests use t.Parallel() for concurrent execution
  • Correct build tag ((go/redacted):build !integration on line 1)
  • No mock libraries (no gomock, testify/mock, .EXPECT())
  • 100% design-test coverage (all verify user-visible behavior)
  • Strong integration test with file I/O and JSON parsing
  • Proper error handling patterns with require.*
  • Realistic test fixtures and data

⚠️ Notes:

  • TestInferAliasHints uses minimal examples (1 case)
  • No negative/error-path tests for failure scenarios
  • Package-level goroutine-leak guard (goleak.VerifyTestMain) provides additional protection

Metrics

  • Test:code ratio: 100:433 = 0.23:1 ✅ (threshold: <2:1)
  • Design tests: 3/3 = 100%
  • Edge-case coverage: 2/3 = 67%
  • Mock violations: 0 ✅
  • Build-tag violations: 0 ✅

Scoring

Design tests (3/3) × 40    = 40
Edge cases (2/3) × 30      = 20
No duplicates              = 20
No inflation (0.23:1)      = 10
─────────────────────────────
Total Score                = 90/100 ✅

Result

APPROVED — Test Quality Sentinel: 90/100. Implementation tests: 0% (threshold: 30%). Tests demonstrate strong behavioral coverage with no violations.

🧪 Test quality analysis by Test Quality Sentinel · haiku45 · 17.6 AIC · ⌖ 16.7 AIC · ⊞ 8.3K ·
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 90/100. 0% implementation tests (threshold: 30%). Tests demonstrate strong behavioral coverage of the new models catalog command with no violations.

@gh-aw-bot

Copy link
Copy Markdown
Collaborator

@copilot Please take another pass on this PR. The failed check still needs attention: Design Decision Gate 🏗️ — https://github.com/github/gh-aw/actions/runs/32662863381/job/97254401123

Please refresh the branch, address the failing workflow, and run the pr-finisher skill before handing this back for review.

Generated by 👨‍🍳 PR Sous Chef · gpt54 · 7.75 AIC · ⌖ 9.32 AIC · ⊞ 9.5K ·
Comment /souschef to run again

@pelikhan

Copy link
Copy Markdown
Collaborator

@copilot add integration test

Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com>

Copilot AI commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot Please take another pass on this PR. The failed check still needs attention: Design Decision Gate 🏗️ — https://github.com/github/gh-aw/actions/runs/32662863381/job/97254401123

Please ...

Addressed in the latest commit.

  • Design Decision Gate: the gate's agent failed because it could not push its generated ADR (its git push was denied), so no ADR landed. I added docs/adr/55148-models-command-for-catalog-alias-and-observed-models.md documenting the context, decision, alternatives, and consequences for gh aw models.
  • Correctness fixes made in the same pass:
    • LogsDownloadOptions.SuppressRender stops the logs orchestrator after artifacts/summary are written, so the default refresh no longer prints a report and gh aw models --json emits a single valid JSON document.
    • Run IDs recorded in summary.json are skipped when walking run-* directories, so occurrence counts are no longer doubled.
    • Catalog membership is provider-scoped; the bare model-name index is only consulted for observations without a provider, so other/gpt-5.4 is no longer marked catalog-backed.
  • Also added CLI reference docs for gh aw models and a changeset, plus tests for the new de-duplication, provider-scoped catalog matching, and suppressed rendering.

Local validation: make fmt and make agent-report-progress tests pass; golint-custom failures are pre-existing on this branch (they reproduce with my changes stashed) and untouched by this PR. Note that agent pushes do not re-trigger CI, so a maintainer needs to re-run the Design Decision Gate check.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot add integration test

Added pkg/cli/models_command_integration_test.go (commit 4fe6b6d) with end-to-end tests that execute the cobra command against a fixture logs directory:

  • TestModelsCommandJSONOutputIsSingleDocument — asserts stdout is exactly one JSON payload (no trailing content from the logs refresh path), and that observed models merge summary + awf-reflect provenance without double counting a run already present in summary.json.
  • TestModelsCommandConsoleOutputSections — asserts the human-readable report renders the catalog, alias, and observed sections.
  • TestModelsCommandWithEmptyLogsDir — asserts catalog/alias data is still reported, with no observed rows or warnings, when no artifacts exist.

They run under the integration build tag and are picked up by the "CLI Completion & Other" CI group.

@pelikhan
pelikhan merged commit f8bbaea into main Aug 23, 2026
36 checks passed
@pelikhan
pelikhan deleted the copilot/add-command-listing-models branch August 23, 2026 21:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants