Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Render sandbox.firewall models.json in AWF step summaries#34088

Merged
pelikhan merged 6 commits into
mainfrom
copilot/add-models-json-rendering
May 22, 2026
Merged

Render sandbox.firewall models.json in AWF step summaries#34088
pelikhan merged 6 commits into
mainfrom
copilot/add-models-json-rendering

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 22, 2026

AWF step summaries already showed /reflect endpoint state, but not the sandbox.firewall/models.json payload that captures the provider endpoints and runtime-discovered models actually available to the sandbox. This change extends the existing summary so operators can see both the configured proxy view and the emitted runtime model inventory in one place.

  • Summary integration

    • Extend awf_reflect_summary.cjs to read /tmp/gh-aw/sandbox/firewall/models.json alongside awf-reflect.json
    • Keep the existing collapsible AWF API proxy summary and append a second table for runtime model inventory when present
  • Runtime models rendering

    • Normalize multiple models.json shapes into a single table model
    • Render provider, resolved endpoint URL, and detected model IDs
    • Reuse the existing compact model-list formatting, including truncation for long inventories
  • Parsing support

    • Add helpers to:
      • read models.json safely
      • extract model IDs from string or object entries
      • normalize endpoint/provider payloads into summary rows
  • Coverage

    • Add focused Vitest cases for:
      • missing/invalid models.json
      • normalization of runtime payloads
      • combined summary output with the new runtime table

Example summary output:

<details>
<summary>AWF API proxy: 3 of 5 providers configured</summary>

Configured endpoints

| Provider | Port | Configured | Available models |
|----------|------|:----------:|------------------|
| openai | 10000 || gpt-4o, gpt-4o-mini |
| copilot | 10002 || claude-sonnet-4.6, gpt-4o |

Runtime models.json

| Provider | Endpoint | Available models |
|----------|----------|------------------|
| copilot | http://api-proxy:10002/models | claude-sonnet-4.6, gpt-4o |
| openai | http://api-proxy:10000/v1/models | gpt-4o, gpt-4o-mini |
</details>

pr-sous-chef: branch updated for maintainer follow-up.
Run:

Generated by 👨‍🍳 PR Sous Chef · ● 6.2M ·

@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot also render the model alias information

Copilot AI and others added 2 commits May 22, 2026 18:58
Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 22, 2026

@copilot also render the model alias information

Addressed in 24acd7f.

@pelikhan pelikhan marked this pull request as ready for review May 22, 2026 19:25
Copilot AI review requested due to automatic review settings May 22, 2026 19:25
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Extends the AWF step-summary generator to include additional sandbox/firewall model inventory information so operators can see configured /reflect endpoints and runtime-discovered models in the GitHub Actions step summary.

Changes:

  • Read and render /tmp/gh-aw/sandbox/firewall/models.json as an additional “Runtime models.json” table in the step summary.
  • Add normalization/parsing helpers for runtime model payload shapes and model-ID extraction.
  • Add Vitest coverage for reading/normalizing the new payload and for combined summary output.
Show a summary per file
File Description
actions/setup/js/awf_reflect_summary.cjs Adds runtime models.json + awf-config parsing helpers and renders additional tables in the step summary output.
actions/setup/js/awf_reflect_summary.test.cjs Adds tests for new file-reading helpers, normalization behavior, and the updated summary output.

Copilot's findings

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 2/2 changed files
  • Comments generated: 3

*
* Supported payload shapes:
* - { endpoints: [...] }
* - { providers: { name: ... } }
pushRow(runtimeModelsData.provider, runtimeModelsData);
}

return rows.filter(row => row.provider).sort((a, b) => a.provider.localeCompare(b.provider) || a.endpoint.localeCompare(b.endpoint));
Comment on lines +234 to +243
if (modelAliasRows.length > 0) {
lines.push("");
lines.push("Model aliases");
lines.push("");
lines.push("| Alias | Resolution order |");
lines.push("|-------|------------------|");
for (const row of modelAliasRows) {
lines.push(`| ${row.label} | ${formatModelList(row.targets, maxModels)} |`);
}
}
@github-actions
Copy link
Copy Markdown
Contributor

@copilot review all comments and address the 3 open review threads, especially the out-of-scope model-alias section.

Please post a brief blocker summary once those are resolved.

Generated by 👨‍🍳 PR Sous Chef · ● 4.3M ·

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

🧪 Test Quality Sentinel completed test quality analysis.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

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

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

Design Decision Gate 🏗️ completed the design decision gate check.

No ADR enforcement needed: PR #34088 does not have the implementation label and has 0 new lines of code in business logic directories (default threshold: 100).

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

PR Code Quality Reviewer completed the code quality review.

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Code Quality Review

The implementation is well-structured and thoroughly tested, but there are a few maintainability issues that should be addressed before merging.

Review summary

Issues found:

  1. Scope mismatch — PR adds undocumented Model aliases feature from awf-config.json
  2. Inaccurate JSDoc — Comment doesn't match implementation for providers field shape
  3. Redundant filter — Filter that will never remove any rows

What's done well:

  • Comprehensive test coverage for all new functions
  • Progressive disclosure with null-safe reads
  • Flexible normalization handling multiple payload shapes
  • Reuse of existing formatting helpers

🔎 Code quality review by PR Code Quality Reviewer · ● 653.4K

for (const row of modelAliasRows) {
lines.push(`| ${row.label} | ${formatModelList(row.targets, maxModels)} |`);
}
}
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.

Scope mismatch: PR adds Model aliases section from awf-config.json without mentioning it in title/description.

💡 Suggested approach

The PR title and description only mention extending summaries with sandbox/firewall/models.json, but lines 235-243 also add a "Model aliases" table sourced from /tmp/gh-aw/awf-config.json. This additional feature is undocumented in the PR description and example output.

Options:

  1. Update PR description and example to document the model aliases table
  2. Remove the model aliases feature and defer to a separate PR to keep scope focused

Adding undocumented features makes code review harder and creates incomplete changelogs.

pushRow(runtimeModelsData.provider, runtimeModelsData);
}

return rows.filter(row => row.provider).sort((a, b) => a.provider.localeCompare(b.provider) || a.endpoint.localeCompare(b.endpoint));
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.

Redundant filter: filter(row => row.provider) always passes because provider defaults to "unknown".

💡 Suggested fix

The pushRow function on line 103 always assigns a non-empty provider string:

provider: String(provider || entry?.provider || entry?.name || "unknown")

This means row.provider will never be falsy, so the filter on line 127 is redundant and will never remove any rows.

Options:

  1. Remove the filter: .sort((a, b) => ...)
  2. If the intent is to exclude unknown providers, allow empty provider values and filter explicitly:
    .filter(row => row.provider && row.provider !== "unknown")

/**
* Normalize runtime model entries to a common table-friendly shape.
*
* Supported payload shapes:
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.

Inaccurate JSDoc: Comment lists incorrect shape for providers field.

💡 Suggested fix

The JSDoc on line 82 states:

 *   - { providers: { name: ... } }

But the implementation on lines 113-117 treats providers as a map keyed by provider name, not an object with a name field:

for (const [provider, entry] of Object.entries(runtimeModelsData.providers)) {
  pushRow(provider, entry);
}

Update the JSDoc to reflect the actual supported shape:

 *   - { providers: { [providerName]: { endpoint: ..., models: [...] } } }

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Skills-Based Review 🧠

Applied /tdd and /grill-with-docs — requesting changes on domain language clarity and edge case coverage.

📋 Key Themes & Highlights

Key Themes

  • Domain language drift — Five different field names for model lists suggests unclear vocabulary. Document the canonical schema and mark legacy fallbacks explicitly.
  • Silent error handling — Malformed payload entries are filtered silently. Add edge case tests and consider debug logging for dropped data.
  • Function declaration order — Helper functions called before declaration hurts readability and could break if refactored to arrow functions.
  • Missing boundary tests — No tests for empty payloads, null endpoints, or malformed model entries.

Positive Highlights

  • Comprehensive test coverage — Every new function has corresponding tests
  • Progressive disclosure — Extends existing summary without breaking behavior
  • Defensive parsing — All file reads gracefully handle missing/invalid files
  • Clean separation — Runtime data vs. config data vs. aliases are clearly distinct
  • Sorting consistency — Provider rows are deterministically sorted
🔍 Review Scope

Skills selected: /tdd (test-driven development) + /grill-with-docs (domain language consistency)

Focus areas:

  • Test coverage for edge cases and boundary conditions
  • Domain vocabulary clarity and consistency
  • Error handling visibility and debugging support
  • Code organization and readability

Not reviewed: Performance, security (no sensitive data), accessibility (markdown output)

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · ● 1M

Comment thread actions/setup/js/awf_reflect_summary.cjs
Comment thread actions/setup/js/awf_reflect_summary.cjs
Comment thread actions/setup/js/awf_reflect_summary.cjs
});

describe("normalizeRuntimeModelRows", () => {
it("normalizes endpoint payloads into sorted rows", () => {
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] Missing edge case tests for empty and invalid runtime payloads.

💡 Add boundary condition tests

The tests cover valid payloads but not edge cases that could occur in production:

it('returns empty array for null or undefined', () => {
  expect(module.normalizeRuntimeModelRows(null)).toEqual([]);
  expect(module.normalizeRuntimeModelRows(undefined)).toEqual([]);
});

it('returns empty array for empty endpoints', () => {
  expect(module.normalizeRuntimeModelRows({ endpoints: [] })).toEqual([]);
});

it('filters out null and undefined endpoints', () => {
  const data = {
    endpoints: [null, undefined, { provider: 'valid', models: [] }],
  };
  const rows = module.normalizeRuntimeModelRows(data);
  expect(rows).toHaveLength(1);
  expect(rows[0].provider).toBe('valid');
});

These edge cases can happen if the firewall crashes mid-write or emits partial JSON.

@github-actions
Copy link
Copy Markdown
Contributor

🧪 Test Quality Sentinel Report

Test Quality Score: 86/100 — Excellent

Analyzed 11 new test(s): all 11 are design tests verifying behavioral contracts, 0 implementation tests, 0 guideline violations.

📊 Metrics & Test Classification (11 tests analyzed)
Metric Value
New/modified tests analyzed 11
✅ Design tests (behavioral contracts) 11 (100%)
⚠️ Implementation tests (low value) 0 (0%)
Tests with error/edge cases 6 (55%)
Duplicate test clusters 0
Test inflation detected No (0.85 ratio)
🚨 Coding-guideline violations 0

Test Classification Details

Test File Classification Notes
returns null when file does not exist actions/setup/js/awf_reflect_summary.test.cjs:103 ✅ Design Tests null-handling contract for missing config file
returns null when file contains invalid JSON actions/setup/js/awf_reflect_summary.test.cjs:107 ✅ Design Tests error handling for malformed JSON
parses and returns valid JSON actions/setup/js/awf_reflect_summary.test.cjs:112 ✅ Design Tests happy-path parsing contract
returns null when file does not exist actions/setup/js/awf_reflect_summary.test.cjs:175 ✅ Design Tests null-handling contract for missing models file
returns null when file contains invalid JSON actions/setup/js/awf_reflect_summary.test.cjs:179 ✅ Design Tests error handling for malformed JSON
parses and returns valid JSON actions/setup/js/awf_reflect_summary.test.cjs:184 ✅ Design Tests happy-path parsing contract
normalizes endpoint payloads into sorted rows actions/setup/js/awf_reflect_summary.test.cjs:191 ✅ Design Tests data transformation contract for multi-endpoint format
normalizes single-provider models.json payloads actions/setup/js/awf_reflect_summary.test.cjs:207 ✅ Design Tests edge case: alternative single-provider schema
normalizes alias mappings and sorts the default alias first actions/setup/js/awf_reflect_summary.test.cjs:224 ✅ Design Tests transformation + sorting behavior
renders runtime models.json table alongside configured endpoint summary actions/setup/js/awf_reflect_summary.test.cjs:310 ✅ Design Integration test: verifies models.json appears in summary
renders model aliases from awf-config.json actions/setup/js/awf_reflect_summary.test.cjs:322 ✅ Design Integration test: verifies alias table appears in summary

Language Support

Tests analyzed:

  • 🟨 JavaScript (*.test.cjs): 11 tests (vitest)

Verdict

Check passed. 0% of new tests are implementation tests (threshold: 30%).

📖 Understanding Test Classifications

Design Tests (High Value) verify what the system does:

  • Assert on observable outputs, return values, or state changes
  • Cover error paths and boundary conditions
  • Would catch a behavioral regression if deleted
  • Remain valid even after internal refactoring

Implementation Tests (Low Value) verify how the system does it:

  • Assert on internal function calls (mocking internals)
  • Only test the happy path with typical inputs
  • Break during legitimate refactoring even when behavior is correct
  • Give false assurance: they pass even when the system is wrong

Goal: Shift toward tests that describe the system's behavioral contract — the promises it makes to its users and collaborators.

🧪 Test quality analysis by Test Quality Sentinel · ● 1.5M ·

Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

✅ Test Quality Sentinel: 86/100. Test quality is excellent — 0% of new tests are implementation tests (threshold: 30%).

@github-actions
Copy link
Copy Markdown
Contributor

@copilot review all comments
Please address the unresolved review feedback on this PR.

Generated by 👨‍🍳 PR Sous Chef · ● 6.2M ·

@pelikhan
Copy link
Copy Markdown
Collaborator

@copilot review all comments and review. Resolve reviews you fix or ignore with a reason.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 22, 2026

@copilot review all comments and review. Resolve reviews you fix or ignore with a reason.

Handled in 56e7bdf. I fixed the two actionable review points in code: the providers JSDoc now matches the supported keyed-map shape, and the redundant runtime-row filter is removed. I left the model-alias section in place because that output came from the earlier maintainer request to render alias information, so I did not treat the scope comment as a revert request.

@pelikhan pelikhan merged commit 43c5f9c into main May 22, 2026
@pelikhan pelikhan deleted the copilot/add-models-json-rendering branch May 22, 2026 21:00
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.

3 participants