Skip to content

Fix dotnet-maui skill regressions and sharpen decisiveness#947

Open
kubaflo wants to merge 8 commits into
dotnet:mainfrom
kubaflo:kubaflo/dotnet-maui-skills-eval-fixes
Open

Fix dotnet-maui skill regressions and sharpen decisiveness#947
kubaflo wants to merge 8 commits into
dotnet:mainfrom
kubaflo:kubaflo/dotnet-maui-skills-eval-fixes

Conversation

@kubaflo

@kubaflo kubaflo commented Jul 26, 2026

Copy link
Copy Markdown

Summary

Addresses #895 — the cross-family evaluation for the dotnet-maui plugin (8 skills, 48% pass, 1 P0).

Every claim in this PR was validated empirically by building a real .NET MAUI app against the current SDK — not by source reading alone. That mattered: one of my initial "fixes" turned out to be wrong and was reverted (see below).

🔴 P0 — maui-collectionview (FIX-REGRESSION)

Root cause found: the skill documented markup that does not compile.

ItemSizingStrategy was shown on LinearItemsLayout in both SKILL.md and references/collectionview-api.md. It is declared on StructuredItemsView, so the documented form is a hard build break:

error MAUIX2002: No accessible property, BindableProperty, or event found for
"ItemSizingStrategy", or mismatching type between value and property.

This is a plausible driver of the "skilled is worse than baseline" signal — the skill actively taught broken XAML. Corrected to set it on <CollectionView>, keeping the invalid form as an explicit ❌ counter-example.

Per the CTA's FIX-REGRESSION guidance, also added:

  • A Scope Control section with explicit stop-conditions (do NOT act when…) targeting over-application: don't answer beyond the question, don't rewrite working code, don't migrate a working ListView, don't churn style.
  • A narrowed frontmatter trigger (excludes CarouselView/BindableLayout, handler customization, and binding questions that merely mention a list).
  • Demoted prescriptive edits to suggestions the agent may decline, reducing the non-negotiable rules to the three that actually break code.
  • A validation checklist.

🔴 HIGH — maui-app-lifecycle (non-compiling code, newly found)

The iOS ConfigureLifecycleEvents examples called .DidBecomeActive() / .WillResignActive(), which don't exist:

error CS1061: 'IiOSLifecycleBuilder' does not contain a definition for 'DidBecomeActive'

Corrected to .OnActivated() / .OnResignActivation(). The platform-mapping tables now show both the UIKit selector and the builder method, because the names deliberately differ — that mismatch is exactly what made this easy to get wrong.

Correctness fixes

Skill Fix
maui-data-binding The XC0022–XC0025 meanings table was wrong on all four rows. Corrected against Build.Tasks/BuildException.cs + ErrorMessages.resx.
maui-safe-area Claimed WindowSoftInputModeAdjust.Resize was "removed" — it still compiles and is not obsolete. Reframed as Android-only/superseded. Brevity deliberately preserved (EFFICIENT-WIN).

🟡 STRENGTHEN — decisiveness

Ties dominated maui-shell-navigation, maui-theming, maui-data-binding and maui-dependency-injection: the content was correct but read as reference prose the model already knows, so the judge saw no behaviour change.

Each now has a compact "Rules That Change the Answer" table converting prose into when-A-do-B guidance (e.g. IQueryAttributable on the ViewModel not the Page; ContentTemplate for lazy page creation; AddScoped silently behaving as Singleton without an IServiceScope), plus an explicit "don't churn working code" stop-condition to avoid trading ties for losses.

⚠️ Notably NOT changed

  • maui-theming's {AppThemeBinding Light={DynamicResource …}} guidance. Reading AppThemeBindingExtension suggested the nested DynamicResource could never resolve, and I initially "fixed" it. A runtime probe disproved that: after swapping the dictionary the value tracked it (#FF0000#0000FF) while a StaticResource control stayed frozen at #FF0000. The original guidance is correct — reverted. (This is why the empirical step was worth it.)
  • maui-shell-navigation fixture/SDK pinning. Per the [skills-eval] Judge-side transient failures (disabled PAT + session.idle timeout) corrupt reliability verdicts #909 correction, the errored trial was a judge-side disabled-PAT failure, not fixture nondeterminism — so it was treated as STRENGTHEN, not FIX-RELIABILITY.
  • dotnet-maui-doctor (EXEMPLAR) — unchanged.

Validation

  • skill-validator check --plugin ./plugins/dotnet-maui → ✅ all checks passed (8 skills, 0 errors, 26 reference files scanned).
  • A net11.0-maccatalyst MAUI app builds clean with every corrected snippet (CollectionView grid/selection/refresh/swipe/empty-view, Shell ContentTemplate, GetDeferral/Complete, ShellNavigationQueryParameters, IQueryAttributable, DI registrations, iOS lifecycle).
  • Both original buggy forms reproduce the exact errors quoted above.

Full cross-family re-evaluation still to be triggered per the instructions in #895.

Addresses the cross-family evaluation findings in dotnet#895 for the
dotnet-maui plugin (8 skills, 48% pass, 1 P0).

Every claim below was validated empirically by building a real .NET MAUI app
against the current SDK, not by code reading alone.

FIX-REGRESSION - maui-collectionview (P0):
- ItemSizingStrategy was documented on LinearItemsLayout in both SKILL.md and
  references/collectionview-api.md. It is declared on StructuredItemsView, so
  the documented markup is a hard build break:
  "error MAUIX2002: No accessible property, BindableProperty, or event found
  for ItemSizingStrategy". Corrected to set it on CollectionView, with the
  invalid form kept as an explicit counter-example.
- Added a "Scope Control" section with stop-conditions (do NOT act when...),
  narrowed the frontmatter trigger, demoted the non-essential guidance to
  suggestions the agent may decline, and reduced the three non-negotiable
  rules to those that actually break code. This targets the ~30% of trials
  where skilled output was worse than baseline through over-application.
- Added a validation checklist.

HIGH severity, non-compiling - maui-app-lifecycle:
- The iOS ConfigureLifecycleEvents examples called .DidBecomeActive() and
  .WillResignActive(), which do not exist:
  "error CS1061: IiOSLifecycleBuilder does not contain a definition for
  DidBecomeActive". Corrected to .OnActivated() / .OnResignActivation() and
  documented that the builder method names deliberately differ from the UIKit
  selector names (the mapping tables now show both columns).

Correctness - maui-data-binding:
- The XC0022-XC0025 meanings table was wrong on all four rows. Corrected
  against Build.Tasks/BuildException.cs and ErrorMessages.resx (XC0022 =
  binding without x:DataType, XC0023 = x:DataType explicitly null, XC0024 =
  x:DataType from outer scope, XC0025 = explicit Source).

Correctness - maui-safe-area:
- Claimed WindowSoftInputModeAdjust.Resize was "removed". It still compiles
  and is not obsolete. Reframed as Android-only and superseded, preserving
  the skill's brevity (EFFICIENT-WIN - deliberately not grown).

STRENGTHEN - decisiveness (ties dominated these skills):
- Added a compact "Rules That Change the Answer" table to maui-shell-navigation,
  maui-data-binding, maui-dependency-injection and maui-theming, converting
  reference prose into when-A-do-B guidance, each with an explicit "do not
  churn working code" stop-condition.

Notably NOT changed:
- maui-theming's {AppThemeBinding Light={DynamicResource ...}} guidance. This
  looked invalid from source reading, but a runtime probe proved it is fully
  dynamic (value tracked a dictionary swap: #FF0000 -> #0000FF, while the
  StaticResource control stayed #FF0000). The original guidance is correct.
- maui-shell-navigation fixture/SDK pinning. Per the dotnet#909 correction the
  errored trial was a judge-side disabled-PAT failure, not fixture
  nondeterminism, so the skill was treated as STRENGTHEN.
- dotnet-maui-doctor (EXEMPLAR) is unchanged.

Validation:
- skill-validator check --plugin ./plugins/dotnet-maui -> all checks passed
  (8 skills, 0 errors, 26 reference files scanned).
- All corrected snippets compile in a net11.0-maccatalyst MAUI app; both
  original buggy forms reproduce the exact errors quoted above.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 58513e0c-4086-4112-9ea1-95dbd8e8e469
Copilot AI review requested due to automatic review settings July 26, 2026 08:10
@kubaflo
kubaflo requested review from a team, Redth and jfversluis as code owners July 26, 2026 08:10
@kubaflo

kubaflo commented Jul 26, 2026

Copy link
Copy Markdown
Author

/evaluate

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

This PR updates the dotnet-maui plugin’s skill documentation to fix known non-compiling snippets (regressions) and to make several skills more behaviorally decisive by adding concise “Rules That Change the Answer” / scope-control guidance.

Changes:

  • Fixes MAUI documentation examples that previously produced build errors (CollectionView ItemSizingStrategy placement; iOS lifecycle builder method names).
  • Adds “Rules That Change the Answer” (and related stop-conditions / validation checklists) to reduce ties and prevent over-application.
  • Clarifies/adjusts guidance around safe-area + keyboard avoidance and compiled-binding warning meanings.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
plugins/dotnet-maui/skills/maui-theming/SKILL.md Adds a “Rules That Change the Answer” section and clarifies combined theming guidance.
plugins/dotnet-maui/skills/maui-shell-navigation/SKILL.md Adds a “Rules That Change the Answer” table and stop-conditions for Shell navigation.
plugins/dotnet-maui/skills/maui-safe-area/SKILL.md Reframes WindowSoftInputModeAdjust.Resize as supported but Android-only; clarifies obsoletion status.
plugins/dotnet-maui/skills/maui-dependency-injection/SKILL.md Adds a compact rules table emphasizing lifetimes and MAUI scoped behavior.
plugins/dotnet-maui/skills/maui-data-binding/SKILL.md Adds rules table and corrects the XC0022–XC0025 meanings section.
plugins/dotnet-maui/skills/maui-collectionview/SKILL.md Adds scope control/stop-conditions, fixes ItemSizingStrategy guidance, and adds validation checklist.
plugins/dotnet-maui/skills/maui-collectionview/references/collectionview-api.md Corrects ItemSizingStrategy placement and adds explicit ✅/❌ examples.
plugins/dotnet-maui/skills/maui-app-lifecycle/SKILL.md Fixes iOS lifecycle builder method names and adds a mapping table note.
plugins/dotnet-maui/skills/maui-app-lifecycle/references/lifecycle-api.md Mirrors the lifecycle mapping fix + note in the reference doc.

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

| Rule | Do this | Not this | Why |
|---|---|---|---|
| **Runtime-swapped values must be dynamic** | `{DynamicResource Key}` | `{StaticResource Key}` | `StaticResource` resolves once at load and never updates when dictionaries are swapped. |
| **Android must declare `UiMode`** | `ConfigurationChanges = … \| ConfigChanges.UiMode` on `MainActivity` | Omitting it | Without it Android restarts the activity on theme change — navigation state is lost and it looks like a crash. |

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in ad057a07. The cell no longer contains the escaped pipe — it now reads "Include ConfigChanges.UiMode in the ConfigurationChanges list on MainActivity". The full attribute with real pipes is still shown in the fenced code block further down, so nothing is lost and there is no \| for a model to copy into C#.

Driven by a local skilled-vs-baseline run (vally 0.10, executor
claude-opus-4.6, judge gpt-5.5, n=3 per stimulus). The judge rationales
named two concrete, fixable causes for the remaining losses:

1. "Response B introduces an unresolved x:DataType prefix unless additional
   namespace declarations are added" (penalised on 2 trials). The skill used
   x:DataType="models:..." in six snippets but never declared xmlns:models,
   so the examples were not copy-pasteable. Basic Setup is now a complete
   ContentPage including the xmlns:models declaration, with an explicit
   instruction to carry the matching xmlns when handing over a snippet.

2. Baseline beat the skill on the ListView/ViewCell migration stimulus by
   supplying nuance the skill lacked - that ListView still exists, plus
   event/API replacements. Added a "Migrating from ListView" section with a
   verified mapping table (ViewCell, ItemSelected/ItemTapped ->
   SelectionChanged, IsPullToRefreshEnabled -> RefreshView, IsGroupingEnabled
   -> IsGrouped, HasUnevenRows -> ItemSizingStrategy, and the missing
   separator APIs). Every member was confirmed against
   Controls/PublicAPI.Shipped.txt.

Measured effect on the same eval (12 trials per arm, identical settings):

  original skill   17% win rate   2 wins / 4 ties / 6 losses   mean -0.13
  this PR          42% win rate   5 wins / 6 ties / 1 loss     mean +0.13

Losses drop 6 -> 1 and the mean impact flips from negative (the
FIX-REGRESSION signal in dotnet#895) to positive. n=12 on a single executor, so
directional rather than significant, but the loss collapse is the intended
effect of the regression fix.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 58513e0c-4086-4112-9ea1-95dbd8e8e469
Copilot AI review requested due to automatic review settings July 26, 2026 09:49
@kubaflo

kubaflo commented Jul 26, 2026

Copy link
Copy Markdown
Author

Evaluation results (skilled vs. baseline)

Per @AbhitejJohn's verification guidance in #895 (comment), I ran the skilled-vs-baseline comparison for the P0 skill (maui-collectionview). The /evaluate gate requires write access (Actor kubaflo has permission: readActor does not have write access), so I ran the same harness locally instead:

  • vally 0.10.0 (@microsoft/vally-cli), driving dotnet-skills.experiment.yaml unmodified except runs: 3
  • Executor claude-opus-4.6, judge gpt-5.5 — cross-family, judge ≠ executor family, matching the CI grid's rule
  • --eval-filter tests/dotnet-maui/maui-collectionview/eval.yaml, n=3 per stimulus → 12 trials per arm
  • Both arms run identically; the only difference is the skill content

Headline

Arm Win rate Wins Ties Losses Mean impact Errors
main (original skill) 17% 2 4 6 −0.13 0
This PR (first commit) 25% 3 4 5 −0.07 0
This PR (head) 42% 5 6 1 +0.13 0

Losses 6 → 1, and mean impact flips from negative to positive.

The main arm independently reproduced the exact regression signature reported in #895 — 6 losses over 12 trials (the issue's table records Loss▵ 6 for this skill). That reproduction is what gives me confidence the harness is measuring the right thing.

⚠️ Caveat, stated plainly: n=12 on a single executor family. The head arm's 95% CI is [−0.03, +0.30], so this is directional, not statistically significant. The full 5-family grid should still be run before trusting the magnitude. The loss collapse (6 → 1) is the effect the FIX-REGRESSION change was aiming for.

The second commit was driven by these results

The first commit only moved losses 6 → 5. Reading the judge's per-trial rationales identified two concrete causes, which b07628c fixes:

  1. "Response B introduces an unresolved x:DataType prefix unless additional namespace declarations are added" — penalised on 2 trials.

    The skill used x:DataType="models:…" in six snippets but never declared xmlns:models, so its examples weren't copy-pasteable. Basic Setup is now a complete ContentPage including the declaration.

  2. On the ListView/ViewCell stimulus, baseline won by supplying nuance the skill lacked — that ListView still exists, plus event/API replacements. Added a Migrating from ListView table (every member verified against PublicAPI.Shipped.txt), including the commonly-missed fact that CollectionView has no separator API.

Coverage gap worth flagging

None of the four maui-collectionview stimuli exercise ItemSizingStrategy or performance guidance — so the eval cannot detect the build-break this PR fixes:

error MAUIX2002: No accessible property, BindableProperty, or event found for "ItemSizingStrategy"

That defect was caught by compiling the documented XAML, not by the eval. A stimulus covering item sizing / performance would close the gap.

Compile validation

Separately, every corrected snippet was verified by building a real net11.0-maccatalyst MAUI app, and both original buggy forms reproduce their exact errors:

Claim Result
ItemSizingStrategy on LinearItemsLayout (original) error MAUIX2002
ItemSizingStrategy on CollectionView (fixed) ✅ builds
.DidBecomeActive() / .WillResignActive() (original) error CS1061: 'IiOSLifecycleBuilder' does not contain a definition for 'DidBecomeActive'
.OnActivated() / .OnResignActivation() (fixed) ✅ builds
WindowSoftInputModeAdjust.Resize ("removed") ✅ builds, not obsolete → claim corrected
{AppThemeBinding Light={DynamicResource …}} ✅ builds and is dynamic at runtime (#FF0000#0000FF after a dictionary swap, vs. StaticResource frozen at #FF0000) → my proposed "fix" was wrong and was reverted

skill-validator check --plugin ./plugins/dotnet-maui → ✅ all checks passed (8 skills, 0 errors, 26 reference files).

A maintainer will still need to post /evaluate to run the full 5-family grid.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 58513e0c-4086-4112-9ea1-95dbd8e8e469

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

plugins/dotnet-maui/skills/maui-theming/SKILL.md:62

  • In the theming rules table, the inline code uses \| to escape the pipe character. Because this is inside a code span, the escape isn't needed for Markdown tables and it produces an invalid C# expression if someone copies it (bitwise OR is |, not \|).
| **Runtime-swapped values must be dynamic** | `{DynamicResource Key}` | `{StaticResource Key}` | `StaticResource` resolves once at load and never updates when dictionaries are swapped. |
| **Android must declare `UiMode`** | `ConfigurationChanges = … \| ConfigChanges.UiMode` on `MainActivity` | Omitting it | Without it Android restarts the activity on theme change — navigation state is lost and it looks like a crash. |
| **Force a theme via `UserAppTheme`** | `Application.Current.UserAppTheme = AppTheme.Dark` | Manually re-assigning colors | `UserAppTheme` overrides the OS; `AppTheme.Unspecified` returns to following the system. |

Copilot AI review requested due to automatic review settings July 26, 2026 09:51

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

plugins/dotnet-maui/skills/maui-theming/SKILL.md:61

  • In this table row, the escaped pipe (\|) is inside an inline code span, so it will render with the backslash visible (and users may copy it). Consider using an HTML entity for the pipe so the rendered code shows the correct | without breaking the markdown table.
| **Android must declare `UiMode`** | `ConfigurationChanges = … \| ConfigChanges.UiMode` on `MainActivity` | Omitting it | Without it Android restarts the activity on theme change — navigation state is lost and it looks like a crash. |

Reviewed by claude-opus-5, claude-opus-4.8, gpt-5.6-sol and gpt-5.5.
Verdicts were split (2 SHIP / 1 FIX / 1 NEEDS_CHANGES), so the blocking and
consensus findings are addressed here. Every disputed factual claim was
re-verified against the dotnet/maui source before changing anything.

Factual corrections (reviewers were right, I was wrong):

- ListView IS marked [Obsolete] as of .NET 10 ("ListView is deprecated. Please
  use CollectionView instead.", ListView.cs:19). Verified it is present on
  main, net10.0 and release/10.0.1xx-sr7, and absent on release/9.0.1xx. The
  previous "it is not removed or obsolete" wording was wrong. (gpt-5.6-sol)

- MAUI DOES create one IServiceScope per window
  (MauiContextExtensions.MakeWindowScope, called from the iOS/Android/Windows/
  Tizen ApplicationExtensions), so "a Scoped registration resolves from the
  root scope and behaves like a Singleton" was over-broad. Reworded to keep the
  rubric-rewarded "no built-in request scope like ASP.NET Core" phrasing while
  stating the window-scope reality. (opus-5, gpt-5.6-sol)

- ItemTapped -> SelectionChanged is not behaviour-preserving (SelectionChanged
  only fires when the selection changes), and RowHeight -> MeasureFirstItem is
  not an explicit row height. Split into accurate rows. (gpt-5.6-sol)

Rules that could suppress rubric-rewarded answers (the main eval risk):

- The ListView stop-condition ("do not migrate unless the user asked to
  migrate") fired on eval stimulus 4, which asks "Should I keep using ListView
  in MAUI?" - the user asks *whether*, not *to*. Reworded to recommend
  CollectionView when asked which control to use, while still forbidding
  silent rewrites. Flagged independently by opus-5 and gpt-5.5.

- data-binding's blanket "do not convert a working binding" could talk the
  agent out of the rubric-rewarded x:DataType recommendation. Scoped it. (opus-5)

- "Point out a concrete defect or say nothing" -> answer the question asked;
  "say nothing" invited non-answers, which judges penalise. (opus-5)

Internal contradictions introduced by this PR:

- data-binding Common Pitfalls still said "enable XC0025 as error" for a
  missing x:DataType; XC0022 is the missing-x:DataType code. (opus-4.8)
- The rules table said x:DataType "root element only" two rows above a row
  requiring one per DataTemplate. Reworded to "wherever a binding scope
  starts". (opus-5, gpt-5.6-sol)
- The Validation checklist re-armed items the Scope Control section had just
  demoted; scoped it to markup the agent actually wrote. (opus-5)
- Dropped the "Using ListView instead of CollectionView" pitfall row, which
  contradicted the new migration section. (opus-5)

Other:

- Removed the escaped pipe (\|) from the theming rules table - a model reading
  raw Markdown could copy it into C#. (Copilot reviewer, opus-5)
- Softened "Apply these three rules to every theming answer" so narrow
  questions don't attract unrelated UiMode/UserAppTheme guidance. (gpt-5.5)
- De-duplicated the AddScoped guidance that appeared 4x. (opus-5)

Measured effect (maui-collectionview, executor claude-opus-4.6, judge gpt-5.5,
n=3/stimulus, 12 trials/arm, base re-run in the same session):

  base (main, no fix)   33% win   4 wins / 4 ties / 4 losses   mean +0.00 [-0.22,+0.22]
  previous commit       42% win   5 wins / 6 ties / 1 loss     mean +0.13 [-0.03,+0.30]
  this commit           58% win   7 wins / 5 ties / 0 losses   mean +0.23 [+0.10,+0.36]

Zero losses, and the confidence interval is now entirely above zero - the
first arm in this series with a statistically significant positive impact.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 58513e0c-4086-4112-9ea1-95dbd8e8e469
Copilot AI review requested due to automatic review settings July 26, 2026 10:27

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

<CollectionView ItemsSource="{Binding Items}" ItemSizingStrategy="MeasureFirstItem" />
```
Only use it when every item really is the same height — with variable-height items it clips or stretches content.
- **Always use `ObservableCollection<T>`**, not `List<T>`. Swapping a `List` forces a full re-render.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 746679a7. You were right on both points: it contradicted this PR's own "use ObservableCollection<T> when the list mutates" rule, and the re-render claim was imprecise. Rewritten around INotifyCollectionChanged and in-place mutation, and it now explicitly notes that replacing ItemsSource re-renders everything regardless of collection type.

Round-2 review by claude-opus-5, claude-opus-4.8, gpt-5.6-sol, gpt-5.5:
2 SHIP, 2 FIX. All blocking and consensus findings addressed.

Consensus finding (opus-5 + gpt-5.6-sol) — the flagship "complete,
copy-pasteable page" declared xmlns:models but had no root x:DataType, so its
outer ItemsSource binding was an uncompiled reflection binding. That undercut
the skill's own compiled-bindings guidance and left rubric credit unclaimed on
collectionview stimulus 1. Added xmlns:vm + root x:DataType.

opus-5 blocking claim — <WarningsAsErrors>XC0022;XC0025</WarningsAsErrors>
(pre-existing, line 110 on main) was said to break any build using Source= or
RelativeSource bindings, because XC0025 means "binding not compiled due to an
explicit Source" and MauiEnableXamlCBindingWithSourceCompilation defaults true
only under AOT/full-trim.

  Tested empirically: a net11.0-maccatalyst app with that exact
  WarningsAsErrors value plus both a Source={x:Reference} binding and a
  RelativeSource binding BUILDS CLEAN. The XC diagnostics are not emitted on
  the current SourceGen path (Descriptors.cs has XC0022/0023/0025 commented
  out), so the claim does not reproduce on current MAUI.

  It can still bite on the older XamlC path, and the reasoning is sound, so
  the guidance now pairs the switch with the setting and states the caveat
  rather than changing the rubric-rewarded value.

Other round-2 fixes:
- "A binding falls back to reflection (XC0022/XC0023) | Fix the path" still
  carried pre-correction semantics; neither code concerns the binding path
  (that is XC0045). Reworded. (opus-5)
- "Everything below is a suggestion the agent may decline" literally demoted
  the Key Rules and the Validation checklist. Scoped it to the API reference
  sections and promoted x:DataType to a fourth non-negotiable. (opus-5)
- AddScoped lifetime table row and checklist still implied a manual scope is
  the only scope; both now reflect window lifetime. (gpt-5.6-sol)
- Shell "Option 2: QueryProperty — apply directly on the page class"
  contradicted the new rule table and the eval rubric ("on the ViewModel, not
  the page"). (opus-5)

Copilot review comment — "Always use ObservableCollection<T>, not List<T>.
Swapping a List forces a full re-render" contradicted this PR's own
"use ObservableCollection when the list mutates" rule, and the claim was
imprecise: replacing ItemsSource re-renders regardless of collection type.
Rewritten around INotifyCollectionChanged and in-place mutation.

Not changed: gpt-5.6-sol and opus-5 both suggested editing
tests/dotnet-maui/*/eval.yaml rubrics (safe-area "replaced by", DI "behaves
like Singleton") to match the corrected facts. Changing the benchmark in the
same PR that changes the skill would invalidate the comparison, so these are
left for maintainers and called out in the PR instead.

Measured (maui-collectionview, executor claude-opus-4.6, judge gpt-5.5,
n=3/stimulus, 12 trials/arm, base re-run in the same session each time):

  round 3   base +0.00        this PR +0.23     delta +0.23
  round 4   base -0.07        this PR +0.17     delta +0.24

Absolute numbers move with run-to-run noise (three independent base runs gave
-0.13, +0.00, -0.07), but the advantage over base is stable at ~+0.24 mean and
~+25pp win rate across every paired run.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 58513e0c-4086-4112-9ea1-95dbd8e8e469
Copilot AI review requested due to automatic review settings July 26, 2026 10: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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.


| Situation | Do this | Not this |
|---|---|---|
| Declaring pages in `AppShell.xaml` | `<ShellContent ContentTemplate="{DataTemplate pages:MyPage}" />` — lazy | `<ShellContent Content="..."/>`, which constructs **every** page at startup |

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 0b86a416. Confirmed against source: ShellContent is [ContentProperty(nameof(Content))] with Content typed object (ShellContent.cs:15,45), so the eager form is nested markup. The row now shows <ShellContent><views:MyPage /></ShellContent> as the anti-pattern and declares xmlns:views (the previous pages: prefix was undeclared). gpt-5.6-sol flagged this independently.

Comment on lines +193 to +195
Apply on the **ViewModel** class (or the page, if it genuinely owns the state).
Prefer `IQueryAttributable` on the ViewModel — it keeps navigation state with the
`BindingContext` and handles multiple parameters in one call:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 0b86a416. The example is now AnimalDetailsViewModel : ObservableObject, and it also uses [ObservableProperty] rather than a plain auto-property — Shell applies query attributes after the page constructor sets BindingContext, so a non-notifying property would leave the binding on its initial value. Compile-verified with CommunityToolkit.Mvvm on net11.0-maccatalyst.

Round-3 review by claude-opus-5, claude-opus-4.8, gpt-5.6-sol, gpt-5.5:
3 SHIP, 1 FIX. Both of gpt-5.6-sol's blocking items are fixed here, along
with the non-blocking findings from opus-5 and gpt-5.5.

gpt-5.6-sol (blocking):
- The Shell rules table used an undeclared `pages:` prefix, and its "Not this"
  cell claimed `<ShellContent Content="..."/>` constructs pages eagerly.
  `ShellContent` is `[ContentProperty(nameof(Content))]` with `Content` typed
  `object` (ShellContent.cs:15,45), so the eager form is nested markup, not a
  string attribute. Row rewritten with a declared `xmlns:views` and the real
  eager form `<ShellContent><views:MyPage /></ShellContent>`.
- QueryProperty prose said "ViewModel" while the example was still a
  ContentPage. Also flagged independently by gpt-5.5 (consensus).

opus-5 (non-blocking, both real):
- The rules-table cell I added in round 2 contained `</...>` — not valid XML.
  A model lifting that cell verbatim emits an unparseable .csproj. Reworded to
  prose so there is no truncated tag to copy.
- The QueryProperty ViewModel example used a plain auto-property. On a page
  that was harmless (code-behind reads it); on a ViewModel it is the binding
  target, and Shell applies query attributes *after* BindingContext is set, so
  a non-notifying property leaves the binding on its initial value. Switched
  to [ObservableProperty] and explained why.
- The "complete, copy-pasteable page" never set BindingContext, so pasting it
  renders blank — the exact failure maui-data-binding lists first. Added it.

Both changed snippets were compile-verified in a net11.0-maccatalyst app
(flagship CollectionView page with root x:DataType + BindingContext, and the
[QueryProperty] + [ObservableProperty] ViewModel with CommunityToolkit.Mvvm).

Measured (maui-collectionview, paired base + current run per round, same
session, executor claude-opus-4.6, judge gpt-5.5, n=3/stimulus, 12 trials/arm):

  round 3   base +0.00   this PR +0.23   delta +0.23
  round 4   base -0.07   this PR +0.17   delta +0.24
  round 5   base +0.00   this PR +0.13   delta +0.13

Round 5 is this commit. The delta is smaller than rounds 3-4 but the 95% CIs
overlap heavily at n=12 (base CI +/-0.24), so this is not a demonstrated
regression. The changes in this commit are correctness fixes - invalid XML,
a silently-broken binding, and an inaccurate Shell claim - which are worth
making regardless of a benchmark that cannot resolve a 0.1 difference. A
higher-n run follows to tighten the estimate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 58513e0c-4086-4112-9ea1-95dbd8e8e469
Copilot AI review requested due to automatic review settings July 26, 2026 11:24

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

| Mistake | Fix |
|---------|-----|
| Missing `x:DataType` — bindings silently fall back to reflection | Add `x:DataType` at page root and every `DataTemplate`; enable `XC0025` as error |
| Missing `x:DataType` — bindings silently fall back to reflection | Add `x:DataType` at page root and every `DataTemplate`; enable `XC0022` as error |

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in df0806a4. The pitfall row no longer restates a partial prescription — it now points at the "Enforce binding warnings as errors" section as the single source of truth, so there is only one place describing which warnings to promote.

The data-binding "Common Pitfalls" row said "enable XC0022 as error" while the
"Enforce binding warnings as errors" section above recommends XC0022;XC0025
paired with MauiEnableXamlCBindingWithSourceCompilation - two different
prescriptions for the same task. The pitfall row now points at that section as
the single source of truth instead of restating a partial version.

Copilot's four earlier comments on this PR (theming escaped pipe,
ObservableCollection contradiction, ShellContent eager form, QueryProperty
example) were already addressed in previous commits; the ShellContent and
QueryProperty findings matched gpt-5.6-sol's and gpt-5.5's independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 58513e0c-4086-4112-9ea1-95dbd8e8e469
Copilot AI review requested due to automatic review settings July 26, 2026 11:43
@kubaflo

kubaflo commented Jul 26, 2026

Copy link
Copy Markdown
Author

Multi-model review loop — converged (4/4 SHIP) + high-n validation

Ran an iterative review → fix → re-measure loop with four reviewers from three families: claude-opus-5, claude-opus-4.8, gpt-5.6-sol, gpt-5.5. Each round they reviewed the full diff with access to the dotnet/maui source as ground truth and the eval rubrics.

Round opus-5 opus-4.8 gpt-5.6-sol gpt-5.5
1 FIX SHIP NEEDS_CHANGES SHIP
2 FIX SHIP FIX SHIP
3 SHIP SHIP FIX SHIP
4 SHIP SHIP SHIP SHIP

What the reviewers caught that I had wrong

Several were factual errors in my own changes, verified against source before fixing:

  • ListView IS [Obsolete] as of .NET 10 (ListView.cs:19; present on main/net10.0/release/10.0.1xx-sr7, absent on release/9.0.1xx). My "not removed or obsolete" wording was wrong. (gpt-5.6-sol)
  • MAUI DOES create one IServiceScope per window (MauiContextExtensions.MakeWindowScope). "Behaves like a Singleton" was over-broad. (opus-5, gpt-5.6-sol)
  • ShellContent.Content is the [ContentProperty] (typed object), so the eager form is nested markup — not Content="...". My "Not this" cell was wrong, and used an undeclared pages: prefix. (gpt-5.6-sol, Copilot)
  • ItemTappedSelectionChanged isn't behaviour-preserving (SelectionChanged only fires on change), and RowHeightMeasureFirstItem isn't an explicit height. (gpt-5.6-sol)
  • A stop-condition I added suppressed a rubric-rewarded answer — "do not migrate unless the user asked to migrate" fired on stimulus 4, which asks "Should I keep using ListView?" (asks whether, not to). (opus-5 + gpt-5.5, consensus)
  • </...> truncated XML in a table cell I'd just added — a model copying it emits an unparseable .csproj. (opus-5)
  • [QueryProperty] on a ViewModel needs [ObservableProperty] — Shell applies query attributes after BindingContext is set, so a plain auto-property leaves the binding stuck. (opus-5)

One blocking claim did not survive testing: opus-5 argued <WarningsAsErrors>XC0022;XC0025</WarningsAsErrors> breaks any build with Source=/RelativeSource bindings. I built an app with exactly that setting plus both binding kinds — it compiles clean, because those diagnostics are commented out on the current SourceGen path. The value is also pre-existing on main and rubric-rewarded, so I kept it and documented the caveat instead.

All Copilot bot comments are resolved; its ShellContent and QueryProperty findings independently matched the model reviewers'.

Final measurement — n=6 (24 trials/arm), base re-run in the same session

Arm Win rate W / T / L Mean impact 95% CI
base (main, no fix) 33% 8 / 8 / 8 +0.00 [−0.14, +0.14]
this PR 71% 17 / 4 / 3 +0.23 [+0.11, +0.35]

The PR's CI is entirely above zero; base straddles it.

Every commit was measured against base and the prior commit

Stage base mean PR mean delta
original skill (issue #895 repro: 6 losses) −0.13
commit 1 −0.07 +0.06
commit 2 +0.13 +0.20
review round 1 +0.00 +0.23 +0.23
review round 2 −0.07 +0.17 +0.24
review round 3 +0.00 +0.13 +0.13
final, n=24 +0.00 +0.23 +0.23

Five independent base runs gave −0.13, +0.00, −0.07, +0.00, +0.00 — that spread is why every round re-runs base rather than comparing against a stale number. The round-3 dip to +0.13 looked like a regression at n=12; the n=24 run resolved it as noise (+0.23).

Notes for maintainers

  • Two eval rubrics now assert things the corrected skills contradict: maui-safe-area ("WindowSoftInputModeAdjust.Resize replaced by" — it isn't removed) and maui-dependency-injection ("behaves like Singleton" — it's window-scoped). I deliberately did not touch tests/ — changing the benchmark in the same PR that changes the skill would invalidate this comparison.
  • The maui-collectionview skill-validator "comprehensive skill" token warning is expected; the measured +38pp win rate on that skill is the counter-evidence.
  • /evaluate still needs a maintainer (fork PRs lack write access).

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (1)

plugins/dotnet-maui/skills/maui-collectionview/SKILL.md:117

  • The “Key rules” section says to always bind ItemsSource to ObservableCollection<T>, but later in the same file the Performance Tips correctly note that List<T> is fine when the list never changes after binding. This inconsistency can cause unnecessary churn (telling users to switch to ObservableCollection<T> even for static lists). Align the “Key rules” bullet with the later guidance.
- Bind `ItemsSource` to an `ObservableCollection<T>` so the UI updates on add/remove.

@JanKrivanek

Copy link
Copy Markdown
Member

/evaluate

@github-actions

Copy link
Copy Markdown
Contributor

📊 Skill Evaluation Results

7 skill(s) evaluated — 4 improved, 3 no credible improvement. A skill passes only on a credible improvement over baseline (mean preference > 0 with its 95% CI above 0); ⚠️ marks a comparison that couldn't complete (errored/unmatched trials).

Skill Result Δ Preference [95% CI] W/T/L Quality Baseline Overfit Skills Loaded
maui-app-lifecycle +55.0% [+7.3%, +102.7%] 4/0/0 5.0/5 3.8/5 ✅ 0.14 4/4 · 4/4 (plugin)
maui-collectionview +40.0% [+40.0%, +40.0%] 4/0/0 5.0/5 4.9/5 ✅ 0.07 4/4 · 4/4 (plugin)
maui-data-binding +40.0% [+40.0%, +40.0%] 4/0/0 4.9/5 4.2/5 ✅ 0.11 4/4 · 4/4 (plugin)
maui-dependency-injection +0.0% [-52.0%, +52.0%] 1/2/1 5.0/5 4.6/5 ✅ 0.13 4/4 · 4/4 (plugin)
maui-safe-area +100.0% [+100.0%, +100.0%] 4/0/0 5.0/5 2.3/5 ✅ 0.08 4/4 · 4/4 (plugin)
maui-shell-navigation +35.0% [-40.2%, +110.2%] 2/2/0 5.0/5 3.9/5 ✅ 0.10 4/4 · 4/4 (plugin)
maui-theming +20.0% [-43.6%, +83.6%] 3/0/1 5.0/5 5.0/5 ✅ 0.10 4/4 · 4/4 (plugin)
ℹ️ Column legend
  • Δ Preference — mean head-to-head preference of skilled vs baseline (−100%…+100%), judged by vally compare.
  • [95% CI] — 95% confidence interval on that mean; a skill passes only when the whole interval is above 0.
  • W/T/L — wins / ties / losses across trials.
  • Quality / Baseline — mean absolute judge score 0–5 (skilled isolated vs skill-free control).
  • Overfit — overfitting-judge severity (✅ Low, 🟡 Moderate, 🔴 High, — none) with its score.
  • Skills Loaded — of the scenarios that expect activation, how many actually activated / that total (plugin run shown when present); ⚠️ marks a scenario that expected activation but didn't activate.
✅ maui-app-lifecycle — details

Reason: Mean preference +55.0% [95% CI 7.3%, 102.7%], win rate 100.0% (4W/0T/0L over 4 trial(s)) — credibly better

Scenario Mean preference Trials (W/T/L)
▲ Avoid legacy Xamarin.Forms lifecycle methods +40.0% 1/0/0
▲ Platform-specific lifecycle mapping +40.0% 1/0/0
▲ Save and restore state on background +100.0% 1/0/0
▲ Window lifecycle event subscription +40.0% 1/0/0
✅ maui-collectionview — details

Reason: Mean preference +40.0% [95% CI 40.0%, 40.0%], win rate 100.0% (4W/0T/0L over 4 trial(s)) — credibly better

Scenario Mean preference Trials (W/T/L)
▲ Avoid ListView and ViewCell mistakes +40.0% 1/0/0
▲ Basic CollectionView with data binding and DataTemplate +40.0% 1/0/0
▲ Grid layout with CollectionView +40.0% 1/0/0
▲ Selection and pull-to-refresh with CollectionView +40.0% 1/0/0
✅ maui-data-binding — details

Reason: Mean preference +40.0% [95% CI 40.0%, 40.0%], win rate 100.0% (4W/0T/0L over 4 trial(s)) — credibly better

Scenario Mean preference Trials (W/T/L)
▲ Create and use an IValueConverter +40.0% 1/0/0
▲ Diagnose missing BindingContext and non-compiled bindings +40.0% 1/0/0
▲ Implement MVVM ViewModel with ObservableObject +40.0% 1/0/0
▲ Set up compiled bindings with x:DataType on a page +40.0% 1/0/0
❌ maui-dependency-injection — details

Reason: Mean preference +0.0% [95% CI -52.0%, 52.0%], win rate 25.0% (1W/2T/1L over 4 trial(s)) — no improvement

Scenario Mean preference Trials (W/T/L)
▼ Avoid AddScoped pitfall in MAUI -40.0% 0/0/1
▲ Platform-specific service registration with fallback +40.0% 1/0/0
= Register services with correct lifetimes in MauiProgram.cs +0.0% 0/1/0
= Shell navigation auto-resolves DI-registered pages +0.0% 0/1/0
✅ maui-safe-area — details

Reason: Mean preference +100.0% [95% CI 100.0%, 100.0%], win rate 100.0% (4W/0T/0L over 4 trial(s)) — credibly better

Scenario Mean preference Trials (W/T/L)
▲ Avoid deprecated UseSafeArea in new .NET 10 project +100.0% 1/0/0
▲ Edge-to-edge layout with SafeAreaEdges +100.0% 1/0/0
▲ Handle notch and status bar safe areas on iOS +100.0% 1/0/0
▲ Keyboard avoidance with safe area for chat UI +100.0% 1/0/0
❌ maui-shell-navigation — details

Reason: Mean preference +35.0% [95% CI -40.2%, 110.2%], win rate 50.0% (2W/2T/0L over 4 trial(s)) — not credible (95% CI includes 0)

Scenario Mean preference Trials (W/T/L)
▲ Diagnose common Shell navigation mistakes +40.0% 1/0/0
▲ Handle back navigation and unsaved changes guard +100.0% 1/0/0
= Navigate with parameters using GoToAsync +0.0% 0/1/0
= Set up Shell navigation with tabs and flyout +0.0% 0/1/0
❌ maui-theming — details

Reason: Mean preference +20.0% [95% CI -43.6%, 83.6%], win rate 75.0% (3W/0T/1L over 4 trial(s)) — not credible (95% CI includes 0)

Scenario Mean preference Trials (W/T/L)
▲ Add light/dark mode support using AppThemeBinding +40.0% 1/0/0
▼ Avoid common theming mistakes -40.0% 0/0/1
▲ Create custom themes with ResourceDictionary switching +40.0% 1/0/0
▲ Detect and respond to system theme changes +40.0% 1/0/0

🔍 Full Results - additional metrics and failure investigation steps

To investigate failures, paste this to your AI coding agent:

For PR 947 in dotnet/skills, download eval artifacts with gh run download 30246707498 --repo dotnet/skills --pattern "vally-results-*" --dir ./eval-results, then fetch https://raw.githubusercontent.com/dotnet/skills/df0806a4dc9101e006beffa0a5d98a225efd9cbb/eng/vally-adapter/InvestigatingResults.md and follow it to analyze the results.json files. Diagnose each failure, suggest fixes to the eval.yaml and skill content, and tell me what to fix first.

▶ Sessions Visualisation -- interactive replay of all evaluation sessions
📊 Session Analytics (preview) -- aggregated metrics across evaluation sessions

The maintainer-triggered /evaluate run (actions/runs/30246707498) passed 4 of 7
skills. maui-collectionview - the P0 this PR exists to fix - passed 4W/0T/0L,
alongside maui-safe-area (+100%), maui-app-lifecycle (+55%) and
maui-data-binding (+40%). This commit addresses the other three. Only those
three files change; the four passing skills are untouched.

Diagnosis from the eval artifacts: in every failing scenario the skilled answer
was SHORTER than baseline (shell 1804 vs 2433 chars, theming 1347 vs 1541).
The scope-control wording added earlier in this PR - needed to stop
maui-collectionview over-applying - had over-corrected the other skills into
answering too narrowly. Baseline kept winning by including the follow-through
code that makes a fix actionable.

maui-shell-navigation (was 2W/2T/0L, +35% not credible):
- Added "answer narrowly, but completely": show AppShell markup *and*
  RegisterRoute, GoToAsync *and* the receiving IQueryAttributable, and present
  both parameter-passing approaches with when each fits.
- Local n=4: 16W/0T/0L, mean +0.66.

maui-dependency-injection (was 1W/2T/1L, +0.0%):
Two claims the judge repeatedly called "misleading"/"overconfident", both
verified wrong against source:
- "Unregistered page silently skips injection - dependencies are silently null,
  no exception is thrown". Routed pages go through
  ActivatorUtilities.GetServiceOrCreateInstance (Routing.cs:336), which injects
  registered dependencies and THROWS when one cannot be resolved.
  ContentTemplate pages go through Activator.CreateInstance
  (ElementTemplate.cs:33) - no DI at all, and a MissingMethodException rather
  than null dependencies. Section rewritten around that real distinction.
- "must be AddTransient" softened to "prefer", with the case where Singleton is
  defensible.
- Also added the alternatives the judge rewarded baseline for: explicit
  IServiceScopeFactory.CreateScope() and the factory pattern.
- Local n=4: 15W/1T/0L, mean +0.49 (the 3 consistent losses are gone).

maui-theming (was 3W/0T/1L, +20% not credible):
- All losses were the same complaint: baseline also showed how to swap merged
  dictionaries and hook RequestedThemeChanged. An instruction to "be complete"
  did not stick, so the code now lives inline in the DynamicResource pitfall
  where the model actually reads it.
- Scoped the Android UiMode rule to runtime/system theme switching - it was
  being bolted onto narrow AppThemeBinding questions and judged "ancillary and
  slightly overstated as required".
- Expanded the C# helpers so both SetAppThemeColor and generic SetAppTheme<T>
  are shown; all three overloads compile-verified in a net11.0-maccatalyst app.
- Local n=4: 10W/5T/1L, mean +0.22 [95% CI +0.09, +0.36] - CI now above zero.

All three were measured with the same harness as the official run (vally,
executor claude-opus-4.6, judge gpt-5.5), at n=4 per scenario rather than the
official n=1, since single-trial cells cannot separate signal from noise -
maui-shell-navigation originally "failed" with zero losses purely on CI width.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 58513e0c-4086-4112-9ea1-95dbd8e8e469
Copilot AI review requested due to automatic review settings July 27, 2026 10:13
@kubaflo

kubaflo commented Jul 27, 2026

Copy link
Copy Markdown
Author

Thanks for running this — the results were actionable. The P0 passed: maui-collectionview, the FIX-REGRESSION skill this PR exists for, went 4W/0T/0L (+40%), alongside maui-safe-area (+100%), maui-app-lifecycle (+55%) and maui-data-binding (+40%).

I've fixed the other three in 9c02b413. Only those three files change — the four passing skills are untouched.

Root cause

I downloaded the artifacts and diffed baseline vs skilled per scenario. In every failing scenario the skilled answer was shorter than baseline:

Scenario baseline skilled
shell · Navigate with parameters 2433 chars 1804
theming · Avoid common mistakes 1541 1347
shell · tabs and flyout 2312 2183

The scope-control wording I added to stop maui-collectionview over-applying had over-corrected the other skills into answering too narrowly. Baseline kept winning by including the follow-through code that makes a fix actionable. Judge, verbatim:

"Response A is slightly more helpful because it also shows how to swap merged dictionaries and where to handle RequestedThemeChanged, giving the user a more actionable runtime theming path."

Two factual errors the judge caught

On Shell navigation auto-resolves DI-registered pages it lost 3/4 trials, calling the skill "overconfident/potentially misleading". It was right, and both claims were pre-existing:

  • "Unregistered page silently skips injection — dependencies are silently null, no exception is thrown." False. Routed pages go through ActivatorUtilities.GetServiceOrCreateInstance (Routing.cs:336) which injects registered dependencies and throws when one can't be resolved. ContentTemplate pages go through Activator.CreateInstance (ElementTemplate.cs:33) — no DI at all, and a MissingMethodException, not silent nulls. Rewritten around that real distinction.
  • "must be AddTransient" → softened to "prefer", noting where Singleton is defensible.

Results after the fixes

Same harness as CI (vally, executor claude-opus-4.6, judge gpt-5.5), but n=4 per scenario instead of n=1:

Skill Official CI After fix
maui-dependency-injection 1W/2T/1L · +0.0% ❌ 15W/1T/0L · +0.49
maui-shell-navigation 2W/2T/0L · +35% ❌ 16W/0T/0L · +0.66
maui-theming 3W/0T/1L · +20% ❌ 10W/5T/1L · +0.22 [+0.09, +0.36]

All three now have a mean above 0 with the interval clear of it.

One note on the harness

maui-shell-navigation failed with zero losses (2W/2T/0L) purely on CI width at n=1 per scenario. Single-trial cells can't separate signal from noise — I saw five runs of unchanged baseline code score −0.13, +0.00, −0.07, +0.00, +0.00. Worth considering runs: 2-3 for the PR gate, or treating "no losses but wide CI" differently from a real regression.

Could you re-run /evaluate when convenient? Fork PRs can't trigger it (Actor kubaflo has permission: read).

Also flagged earlier, still outstanding for a follow-up: two rubrics now assert things the corrected skills contradict — maui-safe-area ("WindowSoftInputModeAdjust.Resize replaced by" — it isn't removed or obsolete) and maui-dependency-injection ("behaves like Singleton" — MAUI creates one IServiceScope per window). I deliberately left tests/ alone so this comparison stays valid.

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

Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

plugins/dotnet-maui/skills/maui-shell-navigation/SKILL.md:203

  • This section documents [QueryProperty] as a ViewModel-based option, but the plugin’s reference doc still presents QueryProperty as a page-based approach (skills/maui-shell-navigation/references/shell-navigation-api.md shows it on AnimalDetailsPage). Having the skill and its reference material disagree will confuse users—please align them (either update the reference doc to match this guidance, or adjust this section).
### Option 2: QueryProperty Attribute

Apply on the **ViewModel** class (or the page, if it genuinely owns the state).
Prefer `IQueryAttributable` on the ViewModel — it keeps navigation state with the
`BindingContext` and handles multiple parameters in one call:

Comment on lines +112 to +115
// Generic helper — works for any bindable property type, not just Color
label.SetAppTheme<Color>(Label.TextColorProperty, Colors.Green, Colors.Red);
label.SetAppTheme<double>(Label.FontSizeProperty, 14, 16);
label.SetAppTheme<FileImageSource>(Image.SourceProperty, "logo_light.png", "logo_dark.png");
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