Skip to content

fix: DevFlow IView visibility/bounds resolution for Comet#174

Open
davidortinau wants to merge 3 commits intomainfrom
fix/devflow-comet-resolver
Open

fix: DevFlow IView visibility/bounds resolution for Comet#174
davidortinau wants to merge 3 commits intomainfrom
fix/devflow-comet-resolver

Conversation

@davidortinau
Copy link
Copy Markdown
Contributor

@davidortinau davidortinau commented Apr 28, 2026

Extracts DevFlow-only changes from PR #68 / feature/comet so they can ship independently of the Comet app framework.

Commits

  1. 6f7efa29 — fix: DevFlow IView visibility/bounds resolution

    • CometViewResolver (new) bridges IView → handler-native view via reflection (no compile-time Comet ref)
    • VisualTreeWalker uses it for visibility/bounds when Element lookup yields nothing
  2. 93101e0a — feat(devflow): Yoga layout inspection across agent, driver, and CLI

    • New ?layout=1 query param on /api/v1/tree (and --layout CLI flag, layout MCP param)
    • LayoutInspectorAdapter reflects against Comet.Layout.IYogaLayoutInspector so the agent picks up Yoga snapshots when Comet is loaded — zero hard dependency on Comet
    • Adds LayoutInfo DTOs to both Agent.Core and Driver
    • Cached per-Type LayoutManager PropertyInfo lookup (walks the type chain) for low overhead

Scope notes

  • DevFlow is an independent product in this monorepo; it must not block on Comet shipping
  • Two further DevFlow commits remain on feature/comet (_appBoundApplication migration + Comet view-resolution / IView scroll support). They have non-trivial conflicts with BLE work that landed on main post-branch, so they're deferred to a later DevFlow PR with build verification — they don't block this one
  • Closes the DevFlow concerns of Fix remaining DevFlow support for Comet apps #68

Verification

  • Local: cherry-picks of cae8b05e and 0d033ed6; conflicts resolved manually keeping main's BLE/status/dispatcher work intact
  • Build: relies on CI (Arcade SDK + sandbox network restrictions prevent local build here)

- Add ResolveIViewWindowBounds, ResolveIViewPlatformVisibility,
  PopulateIViewNativeInfo virtual methods to VisualTreeWalker (Core)
  with platform overrides (Agent)
- IView branch now resolves bounds from handler's native view
  (UIView.ConvertRectToView on iOS, GetLocationInWindow on Android,
  TransformToVisual on Windows)
- Visibility checked via native view Hidden/Alpha/size instead of
  IView.Visibility alone
- Text extraction checks ILabel, ITextButton, IEntry, IEditor,
  ISearchBar interfaces
- CometViewResolver.TryExtractText() added for reflection-based
  text fallback

Cherry-picked DevFlow-only hunks from cae8b05 on
fix/devflow-comet-followups; Comet runtime changes (toolbar items,
safe area) move to a separate PR against feature/comet.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 28, 2026 21:31
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

Adds improved DevFlow visual-tree inspection support for Comet (and other IView implementations that don’t derive from VisualElement) by resolving bounds/visibility via the handler’s native platform view, plus a reflection-based Comet text extraction fallback.

Changes:

  • Extend VisualTreeWalker (Core) to compute visibility, window-bounds, and native-info for IView elements via new overridable hooks.
  • Implement platform-specific IView window-bounds/visibility/native-info resolution in the Agent walker using native view APIs.
  • Add CometViewResolver.TryExtractText reflection fallback for Comet views that don’t surface text through standard MAUI interfaces.
Show a summary per file
File Description
src/DevFlow/Microsoft.Maui.DevFlow.Agent/VisualTreeWalker.cs Implements platform-native bounds/visibility/native-info extraction for IView via Handler.PlatformView.
src/DevFlow/Microsoft.Maui.DevFlow.Agent.Core/VisualTreeWalker.cs Adds IView fallthrough flow (visibility/bounds/native info + richer text extraction).
src/DevFlow/Microsoft.Maui.DevFlow.Agent.Core/CometViewResolver.cs Adds reflection-based text extraction fallback (TryExtractText) for Comet views.

Copilot's findings

Comments suppressed due to low confidence (1)

src/DevFlow/Microsoft.Maui.DevFlow.Agent.Core/VisualTreeWalker.cs:1284

  • Fallback visibility check only treats Visibility.Collapsed as not visible. If IView.Visibility can also be Hidden, this would currently report hidden (non-displayed) views as visible. Consider using iView.Visibility == Visibility.Visible (or explicitly excluding both Hidden and Collapsed) when falling back to the MAUI visibility value.
            var platformVisible = ResolveIViewPlatformVisibility(iView);
            info.IsVisible = platformVisible ?? (iView.Visibility != Visibility.Collapsed);
  • Files reviewed: 3/3 changed files
  • Comments generated: 8

Comment on lines +290 to +292
if (uiView.Hidden) return false;
if (uiView.Alpha <= 0) return false;
if (uiView.Bounds.Width <= 0 && uiView.Bounds.Height <= 0) return false;
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The zero-size visibility check uses Width <= 0 && Height <= 0 (iOS and Android paths). This will treat views with one dimension <= 0 as visible. If the intent is to treat any zero dimension as not visible, use || (or align with the > 0 && > 0 checks used elsewhere in this file).

Copilot uses AI. Check for mistakes.

if (result is string envText && !string.IsNullOrEmpty(envText))
return envText;
break;
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

break here stops trying other GetEnvironment overloads even when the current call returns null/empty. Consider continuing the loop unless a non-empty string was found, so additional overloads can be attempted.

Suggested change
break;
continue;

Copilot uses AI. Check for mistakes.
Comment on lines +1281 to +1284
// Check platform-native visibility first (handler's UIView.Hidden/Alpha on iOS, etc.)
// Falls back to IView.Visibility if platform check is unavailable
var platformVisible = ResolveIViewPlatformVisibility(iView);
info.IsVisible = platformVisible ?? (iView.Visibility != Visibility.Collapsed);
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

New IView visibility/window-bounds behavior isn’t covered by existing unit tests. Consider adding a net10.0 test that walks a minimal IVisualTreeElement implementing IView with a test VisualTreeWalker subclass overriding the new virtuals, to verify (1) platform visibility precedence vs IView.Visibility, and (2) bounds/window-bounds handling for IView elements.

Copilot generated this review using guidance from repository custom instructions.
if (winFe.Visibility != Microsoft.UI.Xaml.Visibility.Visible) return false;
if (winFe.Opacity <= 0) return false;
return true;
}
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This #if block handles iOS/Android/Windows but not MACOS, even though the Agent targets net10.0-macos and this file already has AppKit implementations elsewhere. As a result, IView/Comet visibility on macOS will always fall back to the base behavior. Consider adding an AppKit NSView visibility/alpha/size check here.

Suggested change
}
}
#elif MACOS
if (platformView is NSView nsView)
{
if (nsView.Hidden) return false;
if (nsView.AlphaValue <= 0) return false;
if (nsView.Bounds.Width <= 0 && nsView.Bounds.Height <= 0) return false;
return true;
}

Copilot uses AI. Check for mistakes.
info.NativeProperties[kvp.Key] = kvp.Value;
}
}
#endif
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This native-info population for IView doesn’t include a #elif MACOS branch. On macOS, Comet/IView elements will miss native type/property details even though VisualElement native info is supported on macOS elsewhere in this file. Consider adding an AppKit NSView case here for parity.

Copilot uses AI. Check for mistakes.
Height = fe.ActualHeight
};
}
}
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This preprocessor block lacks a #elif MACOS case, so IView/Comet elements won’t get window-absolute bounds on macOS even though ResolveWindowBounds(VisualElement) supports AppKit above. Consider adding an NSView implementation here for parity.

Suggested change
}
}
#elif MACOS
if (platformView is NSView nsView && nsView.Window != null)
{
var windowRect = nsView.ConvertRectToView(nsView.Bounds, null);
return new BoundsInfo
{
X = windowRect.X,
Y = windowRect.Y,
Width = windowRect.Width,
Height = windowRect.Height
};
}

Copilot uses AI. Check for mistakes.
Comment on lines +1282 to +1284
// Falls back to IView.Visibility if platform check is unavailable
var platformVisible = ResolveIViewPlatformVisibility(iView);
info.IsVisible = platformVisible ?? (iView.Visibility != Visibility.Collapsed);
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

The comment says this “falls back to IView.Visibility if platform check is unavailable”, but the implementation will also override a collapsed IView with true when ResolveIViewPlatformVisibility returns true. Consider combining both signals (treat Visibility.Collapsed as not visible regardless of platform result), or adjust the comment to match the intended precedence.

This issue also appears on line 1283 of the same file.

Suggested change
// Falls back to IView.Visibility if platform check is unavailable
var platformVisible = ResolveIViewPlatformVisibility(iView);
info.IsVisible = platformVisible ?? (iView.Visibility != Visibility.Collapsed);
// Combine it with IView.Visibility so collapsed views are always treated as not visible.
var isCollapsed = iView.Visibility == Visibility.Collapsed;
var platformVisible = ResolveIViewPlatformVisibility(iView);
info.IsVisible = !isCollapsed && (platformVisible ?? true);

Copilot uses AI. Check for mistakes.
Comment on lines +314 to +316
// Comet's generated Text control stores text in a "Value" property (from ILabel.Text:Value mapping)
var valueProp = viewType.GetProperty("Value", BindingFlags.Public | BindingFlags.Instance);
if (valueProp != null && valueProp.PropertyType == typeof(string))
Copy link

Copilot AI Apr 28, 2026

Choose a reason for hiding this comment

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

This method does multiple per-call reflection lookups (e.g., GetProperty("Value") / GetProperty("Text")). Since it may run across many elements during a tree walk, consider caching reflection metadata per Comet view type to reduce overhead.

Copilot uses AI. Check for mistakes.
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.

Expert Code Review — IView Visibility/Bounds Resolution for Comet

Methodology: 3 independent reviewers with adversarial consensus. Findings included only when ≥2/3 reviewers agreed (disputed findings verified via targeted follow-up).

CI Status

Builds are in progress (macOS + Windows matrix). CLA check passed. No test failures observed yet.

Test Coverage Assessment

No new tests added for the 3 new virtual methods or TryExtractText. The ResolveIViewWindowBounds, ResolveIViewPlatformVisibility, and PopulateIViewNativeInfo overrides require platform-specific testing (devices/simulators), which is noted as out of scope per repo conventions. The TryExtractText reflection logic in CometViewResolver could benefit from unit tests with mock objects.


Findings (ranked by severity)

# Severity Consensus File Finding
1 🟡 MODERATE 3/3 Agent/VisualTreeWalker.cs Missing #elif MACOS in all 3 new IView overrides — macOS Comet views lose bounds, visibility, and native properties
2 🟡 MODERATE 3/3 (after follow-up) Agent.Core/VisualTreeWalker.cs:1284 Visibility.Hidden incorrectly reported as visible — fallback uses != Collapsed instead of == Visible
3 🟡 MODERATE 3/3 (after follow-up) Agent/VisualTreeWalker.cs:360-373 Windows PopulateIViewNativeInfo extracts only 1 of 10 native properties — automationId, isPassword, etc. silently omitted
4 🟡 MODERATE 2/3 Agent.Core/CometViewResolver.cs:398 Premature break in GetEnvironment loop skips valid overloads when first match has unknown param count
5 🟡 MODERATE 2/3 Agent/VisualTreeWalker.cs:291,299 Zero-size bounds used as visibility proxy — causes false negatives during layout transitions on iOS/Android
6 🟢 MINOR 3/3 (after follow-up) Agent.Core/CometViewResolver.cs:379-381 Uncached reflection + LINQ allocation per TryExtractText call (rest of class caches reflection metadata)
7 🟢 MINOR 2/3 Agent.Core/CometViewResolver.cs:377 TryExtractText is public static but doesn't guard IsCometAvailable() — fragile for future callers

Discarded Findings (single-reviewer only, no consensus)

  • Near-identical code duplication between VisualElement and IView platform methods (1/3)
  • Generic Binding<T> properties unwrapped via .ToString() without verifying T == string (1/3)

Generated by Expert Code Review (auto) for issue #174 · ● 8.9M

Comment on lines +379 to +381
var getEnvMethods = _cometViewType.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Where(m => m.Name == "GetEnvironment" && m.IsGenericMethod && m.GetParameters().Length >= 1)
.ToList();
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.

🟢 MINOR · 3/3 reviewers (after follow-up) · Uncached reflection + LINQ allocation per call

Every call to TryExtractText for a Comet view executes GetMethods() + .Where().ToList(). The rest of CometViewResolver caches reflection metadata in static fields (_cometViewType, _getViewMethod, _builtViewProperty, etc.) initialized once in IsCometAvailable(). During a full tree walk with many Comet views, this creates unnecessary GC pressure.

Suggestion: Cache the GetEnvironment method lookup in a static field (e.g., private static MethodInfo[]? _getEnvironmentMethods;) initialized alongside the other cached members.

Comment on lines +360 to +361
}
#elif WINDOWS
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.

🟡 MODERATE · 3/3 reviewers (after follow-up) · Windows PopulateIViewNativeInfo omits most native properties

The existing PopulateNativeInfo for Windows (line ~81) extracts 10 properties: automationId, automationName, helpText, name, visibility, isHitTestVisible, isEnabled, isTabStop, isReadOnly, isPassword. This new method only extracts automationName.

The iOS and Android blocks in PopulateIViewNativeInfo closely mirror their PopulateNativeInfo counterparts, but the Windows block was left sparse. Comet IView elements on Windows will silently lose diagnostically important data like automationId (critical for test automation targeting), isPassword, and isReadOnly.

Suggestion: Extract the same set of Windows properties that PopulateNativeInfo does, or factor the Windows property extraction into a shared helper that both methods call.

Comment on lines +231 to +273

#if IOS || MACCATALYST
if (platformView is UIKit.UIView uiView && uiView.Window != null)
{
var windowRect = uiView.ConvertRectToView(uiView.Bounds, uiView.Window.RootViewController?.View ?? uiView.Window);
return new BoundsInfo
{
X = windowRect.X,
Y = windowRect.Y,
Width = windowRect.Width,
Height = windowRect.Height
};
}
#elif ANDROID
if (platformView is global::Android.Views.View androidView)
{
var location = new int[2];
androidView.GetLocationInWindow(location);
var density = androidView.Context?.Resources?.DisplayMetrics?.Density ?? 1f;
return new BoundsInfo
{
X = location[0] / density,
Y = location[1] / density,
Width = androidView.Width / density,
Height = androidView.Height / density
};
}
#elif WINDOWS
if (platformView is Microsoft.UI.Xaml.UIElement uiElement)
{
var transform = uiElement.TransformToVisual(null);
var point = transform.TransformPoint(new global::Windows.Foundation.Point(0, 0));
if (uiElement is Microsoft.UI.Xaml.FrameworkElement fe)
{
return new BoundsInfo
{
X = point.X,
Y = point.Y,
Width = fe.ActualWidth,
Height = fe.ActualHeight
};
}
}
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.

🟡 MODERATE · 3/3 reviewers · Missing #elif MACOS branch in all three new IView overrides

ResolveIViewWindowBounds, ResolveIViewPlatformVisibility, and PopulateIViewNativeInfo handle iOS/Catalyst, Android, and Windows — but none include a #elif MACOS branch. The existing ResolveWindowBounds(VisualElement) (line ~205) and PopulateNativeInfo (line ~55) both have macOS/AppKit handling with NSView coordinate flipping and accessibility extraction.

On macOS, Comet IView elements will get null WindowBounds, fall back to the Visibility.Collapsed-only check (missing NSView.Hidden/AlphaValue), and emit no native properties.

Suggestion: Add #elif MACOS branches mirroring the existing NSView logic, e.g.:

#elif MACOS
if (platformView is AppKit.NSView nsView && nsView.Window?.ContentView != null)
{
    var windowRect = nsView.ConvertRectToView(nsView.Bounds, nsView.Window.ContentView);
    var contentHeight = nsView.Window.ContentView.Bounds.Height;
    return new BoundsInfo
    {
        X = windowRect.X,
        Y = contentHeight - windowRect.Y - windowRect.Height, // flip Y axis
        Width = windowRect.Width,
        Height = windowRect.Height
    };
}

Comment on lines +289 to +291
{
if (uiView.Hidden) return false;
if (uiView.Alpha <= 0) return false;
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.

🟡 MODERATE · 2/3 reviewers · Zero-size bounds used as visibility proxy causes false negatives

On iOS, uiView.Bounds gives the view's own coordinate space — a correctly laid-out view can report zero Bounds before layoutSubviews completes. On Android (line 299), Width/Height are 0 until onMeasure/onLayout runs. A freshly-added IView will be transiently reported as invisible even though it's logically visible. Windows (line 305) doesn't have this check, creating cross-platform inconsistency.

The Hidden/Alpha checks are reliable visibility signals; the zero-size check adds false negatives during layout transitions.

Suggestion: Remove the zero-size checks from this method — restrict to actual visibility flags (Hidden, Alpha, Visibility). Geometry checks belong in bounds/hit-test logic, not visibility determination.

Comment on lines +391 to +398
if (paramCount == 1)
result = genericMethod.Invoke(cometView, new object[] { "Text.Value" });
else if (paramCount == 2)
result = genericMethod.Invoke(cometView, new object[] { "Text.Value", false });

if (result is string envText && !string.IsNullOrEmpty(envText))
return envText;
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.

🟡 MODERATE · 2/3 reviewers · Premature break skips valid GetEnvironment overloads

If Comet adds a 3+ parameter GetEnvironment overload that sorts first in the reflection list, MakeGenericMethod succeeds but paramCount matches neither == 1 nor == 2, leaving result as null. The break then exits the loop — the 1- or 2-parameter overload that would have returned text is never tried.

Suggestion: Add an else continue for unrecognized parameter counts:

if (paramCount == 1)
    result = genericMethod.Invoke(cometView, new object[] { "Text.Value" });
else if (paramCount == 2)
    result = genericMethod.Invoke(cometView, new object[] { "Text.Value", false });
else
    continue; // unknown overload shape; try the next one

if (result is string envText && !string.IsNullOrEmpty(envText))
    return envText;
break; // invocation succeeded, no need to try others

}

// Try GetEnvironment<string>("Text.Value") — Comet stores text in environment
if (_cometViewType != null && _cometViewType.IsInstanceOfType(cometView))
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.

🟢 MINOR · 2/3 reviewers · TryExtractText doesn't guard IsCometAvailable()

This method is public static and uses _cometViewType (set by IsCometAvailable()). The current call site is safe (guarded by cometResolved != null), but any future caller that skips TryResolveCometView will silently skip the environment-based text path since _cometViewType will be null.

Suggestion: Add if (!IsCometAvailable()) return null; at the top, matching the defensive pattern used in TryResolveCometView (line ~124) and GetEnvironmentKeys (line ~420).

// Check platform-native visibility first (handler's UIView.Hidden/Alpha on iOS, etc.)
// Falls back to IView.Visibility if platform check is unavailable
var platformVisible = ResolveIViewPlatformVisibility(iView);
info.IsVisible = platformVisible ?? (iView.Visibility != Visibility.Collapsed);
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.

🟡 MODERATE · 3/3 reviewers (after follow-up) · Visibility.Hidden incorrectly reported as visible

The fallback iView.Visibility != Visibility.Collapsed evaluates to true for Visibility.Hidden, but Hidden means the view is not rendered (only occupies layout space). The VisualElement path (line ~1256) uses ve.IsVisible, which returns false for both Hidden and Collapsed.

When platform visibility returns null (no handler, macOS, GTK), any Comet view with Visibility.Hidden will be erroneously reported as visible — inconsistent with the VisualElement path.

Suggestion:

info.IsVisible = platformVisible ?? (iView.Visibility == Visibility.Visible);

Surfaces computed Yoga layout data through the DevFlow tree inspection
pipeline so agents can reason about flex/stack layout behaviour.

- Agent.Core/LayoutInspectorAdapter.cs: implements
  IYogaLayoutInspector from Comet and captures per-view Yoga nodes as
  the visual tree is walked.
- Agent.Core/ElementInfo.cs, Driver/ElementInfo.cs: shared DTO
  carrying layout metrics (computed bounds, margins/padding, flex
  direction, justify/align, grow/shrink/basis) across the wire.
- Agent.Core/VisualTreeWalker.cs: populate the new ElementInfo layout
  fields while walking, using the adapter when available.
- Agent.Core/DevFlowAgentService.cs: register the inspector adapter
  during agent startup.
- Driver/AgentClient.cs, AppDriverBase.cs: expose the layout fields
  on returned ElementInfo.
- Cli/DevFlow/DevFlowCommands.cs, Mcp/Tools/TreeTool.cs: render the
  layout fields in tree output so MCP agents can see them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
(cherry picked from commit 0d033ed)
Visibility precedence (Agent.Core/VisualTreeWalker.cs):
- IView path: Visibility.Collapsed always wins (matches the VisualElement
  path which uses ve.IsVisible == false for both Hidden and Collapsed).
  Fallback when platform check is unavailable now treats Visibility.Hidden
  as not visible (was previously reported as visible).

Platform IView overrides (Agent/VisualTreeWalker.cs):
- Drop the zero-size proxy from ResolveIViewPlatformVisibility on iOS and
  Android. uiView.Bounds and androidView.Width/Height can be zero before
  layoutSubviews/onLayout completes, causing transient false negatives;
  Hidden/Alpha/Visibility flags are the reliable visibility signals.
- Add #elif MACOS branches to ResolveIViewWindowBounds (NSView with
  bottom-left → top-left flip), ResolveIViewPlatformVisibility (NSView
  Hidden/AlphaValue), and PopulateIViewNativeInfo (full NSView native
  property parity with PopulateNativeInfo).
- Expand Windows PopulateIViewNativeInfo to match PopulateNativeInfo:
  automationId, helpText, name, visibility, isHitTestVisible, isEnabled,
  isTabStop, isReadOnly, isPassword (was: only automationName).

CometViewResolver:
- Cache GetEnvironment generic-method overloads in a static field
  populated by IsCometAvailable, eliminating the GetMethods()+Where().ToList()
  allocation on every TryExtractText call during a tree walk.
- Add IsCometAvailable() guard to TryExtractText so a future caller that
  bypasses TryResolveCometView still goes through normal initialization.
- Replace premature 'break' for unrecognized GetEnvironment overload counts
  with 'continue' so additional overloads are still attempted.

Driver interface alignment:
- IAppDriver.GetTreeAsync gains 'bool includeLayout = false' to match
  AppDriverBase impl introduced by the Yoga layout commit. Without this
  the Driver project fails to build (CS0535).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
davidortinau added a commit that referenced this pull request Apr 28, 2026
The merge 45fb43c ('Merge branch main into feature/comet') silently
favored feature/comet for files where main had net-new content. This
commit takes main's version for all DevFlow + Cli + workflow + docs
files outside src/Comet/ and src/Go/ so that:

- BLE tools (Mcp/Tools/BleTools.cs) compile against AgentClient
- Skills system (Skills/DevFlowSkillCommands.cs) compiles against
  OutputWriter
- DevFlow specs, plugin manifest, READMEs, and CI workflows match main
- DevFlowCommands.cs no longer carries the competing 'update-skill' /
  'skill-version' impl that conflicts with the bundled Skills system

The DevFlow Comet support that was on feature/comet (CometViewResolver
enhancements, IApplication binding, layout inspector, IView visibility
overrides) is preserved in the open DevFlow PRs targeting main:

- PR #174 fix/devflow-comet-resolver
- PR #177 fix/devflow-comet-iapplication

When those merge, this branch's diff vs main shrinks accordingly.

LayoutInspectorAdapter.cs is removed because it depends on LayoutInfo
types that live on the PR #174 branch but not on main yet — it will be
restored on main via PR #174.

global.json (allowPrerelease=true, rollForward=latestMajor) and
eng/Versions.props (MAUI 11.0 preview, Extensions 11.0 preview) are
kept from feature/comet because Comet/Go projects target net11.0 and
require those package versions.

Cross-cutting infra:
- .gitignore: kept (additive)
- Directory.Packages.props: kept (adds Go packages)
- MauiLabs.slnx: kept (adds Comet/Go projects)
- NuGet.config: reverted (repo policy: no direct nuget.org)
- global.json: kept (Comet/Go need net11)
- eng/Versions.props: kept (Comet/Go need preview packages)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jfversluis added a commit that referenced this pull request May 1, 2026
* Add Comet MVU framework

Comet is a Model-View-Update (MVU) framework built on .NET MAUI.
Views are C# functions with reactive state — no XAML required.

Includes:
- Core framework (src/Comet, Comet.SourceGenerator)
- 10 sample apps demonstrating various patterns
- xUnit test suite
- Project templates
- Documentation

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Integrate Comet into maui-labs build system

- Add Directory.Build.props for Comet (builds independently, no Arcade yet)
- Add Directory.Packages.props to opt out of central package management
- Add Comet projects to MauiLabs.slnx
- Promote copilot-instructions.md and squad agent to repo root .github/
- Copy AGENTS.md to repo root for Copilot discovery
- Remove nested .github/workflows (won't fire from src/Comet/)

Build verified: SourceGenerator, Comet.csproj, and tests all pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Keep Comet AI config within src/Comet/

Revert promotion of copilot-instructions, squad agent, and AGENTS.md
to repo root. Each project in this monorepo has different requirements,
so AI context should stay scoped to each project directory.

Restored:
- src/Comet/.github/copilot-instructions.md
- src/Comet/.github/agents/squad.agent.md
- src/Comet/.github/workflows/ (all workflows)
- src/Comet/AGENTS.md (was already there, removed root copy)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Consolidate AI instructions into AGENTS.md

Merge Squad instructions from copilot-instructions.md into AGENTS.md
and remove the redundant file. AGENTS.md is discovered from cwd by
Copilot CLI, making it the right place for per-project AI context
in a monorepo.

Also fixed stale SDK version references (net10 -> net11).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: DevFlow IView visibility/bounds, safe area edge-to-edge, toolbar items on pushed views

FIX 1 — DevFlow VisualTreeWalker IView branch:
- Add ResolveIViewWindowBounds, ResolveIViewPlatformVisibility, PopulateIViewNativeInfo
  virtual methods to VisualTreeWalker (Core) with platform overrides (Agent)
- IView branch now resolves bounds from handler's native view (UIView.ConvertRectToView
  on iOS, GetLocationInWindow on Android, TransformToVisual on Windows)
- Visibility checked via native view Hidden/Alpha/size instead of IView.Visibility alone
- Text extraction checks ILabel, ITextButton, IEntry, IEditor, ISearchBar interfaces
- CometViewResolver.TryExtractText() added for reflection-based text fallback

FIX 2 — CometViewController safe area:
- LoadView() checks ISafeAreaView.IgnoreSafeArea before setting EdgesForExtendedLayout
- ViewWillAppear re-checks safe area and propagates background color to container view
- Eliminates white/black letterboxing when views use .IgnoreSafeArea()

FIX 3 — Toolbar items on pushed views:
- Add View.ToolbarItems() and View.GetToolbarItems() environment-based extensions
- Add EnvironmentKeys.View.ToolbarItems constant
- Extract toolbar creation into reusable ApplyToolbarItems() in NavigationViewHandler
- Pushed views' own toolbar items take priority over NavigationView's items

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: DevFlow _app binding for Comet/IApplication hosts

CometApp implements IApplication but not Microsoft.Maui.Controls.Application,
so Application.Current is never set and DevFlow's retry loop always fails.
This left _app=null and ALL DevFlow endpoints returned 'Agent not bound to app'.

Changes:
- Add _iApp field + BoundApplication property (prefers Application, falls back to IApplication)
- Add StartServerOnly() with TryResolveIApplicationFromDI() using IPlatformApplication.Current
- Add BindIApp() for late-binding IApplication instances
- Replace all _app references with BoundApplication in endpoint handlers
- Add IApplication overloads for WalkTree, GetElementById, HitTestByBounds, Query, QueryCss
- Fix HitTestByBounds to safely cast IWindow→Window for Page/Navigation access
- AgentServiceExtensions: fall back to StartServerOnly() when Application.Current stays null
- Add TryBubbleCometGestureTap for walking parent chain to find tap gestures
- Add case IView iViewNoHandler in HandleTap for views without platform handlers

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: update holden history + decisions for FIX 4 (_app binding)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat: expand Comet BaristaNotes and tooling

Refresh the BaristaNotes sample with new styling, AI and voice services, project-level Squad/Copilot setup, Comet platform fixes, and improved DevFlow broker diagnostics.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* rename Clancey.Comet packages to Microsoft.Maui.Comet

Update NuGet package IDs, metadata, CI feed references, docs, and
template project references. Assembly name stays Comet.dll — no
source code or namespace changes needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: iOS edge-to-edge layout, translucent nav bar, and safe area handling

- CometViewController: use ConfigureWithDefaultBackground (glass/blur)
  for StandardAppearance and transparent for ScrollEdgeAppearance;
  propagate background color to window and container for safe area
  regions; apply toolbar items from Comet view tree
- ScrollViewHandler: set ContentInsetAdjustmentBehavior to Automatic
  so content starts below the nav bar; mark scroll content with
  IgnoreSafeArea to prevent double inset application
- CollectionViewHandler: override MAUI's forced Never inset behavior
  back to Automatic after embedding the UICollectionView
- CometView: propagate content background to container view
- NavigationViewHandler: clean up redundant nav bar configuration
- ThemeManager: add theme change notification support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: BaristaNotes sample — theme system, DI, global usings, code cleanup

- Expand GlobalUsings.cs to reduce repetitive imports across pages
- Convert ShotRecordCard and RatingDisplay to [Body] view pattern
- Consolidate CoffeeColors to resolve from ThemeManager for dark mode
- Wire up ThemeService and CoffeeControlStyles to dynamic theme tokens
- Simplify page code with VStack constructor and DI resolution
- Add CollectionView usage on management and activity pages
- Add toolbar items to management pages for navigation
- Clean up verbose List<View> + foreach patterns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: DevFlow — improve Comet view resolution and IView scroll support

- CometViewResolver: add safe property resolution for generic handler
  types to avoid AmbiguousMatchException
- DevFlowAgentService: add IView/IScrollView scroll path for Comet
  views that don't inherit from VisualElement; walk visual tree for
  Comet ScrollView discovery via FindDescendantIScrollView

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: allow preview SDK for net11.0 target frameworks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: MAUI Go — companion app, dev server, CLI integration

Implements the core MAUI Go prototype:

Dev Server (src/Go/Server/):
- FileSystemWatcher on .cs files with 300ms debounce
- Roslyn incremental compiler (EmitDifference for EnC deltas)
- Reference resolution from Comet.Tests output + .NET SDK ref packs
- WebSocket server for pushing deltas to companion apps
- QR code generation for device pairing

Companion App (src/Go/CompanionApp/):
- Comet-based MAUI app targeting Android/iOS/MacCatalyst
- WebSocket client that receives delta payloads
- MetadataUpdater.ApplyUpdate() integration for hot reload
- Assembly loading via AssemblyLoadContext
- Connect screen with server URL input

Shared Protocol (src/Go/Shared/):
- Binary wire protocol (header + payload) over WebSocket
- Message types: Hello, Welcome, Delta, InitialAssembly, etc.
- DeltaPayload record with metadata, IL, PDB bytes

CLI Integration:
- 'maui go create' scaffolds Comet project with ProjectReference
- 'maui go serve' launches dev server from project directory
- 'maui go upgrade' stub for future MAUI project graduation

Verified: dev server compiles initial assembly, detects file changes,
produces EnC deltas. Companion app launches on Mac Catalyst.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Go): E2E hot reload working — MetadataUpdater.ApplyUpdate succeeds on Mono/Mac Catalyst

Key breakthroughs:
- Fixed EmitBaseline creation: read EnC debug info (local slot maps, lambda/closure maps)
  from PDB instead of returning default. This fixes string heap token mismatches that
  caused SIGABRT in Mono's hot_reload_apply_changes.
- Fixed view re-render: re-instantiate user view after delta instead of calling
  MauiHotReloadHelper.TriggerReload() which destroys the GoMainPage and its
  WebSocket client.
- Added auto-connect via MAUI_GO_SERVER environment variable for testing.
- Set DOTNET_MODIFIABLE_ASSEMBLIES=Debug in Info.plist (LSEnvironment) so Mono
  links the hot_reload component even when launched via 'open'.

Verified: 3 consecutive deltas applied successfully on Mac Catalyst:
  Delta #1: Text change → ✅ Applied in ~2ms
  Delta #2: Color change → ✅ Applied
  Delta #3: Font size change → ✅ Applied
  App stayed connected through all deltas.

Pipeline: edit .cs → FileWatcher → Roslyn EmitDifference → WebSocket →
          MetadataUpdater.ApplyUpdate → new View instance → UI updates

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor(Go): Remove Mono workarounds and debug logging

- Remove TryMonoInternalApplyUpdate (net11.0 uses CoreCLR, not Mono)
- Remove TriggerCometReload from GoClient (handled by GoMainPage)
- Remove deep MetadataUpdater diagnostics from MacCatalyst Program.cs
- Clean up verbose Console.WriteLines, keep only key status messages
- Remove unused HotReload import from GoMainPage

Smoke tested: delta #1 applied successfully after cleanup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Go): Add compilation error overlay in companion app

- Show error banner over user view when compilation errors or
  restart-required messages are received from server
- Dismiss button to clear errors manually
- Errors auto-clear when next successful delta applies
- Server now distinguishes 'no changes' from 'restart required'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Go): Auto-reconnect with exponential backoff

GoClient now auto-reconnects when the WebSocket connection drops:
- Exponential backoff: 1s, 2s, 4s, 8s, 15s
- Creates fresh ClientWebSocket for each attempt
- Keeps user view visible during reconnection
- ReconnectAsync() for manual retry
- Fires Disconnected only after all retries exhausted

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore(Go): Remove UseInterpreter/MtouchInterpreter (CoreCLR on net11)

net11 uses CoreCLR on all platforms including iOS/MacCatalyst.
Mono interpreter flags are unnecessary. Verified E2E hot reload
still works: 3 deltas + error display + reconnection all passed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Go): Android support — smart default URL, simplified error banner

- Default URL auto-detects platform: 10.0.2.2 for Android emulator,
  localhost for other platforms
- Simplified error banner to avoid StackOverflow on Android
- Fixed missing System using in Android MainApplication

Android connects and loads assembly successfully. MetadataUpdater
crashes in Mono's hot_reload component (SIGSEGV in
mono_image_load_enc_delta) — Android still uses Mono runtime, not
CoreCLR. Hot reload works on Mac Catalyst (CoreCLR) but blocked
on Android until CoreCLR is available or Mono delta compat is fixed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Go): Enable CoreCLR on Android via UseMonoRuntime=false

Switches Android from Mono to CoreCLR runtime, which is required for
MetadataUpdater.ApplyUpdate() to work. On emulator with FastDeploy,
CoreCLR hits FileNotFoundException for Microsoft.Maui assembly —
likely a FastDeploy + CoreCLR compat issue in preview SDK. Physical
device with Release build (EmbedAssembliesIntoApk) may work better.

See: https://learn.microsoft.com/dotnet/maui/whats-new/dotnet-10#experimental-coreclr

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Go): Apply Comet branding — icon, splash, and UI theme

- App icon: Comet composed icon (appicon.svg + appiconfg.svg foreground)
- Splash screen: Comet splash.svg with coffee-tone background (#D2BCA5)
- Connect screen: warm brown theme matching Comet brand
- Status bar overlay: Comet brown accent
- Renamed to 'Comet Go' in UI

Assets sourced from CometBaristaNotes sample app.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore(Go): Remove all emojis from source code

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore(Go): Remove unused beans.png assets from icon/splash

Only appicon.svg, appiconfg.svg, and splash.svg are referenced by
the MauiIcon/MauiSplashScreen items. The beans.png files were copied
from CometBaristaNotes but are not used.

Note: Android may show the default icon if installed over a previous
build. A clean uninstall + reinstall is needed to pick up the new icon.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* refactor(Go): Rename to Comet Go, disable CoreCLR on Android

- Renamed all 'MAUI Go' references to 'Comet Go' throughout
- Updated ApplicationTitle to 'Comet Go'
- Disabled UseMonoRuntime=false (CoreCLR) on Android:
  CoreCLR assembly loading hits FileNotFoundException for
  Microsoft.Maui in all configurations (FastDeploy, embedded,
  no assembly store). Likely a dotnet/android experimental
  CoreCLR limitation.
- Also discovered: Preview 3 SDK breaks Comet's ThemeColors
  (MissingMethodException on Color.op_Equality) -- Comet
  needs updating for the new Color API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Comet): Replace Color operator calls with pattern matching for Preview 3

Preview 3 removed Color.op_Equality/op_Inequality operators.
Replaced all == null / != null with is null / is not null across
the entire Comet codebase to avoid calling removed operators.
Also fixed default URL to use localhost (works with adb reverse
on physical devices and directly on simulators).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Go): Enable CoreCLR on Android with .NET 11 Preview 3

Root cause of FileNotFoundException was MAUI version mismatch:
eng/Versions.props pinned MAUI to 10.0.41 but net11.0-android
needs MAUI 11.0.0-preview.3. Updated all central package versions
to Preview 3.

- CoreCLR enabled via UseMonoRuntime=false
- Tested on Pixel 5 (API 34) -- app launches and runs
- Standard MAUI template also verified working with CoreCLR

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Go): Fix text input contrast, app icon, add delta logging

- Text field: larger font (18), dark brown background for contrast
  on light-mode iOS
- App icon: added ForegroundTintColor=#FFCB05 (yellow) since
  Resizetizer strips SVG gradients
- Delta handler: added detailed logging before/after ApplyUpdate
  to diagnose iOS device crash on delta

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Go): Fix blank iOS app icon - add XSAppIconAssets to Info.plist

Root cause: iOS Info.plist was missing XSAppIconAssets key, so actool
never compiled the icon set into Assets.car. Also simplified icon to
a single combined SVG (no foreground composition).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Go): Show QR code by default when starting dev server

QR code was already implemented but hidden behind --qr flag.
Now shows by default; use --no-qr to suppress.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Go): Add QR code scanner and redesigned connect screen

- Added ZXing.Net.Maui.Controls for camera-based QR scanning
- New QrScannerPage with viewfinder overlay and corner accents
- Redesigned connect screen: card-style form, 'or' divider, Scan QR button
- Camera permissions for iOS, MacCatalyst, and Android
- Scanned URL auto-populates server URL field

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Go): Redesign connect screen to match PolyPilot layout

- Added Comet logo image at top of connect screen
- Scan QR Code is now the PRIMARY action (large, accent colored)
- 'or enter manually' divider before URL field
- Connect button is secondary (outlined style)
- Added diagnostics/error handling for QR scan button
- Darker background, cleaner spacing

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Go): Fix QR scanner, use splash logo, polish UI

- Fixed QR scanner: CometApp doesn't use MAUI Navigation, so use
  native iOS UIViewController presentation via ModalPresenter
- Logo: use splash SVG (COMET wordmark with gradient), displayed larger
- Input field: same height as buttons (56px), with rounded border
- Connect button: outlined with border
- Divider: proper horizontal lines beside 'or enter manually'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Go): Polish all screens — match splash colors, fix QR dismiss

Connect screen:
- Background matches splash (#D2BCA5 warm beige)
- Logo: use resizetized name (comet_logo, not .svg)
- Input field and Connect button: yellow/gold outline borders
- Divider lines visible on beige background

QR Scanner:
- X dismiss: use native DismissViewController (MAUI Navigation
  doesn't work with CometApp's native modal presentation)
- X button moved higher (padding 60 from top)
- Instruction text moved below viewfinder

Splash screen:
- Reduced BaseSize from 432x145 to 300x100 for better margins

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Go): Improve contrast — darker button/border/divider colors

- Scan QR button: darker brown (#8B5A2B) instead of yellow/mustard
- Input field + Connect button borders: visible brown (#784028)
- Connect label: darker brown for readability
- Divider lines: darker brown, visible on beige background

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Go): Disable NuGetAudit to avoid 10min restore timeouts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: Add Comet Go project context for session continuity

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Comet): Match [Body] attribute by name for cross-assembly compat

When dynamically-loaded assemblies reference a different Comet assembly
(NuGet) than the companion app (project reference), type-based attribute
matching fails. This adds name-based matching as the primary strategy
with a fallback to the original type-based approach.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore(Comet): Remove legacy build artifacts and conflicting docs

Address PR #62 review feedback by removing:

- Legacy Xamarin-era build pipelines (package-nuget.yml, package-github.yml)
- Outdated build tooling (MauiVersionUpdater, DotNet provisioning, install-vs.ps1)
- Stale solution files referencing removed external/Maui submodule
- Legacy nuspecs with hardcoded net9/SkiaSharp 1.x dependencies
- Old GitHub Actions workflows targeting .NET 9.0.x
- Internal audit docs with contradictory readiness claims and encoding issues

Also updates:
- README disclaimer to clarify experimental/pre-release status
- docs/index.md to remove broken links to deleted internal docs

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Comet): Simplify template to minimal counter example

Replace the 197-line Component<TState> template with a clean 16-line
View + Reactive<T> counter that demonstrates the core Comet pattern:
read .Value in a lambda, write .Value anywhere, UI updates automatically.

- Remove Helpers/Reload.cs (was a no-op shim)
- Remove EnableHotReload() call from App.cs (handled by MetadataUpdateHandler)
- Clean up GlobalUsings to only what's needed
- Add static import of CometControls for factory-style API

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Comet): Use $(MauiVersion) for Controls package in template

Remove hardcoded MAUI version from template csproj and the mauiVersion
template parameter. The project inherits MauiVersion from
Directory.Build.props like all other projects in the repo.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(Comet): Add layout shorthand extensions (Center, Top, Bottom, etc.)

Add convenience extension methods on View for common alignment patterns:
.Center(), .Top(), .Bottom(), .Leading(), .Trailing()

These mirror the ergonomics of MauiReactor's layout helpers and make
simple layout expressions more readable in templates and samples.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Comet): Replace legacy VS Code debug config in template

The old launch.json used a 'comet' debug adapter type and 'comet: Build'
task from a defunct VS Code extension. Replace with standard .NET MAUI
debugging config and add a tasks.json with a proper dotnet build task.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(Comet): Update template to .Alignment() and fix SupportedOSPlatformVersion

- Use .Alignment(Alignment.Center) instead of .Center() in MainPage
- Bump SupportedOSPlatformVersion to iOS/Catalyst 18.0, Android 24.0
  to match .NET 11 Preview 3 SDK minimums

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add Copilot instructions to Comet template

Ships .github/copilot-instructions.md with every new Comet project so
AI coding assistants auto-discover Comet's declarative C# patterns,
Reactive<T>/Signal<T> state management, theming system (Theme, ColorTokens,
ThemeExtensions), layout helpers, and important usage rules.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1: Theme as record (spec §5.2) + fix per-view state leak

- Rewrite Theme.cs as immutable record: required Name/Colors/Typography/
  Spacing/Shapes, ImmutableDictionary-backed per-control style defaults,
  strongly-typed SetControlStyle<TControl,TConfig>. Removes static Current,
  Apply(), ThemeChanged event, AppTheme enum, legacy color properties, and
  ColorScheme. No backward compatibility shim.
- ThemeManager owns active theme state (_defaultTheme fallback, environment
  propagation, MarkViewDirty on swap). Drops SyncMauiAppTheme; system theme
  follow is now app-level (spec §6.5).
- ThemeDefaults: Defaults.Light/Dark as standalone Theme records.
- Delete ThemeExtensions.cs; remove ThemeColor/ThemeTextColor/ApplyTheme/
  ApplyControlStyle from Helpers/ViewExtensions.cs.
- CometApp.ThemeChanged: no-op (was setting Theme.Current to light/dark).
- ControlStyleExtensions: use new GetControlStyle<TControl,TConfig>.
- Fix per-view state leak in AppHostBuilderExtensions: renamed
  ApplyModifierAsTypeScopedDefaults -> ApplyModifierAsInstanceDefaults.
  Style-resolved values (IsPressed/IsHovered colors) now write to the
  target view's cascading Context (per-instance, cascades:true) instead of
  the global type-scoped environment. Explicit fluent setters still win
  via LocalContext (spec §4.8, §10.3).
- Fork Defaults.Light at startup (`Defaults.Light with { }`) so framework
  SetControlStyle of ButtonStyles.Filled doesn't mutate the shared singleton.

Handoff note: src/Comet/.squad/decisions/inbox/holden-phase1-theme-record.md.
Build blocker: ControlStyle.cs references removed IControlStyleApplicable
interface — that file is on Amos's delete list.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1: delete legacy style/theme types + singleton BuiltInStyles

Deletes all legacy style infrastructure per spec §1.2 ("one way to do each thing")
with no backward-compat shims per David's directive. Rewrites BuiltInStyles with
the singleton-per-state pattern from spec §3.6.

Framework deletions (~1,400 LOC):
- Styles/Style.cs, ControlStyle.cs, ButtonStyle.cs, NavbarStyle.cs,
  SliderStyle.cs, ProgressBarStyle.cs, TextStyle.cs, ViewStyle.cs
- Styles/DefaultThemeStyles.cs, ResourceDictionary.cs, AppThemeBinding.cs
- Styles/StyleAwareValue.cs, StyleType.cs, IThemeable.cs, ThemeColors.cs
- Styles/VisualStateManager.cs, Interactivity/VisualStateManager.cs
- Styles/Material/* (MaterialStyle, Extensions, ColorPalette)

Test deletions (~2,676 LOC): ThemeTests/, Styles/{Theme,ControlStyle}Tests.cs,
StylingTests.cs, ThemeTests.cs — all tested deleted APIs.

Call-site migrations:
- AppHostBuilderExtensions: removed legacy style.Apply(); fixed pre-existing
  CS0157 (return-in-finally) in ApplyModifierAsInstanceDefaults.
- AbstractLayout.GetDefaultPadding: hardcoded Thickness(6).
- View.cs: removed Resources property + VSM.ClearVisualStateGroups call.
- ViewExtensions: removed Static/DynamicResource, WithVisualStateGroups, GoToState.
- StyleExtensions: removed ApplyStyle/StyleApply; kept StyleAsH1..StyleAsOverline.
- Trigger, MauiCompatibility, AdaptiveTrigger: removed Setter lists.
- CometViewSourceGenerator: removed StyleBuilder.g.cs emission.

BuiltInStyles.cs rewritten: 4 styles × 4 state singletons (Default/Pressed/Hovered/
Disabled), each a public static readonly ViewModifier<Button>. Theme-aware colors
resolved at Apply(view) time via ColorTokens.X.Resolve(view) — zero allocation
per state change. Static readonly RoundedRectangle/Thickness/Color fields.

Build: dotnet build src/Comet/Comet.csproj -c Debug → 0 errors, no new warnings.

Decision note: src/Comet/.squad/decisions/inbox/amos-phase1-legacy-deletion.md

Out of scope (flagged for Bobbie): 9 sample apps reference deleted API and will
need migration or deletion in a follow-up phase.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1.1: Fix ThemeManager tests for record value equality

Theme is now a record (value equality semantics). Assert.Same checks
reference identity, which is the wrong primitive for record comparison.
Switched both ThemeManager_SetTheme_ChangesGlobalTheme and
ThemeManager_CurrentView_ReturnsGlobalTheme to Assert.Equal.

Test count: 798 -> 800 passed, 6 -> 4 failed (remaining 4 are unrelated
pre-existing flakes).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1.1: Rewrite template copilot-instructions.md for Token/ViewModifier/IControlStyle API

Purges all references to the Phase 1-deleted legacy API (Theme.Current,
AppTheme enum, ColorScheme, ThemeColors, EnvironmentKeys.ThemeColor,
.ThemeBackground/.ThemeColor/.ThemeTextColor extensions, ControlStyle<T>,
Style/Style<T>/StyleBuilder, ResourceDictionary, AppThemeBinding,
VisualStateManager, StaticResource/DynamicResource, IThemeable,
StyleAwareValue).

Teaches the canonical Phase 1 surface: tokens (ColorTokens, TypographyTokens,
SpacingTokens, ShapeTokens), Theme as an immutable record composed via 'with'
from Defaults.Light/Dark, ViewModifier with static singleton instances,
IControlStyle<TControl, TConfig> with ButtonStyles.Filled/Outlined/Text/Elevated,
ThemeManager.SetTheme for global switching, and .UseTheme(theme) for scoped
subtree overrides.

Flags Phase 1 gaps so AI agents don't demo unimplemented behavior:
pressed/hovered/focused state transitions are not yet wired, built-in styles
exist for Button only, style transitions don't exist.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1: scribe session log

Captures Phase 1 outcome: Theme-as-record (932129e), legacy style/theme deletion + singleton BuiltInStyles (58e3935), ThemeManager record-equality test fix (4ab498b), template copilot-instructions rewrite (eb8a756). Logs final state (0 framework errors, 800/4/26 tests, NuGet repacked, template builds clean) and open follow-ups: Phase 1.5 sample migration, Phase 2 reactive state wiring, Phase 3 Toggle/TextField/Slider built-ins, Phase 4 transitions, spec §7.3 .Theme/.UseTheme reconciliation, AbstractLayout.GetDefaultPadding → SpacingTokens.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1.5: bump sample MauiVersion to preview.3.26203.7

Sample/Directory.Build.props pinned MauiVersion=preview.2.26152.10 but the
framework Comet.csproj (built as ProjectReference) resolves the workload's
preview.3.26203.7, causing NU1605 downgrade errors on every sample. Aligning
the sample-side override with the framework's transitive version.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1.5: migrate CometMauiApp + CometVideoApp Theme startup

Replace removed `Theme.Current = X` setter with `ThemeManager.SetTheme(X)`
per STYLE_THEME_SPEC §6.2. Both samples now use the canonical Phase 1 theme
switch API.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1.5: drop deleted Material style demo from Comet.Sample

The Material palette and `MaterialStyle` / `ControlStyle<T>` / `.ApplyStyle()`
APIs were removed in Phase 1 (see inbox/amos-phase1-legacy-deletion.md).
`MaterialStylePicker` and `MaterialSample` existed only to demo those types
and have no migration path. Deleting both files and the "Material Design"
menu entry rather than faking a migration (per Phase 1.5 scope directive).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1.5: migrate CometBaristaNotes CoffeeTheme to Theme record

- Remove `CoffeeControlStyles.cs` wholesale. It defined
  `ControlStyle<Button>`/`ControlStyle<View>` instances (deleted type), and
  every call site already consumes `CoffeeModifiers.PrimaryButton` etc. via
  `.Modifier(...)` — the file was dead.

- Strip deleted legacy Theme properties from `CoffeeTheme.cs`:
  `CurrentTheme` (AppTheme enum gone), `PrimaryColor`/`BackgroundColor`/
  `SurfaceColor`/`TextColor`/`SecondaryTextColor`/`ErrorColor`, and the
  `ColorScheme = new ThemeColors { ... }` duplicate blocks. The
  `Colors = new ColorTokenSet { ... }` blocks remain — those are the spec
  §5.2 canonical path.

The sample's own `AppThemeMode` enum + `IThemeService` are unaffected
(locally defined, not Comet API).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1.5: migrate CometControlsGallery to Theme-as-record API

- App.cs / StyleSystemPage.cs / ThemePage.cs: `Theme` is now a record
  (Phase 1), so `theme.SetControlStyle<T,C>(style)` returns a new instance
  rather than mutating. Every call site was discarding the return value,
  leaving the theme unchanged. Re-bind the local to the returned record
  before `ThemeManager.SetTheme(theme)`.

- StyleSystemPage.cs: `theme.GetNewControlStyle<Button>()` →
  `theme.GetControlStyle<Button, ButtonConfiguration>()` (typed two-arg
  signature is the only remaining shape per spec §5.2).

- CometControlsGallery.csproj: make the `mauiplatforms/Platform.Maui.MacOS`
  `<Import>` conditional on `-macos` TFM + file existence. The sibling repo
  isn't checked out locally, and the unconditional Import broke every non-
  macOS build even before Phase 1. Unrelated to style migration but
  necessary for the Phase 1.5 build gate (net11.0-ios).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1.5: decision note + build helper

Log the sample migration pass (migrated / deleted / left-as-is) and commit
the build-samples.sh helper so the net11.0-ios gate is reproducible.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Phase 1.5: E2E all 19 Comet samples on iPhone 17 Pro / iOS 26.2

Launch + smoke-interact verification of every net11.0-ios-capable Comet
sample on sim UDID 95EC018A-A8CF-4FAB-98A4-EF49D2E626B3 (iOS 26.2 23C54).

Result: 19/19 build, launch, render real UI, survive a light/dark
appearance toggle, and terminate cleanly. No framework regressions.

Per-sample artifacts at .squad/artifacts/phase15-e2e/<Sample>/ show
launch.png (light) + after-interact.png (dark) as evidence of a real
UI and a working trait-change path. 4 oversized PNGs downscaled with
sips -Z 900 to stay under the 1MB cap.

Two samples (Comet.Sample, CometBaristaNotes) needed a one-shot
rm -rf obj bin because their pre-preview.3 incremental obj retained
the preview.2 static registrar map - a stale-intermediate issue, not
a code regression. Flagged in the decision note as a CI hint (clean
on MauiVersion change).

Runner is .squad/e2e-ios.sh; decision note at
.squad/decisions/inbox/bobbie-phase15-e2e.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Merge fix: restore net11 preview SDK resolution in global.json

The merge of origin/main pulled in a .dotnet/sdk paths lock + rollForward:latestMinor
+ allowPrerelease:false, which pinned local builds to SDK 10.0.105 and broke all
net11.0-* TFMs used by the Comet framework and 19 samples.

Keeps main's Arcade SDK bump + tools pin but restores permissive SDK resolution so
net11 preview (11.0.100-preview.3) can be picked from the host install.

Verified: Comet.csproj builds 0 errors across net11.0-android/-ios/-maccatalyst.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: ignore local tool/build artifacts and .vscode/settings.json

Adds rules for .csproj.lscache, .binlog, screenshot_*.png,
negation so per-user VS Code settings stay local.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: add UTF-8 BOM to source files for .NET Hot Reload

Hot Reload / EnC in VS Code computes a source-file hash and compares
it against the PDB-embedded hash. Files saved as UTF-8 without BOM
produce a different hash than the compiler emitted, breaking apply.
Re-saves 348 source files with UTF-8 BOM so hot reload works reliably.

Mechanical change — no code edits.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore(comet): bump iOS/MacCatalyst min to 17.0 and clean up sample csprojs

- Directory.Build.props: SupportedOSPlatformVersion for ios and
  maccatalyst bumped from 15.0 to 17.0 (matches current baseline).
- Comet.Benchmarks.csproj: parameterize MAUI package versions using
  $(MauiVersion) instead of hard-coded preview string.
- Sample csprojs: drop obsolete Microsoft.Maui.Controls.Compatibility
  PackageReference across Comet.Sample, CometFeatureShowcase,
  CometMarvelousApp, CometProjectManager, CometStressTest,
  CometTrackizerApp, CometWeather.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(comet): add Comet.Layout.Yoga library

Introduces a managed Yoga layout engine port as a sibling project of
Comet, exposing YogaNode / YogaStyle / YogaConfig / YogaAlgorithm and
related types. This becomes the shared layout core used by the new
stack/flex layout managers in Comet and by DevFlow's layout inspector.

- src/Comet.Layout.Yoga/: new csproj, algorithm, enums, node/style/config,
  flex helpers, layout results, THIRD-PARTY-NOTICES, README.
- docs/CHANGELOG-Yoga.md: design and implementation notes.
- Comet.sln: register Comet.Layout.Yoga plus a few DevFlow / BaristaNotes
  projects that were previously missing from the solution.
- src/Comet/Comet.csproj: add ProjectReference to Comet.Layout.Yoga and
  bump iOS / MacCatalyst SupportedOSPlatformVersion to 17.0 to match
  Directory.Build.props.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(comet): Yoga-based stack and flex layout managers

Re-platforms Comet's HStack, VStack, ZStack and FlexLayout layout
managers on top of the new Comet.Layout.Yoga engine. HStack and VStack
delegate to a shared YogaStackLayoutManager; FlexLayoutManager is
rewritten to mirror FlexLayout semantics through Yoga.

- Layout/YogaStackLayoutManager.cs (new): shared Yoga-driven stack
  algorithm consumed by HStack and VStack managers.
- Layout/YogaMeasureBridge.cs (new): adapter that feeds Comet view
  measure callbacks into Yoga's measure protocol.
- Layout/IYogaLayoutInspector.cs (new): opt-in hook so DevFlow can
  observe computed layout nodes without Comet taking a hard ref on
  the DevFlow assembly.
- Layout/HStackLayoutManager.cs, VStackLayoutManager.cs,
  ZStackLayoutManager.cs, FlexLayoutManager.cs: delegate to the Yoga
  path and prune the legacy code paths they no longer need.
- Controls/FlexLayout.cs: expose style inputs expected by the Yoga
  manager and drop duplicated measurement logic.
- Helpers/LayoutExtensions.cs, Internal/ReflectionExtensions.cs: add
  helpers used by the Yoga managers (style reads, reflection-based
  environment lookups).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* test(comet): Yoga layout test suite

Adds two layers of tests for the new Yoga layout engine.

- src/Comet.Layout.Yoga.Tests/: ports the upstream facebook/yoga
  gentest suite as-is (YogaGenerated/*) plus YogaEdgeCaseTests,
  validating the managed Yoga port against the reference fixtures.
- tests/Comet.Tests/Layout/: end-to-end tests exercising Comet's
  YogaStackLayoutManager, YogaMeasureBridge, YogaLayoutInspector hook,
  FlexLayout integration, and a regression suite for known iOS/MAUI
  sample layout bugs.
- Comet.Tests.csproj: parameterize MAUI package versions using
  $(MauiVersion) and reference Comet.Layout.Yoga.
- LayoutTests2.cs: updates for the reworked stack managers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(devflow): Yoga layout inspection across agent, driver, and CLI

Surfaces computed Yoga layout data through the DevFlow tree inspection
pipeline so agents can reason about flex/stack layout behaviour.

- Agent.Core/LayoutInspectorAdapter.cs: implements
  IYogaLayoutInspector from Comet and captures per-view Yoga nodes as
  the visual tree is walked.
- Agent.Core/ElementInfo.cs, Driver/ElementInfo.cs: shared DTO
  carrying layout metrics (computed bounds, margins/padding, flex
  direction, justify/align, grow/shrink/basis) across the wire.
- Agent.Core/VisualTreeWalker.cs: populate the new ElementInfo layout
  fields while walking, using the adapter when available.
- Agent.Core/DevFlowAgentService.cs: register the inspector adapter
  during agent startup.
- Driver/AgentClient.cs, AppDriverBase.cs: expose the layout fields
  on returned ElementInfo.
- Cli/DevFlow/DevFlowCommands.cs, Mcp/Tools/TreeTool.cs: render the
  layout fields in tree output so MCP agents can see them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* feat(comet): NavigationView large-title opt-in and sample updates

Adds an opt-in large-title mode on NavigationView and updates the
BaristaNotes, ControlsGallery, and FeatureShowcase samples to match.

- Helpers/ColorExtensions.cs: add NavigationPrefersLargeTitles(bool)
  setter and GetNavigationPrefersLargeTitles() getter extensions on
  View. (Name is misleading — these live here with the other
  environment-backed extensions; a future commit can rehouse them.)
- EnvironmentData.cs: add the NavigationPrefersLargeTitles env key.
- Handlers/Navigation/NavigationViewHandler.iOS.cs: honour the env
  value — set UINavigationBar.PrefersLargeTitles and, when enabled,
  LargeTitleDisplayMode.Always on the view controller.

Sample updates:
- CometBaristaNotes: BaristaApp opts into large titles, ShotLoggingPage
  rework, ActivityFeedPage gains filter UI, BeanManagementPage /
  SettingsPage / UserProfileManagementPage / BeanDetailPage /
  EquipmentDetailPage small fixes, OperationResult model tweaks.
- CometControlsGallery: ControlsPage / LayoutsPage / ShapesPage touched
  up for the new layout behaviour.
- CometFeatureShowcase: AnimationPage minor adjustments.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: CI  conditional Go.Server ref + suppress TFM warningsbuild

The CLI multi-targets net9.0;net10.0 (PR #114) so dotnet tool install
works on both SDKs. Go.Server targets net10.0 only (uses .NET 11 preview
Roslyn APIs), causing NU1201 on the net9.0 build.

Fix:
- Make Go.Server ProjectReference conditional on net10.0
- Guard GoDevServer.RunAsync with #if NET10_0_OR_GREATER
- Add SuppressTfmSupportBuildWarnings to CLI and DevFlow.Driver
  (11.0-preview packages emit hard errors on net9.0 but the code
  is  dotnet picks the highest TFM at install time)compatible

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: scrub junk before main PR

Remove files that should never have been committed:
- .claude/settings.local.json (per-machine Claude Code state; PR #176
  on main adds this to .gitignore)
- screenshot_20260408_205739.png, screenshot_20260408_205831.png
  (debugging screenshots at repo root)
- test-go-app/ (scratch test app at repo root; samples and playground
  belong in samples/ or playground/)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: restore BLE Monitoring + Skills system that were silently dropped on merge

The merge 45fb43cd ('Merge branch main into feature/comet') resolved
deletions in favor of feature/comet for files that were net-new on main:

- BLE Monitoring (Agent.Core/BleMonitor.cs + 4 platform impls + tests + MCP tool)
- DevFlow Skills system (Skills/DevFlowSkillCommands.cs, DevFlowSkillManager.cs,
  + 2 unit test files, + 12 plugin skill markdown files for maui-devflow-debug
  and maui-devflow-onboard)

These are not Comet-related and should not have been removed. Restore
them at origin/main's content.

Note: feature/comet's competing 'update-skill'/'skill-version' impl in
DevFlowCommands.cs is addressed in the next commit by reverting to main's
version (which delegates to the bundled DevFlowSkillCommands).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align DevFlow + Cli files with main, drop competing impls

The merge 45fb43cd ('Merge branch main into feature/comet') silently
favored feature/comet for files where main had net-new content. This
commit takes main's version for all DevFlow + Cli + workflow + docs
files outside src/Comet/ and src/Go/ so that:

- BLE tools (Mcp/Tools/BleTools.cs) compile against AgentClient
- Skills system (Skills/DevFlowSkillCommands.cs) compiles against
  OutputWriter
- DevFlow specs, plugin manifest, READMEs, and CI workflows match main
- DevFlowCommands.cs no longer carries the competing 'update-skill' /
  'skill-version' impl that conflicts with the bundled Skills system

The DevFlow Comet support that was on feature/comet (CometViewResolver
enhancements, IApplication binding, layout inspector, IView visibility
overrides) is preserved in the open DevFlow PRs targeting main:

- PR #174 fix/devflow-comet-resolver
- PR #177 fix/devflow-comet-iapplication

When those merge, this branch's diff vs main shrinks accordingly.

LayoutInspectorAdapter.cs is removed because it depends on LayoutInfo
types that live on the PR #174 branch but not on main yet — it will be
restored on main via PR #174.

global.json (allowPrerelease=true, rollForward=latestMajor) and
eng/Versions.props (MAUI 11.0 preview, Extensions 11.0 preview) are
kept from feature/comet because Comet/Go projects target net11.0 and
require those package versions.

Cross-cutting infra:
- .gitignore: kept (additive)
- Directory.Packages.props: kept (adds Go packages)
- MauiLabs.slnx: kept (adds Comet/Go projects)
- NuGet.config: reverted (repo policy: no direct nuget.org)
- global.json: kept (Comet/Go need net11)
- eng/Versions.props: kept (Comet/Go need preview packages)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: align Comet MauiVersion with repo and unblock Comet.Tests + samples

- src/Comet/Directory.Build.props: import eng/Versions.props and define
  MauiVersion = MicrosoftMauiControlsVersion so csprojs that use
  Version="$(MauiVersion)" resolve against the repo's pinned MAUI
  preview. Fixes NU1015 in Comet.Tests restore.

- src/Comet/sample/Directory.Build.props: replace stale hard-coded
  MauiVersion (11.0.0-preview.3.26203.7) with explicit Import of the
  parent Directory.Build.props. MSBuild's 'first Directory.Build.props
  wins' rule was preventing samples from picking up the parent's
  MauiVersion definition, causing NU1605 package downgrades.

- src/Comet/sample/Directory.Build.targets: centralize SupportedOSPlatformVersion
  bumps (ios/maccatalyst 17.0, android 23.0) for all 22 sample apps so
  they build against the current iOS/MacCatalyst SDK and Android minSdk
  requirements without per-project edits.

Verified clean builds: Comet.Sample, CometTodoApp, CometWeather (all 4 TFMs).
Comet.Tests now restores and runs (838 passed, 26 skipped, 4 pre-existing
failures unrelated to these changes).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* chore: scrub broken Go template; fix Comet.Tests FlowDirectionDefault

- Delete src/Go/Templates/maui-go/ scaffolding. The MauiGoApp.csproj was
  not a real 'dotnet new' template (no .template.config/template.json),
  had a broken ProjectReference path (..\..\Comet vs ..\..\..\Comet), and
  used a leftover token namespace 'MauiGoApp._1'. Not in MauiLabs.slnx,
  not referenced anywhere except src/Go/Go.sln. Removed from Go.sln.
  Real Go templates can be added as follow-up work.

- ViewExtensionTests.FlowDirectionDefault: assertion was incorrect.
  Comet's IView.FlowDirection reads from environment via
  GetEnvironment<FlowDirection>(...), which returns default(FlowDirection)
  when unset. The default enum value (0) is MatchParent, not LeftToRight.
  Updated assertion + comment.

Comet.Tests now: 839 passed, 26 skipped, 3 failed (pre-existing template
staleness — TemplateCurrentSurfaceValidationTests; unrelated to merge
readiness, tracked separately).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: fix critical/major accuracy issues in root README + AGENTS + CONTRIBUTING + plugins

- .github/CONTRIBUTING.md: MauiLabs.sln -> MauiLabs.slnx (5 places); replace {Product}/ placeholder with Cli/DevFlow/Comet/Go enumeration
- AGENTS.md: System.CommandLine 2.0.0-beta4 -> 2.0.5; add Cli/Comet/Go to Products table and project layout tree
- README.md: add Comet and Go to Products section
- plugins/README.md: remove non-existent maui-ai-debugging row; add devflow-connect row

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(comet): fix critical/major/minor accuracy issues in Comet READMEs and docs

- .NET 10 -> .NET 11; net10.0/net9.0 TFMs -> net11.0
- MAUI version refs aligned with eng/Versions.props (11.0.0-preview.3.26207.5)
- Platform minimums updated to match Directory.Build.targets enforcement (ios/maccatalyst 17.0, android 23.0)
- Legacy [Body] examples now marked as legacy with pointer to Component<TState> pattern
- CometProjectManager: add Build section
- Comet.Layout.Yoga: verify/correct provenance date

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: modernize Comet README; add Comet Go README + getting-started

- src/Comet/README.md: lead with Component<TState> + override View Render()
  and 'using static Comet.CometControls' factory style; demote [Body] to a
  legacy section at the bottom; align all examples with the canonical pattern
  used in samples and Comet/AGENTS.md.
- src/Go/README.md (new): top-level intro to Comet Go (server + companion
  app + shared protocol), how it works, requirements, limitations, status.
- src/Go/docs/getting-started.md (new): step-by-step walkthrough from
  fresh checkout to live edits, including hot-apply rules and common
  troubleshooting.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(comet): use UseCometApp<T>() in Getting Started

UseCometApp<T>() is the canonical one-call setup used by every sample
in src/Comet/sample/ — it registers handlers, sets the app type, and
wires lifecycle. Replace the older two-step UseMauiApp + UseCometHandlers
example.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(comet): fix Theme.SetControlStyle and Navigation examples

- Theme.SetControlStyle<T,C>() returns a derived Theme (record), so the
  return value must be captured before calling ThemeManager.SetTheme().
  The previous example discarded the result and would have been a no-op.
  Verified against src/Comet/Styles/Theme.cs:46 and the
  CometControlsGallery samples.

- Navigation.Navigate<TView>() is an instance call on View.Navigation,
  not a static method. Updated the example to show the canonical
  Navigation?.Navigate<TView>(props) pattern from inside a component,
  plus the NavigationView wiring at the app root. Verified against
  src/Comet/Controls/NavigationView.cs:44-55 and CometTaskApp samples.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs(go): correct SDK requirement and Android emulator networking note

- Replace '.NET 11 SDK (preview)' with the actual global.json pin
  (10.0.105 with rollForward: latestMajor + allowPrerelease) plus a
  note that the .NET 11 preview SDK also works. The companion app's
  net11.0-* runtime packs come from the MAUI workload, not from the
  SDK itself.
- Tighten the Android emulator note: the QR-encoded LAN IP works for
  physical devices and bridged emulators but not for the default
  emulator NAT, so users must paste the URL and replace the IP with
  10.0.2.2 manually.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* build(go): pin .NET 11 SDK preview via src/Go/global.json

Mirror Comet's setup: add a directory-scoped global.json that pins the
latest .NET 11 SDK preview with rollForward: latestPrerelease, so the
Go server, companion app, and HelloGo sample all build with the same
SDK Comet uses. Update README and getting-started to point at this
file.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Revert eng/Versions.props to stable 10.0.x, pin Go.Server packages

The 11.0-preview package bump in Versions.props broke the CLI's
net9.0 multi-target (11.0-preview packages hard-error on net9.0).

- Revert Versions.props to main's stable 10.0.x versions
- Pin Go.Server's CodeAnalysis to 4.14.0 (needs LanguageVersion.Latest
  and EmitDifference overloads not in 4.12.0)
- Pin Go.Server's QRCoder to 1.7.0 (needs AsciiQRCode class)

Go.Server already has its own global.json for the .NET 11 SDK.
Now its package versions are also self-contained via VersionOverride.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Disable AOT/trim analyzers for Go.Shared (dev-time tool)

GoProtocol.cs uses non-source-gen JsonSerializer which errors with
the trim/AOT analyzers. Go projects are dev-time tools, not
AOT-published apps.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Also disable EnableAotAnalyzer for Go.Shared

IL3050 errors were not suppressed by IsAotCompatible=false alone.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Disable AOT/trim/single-file analyzers for Go.Server

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Add missing package versions for OpenApi, YamlDotNet, MAUI Go

Versions.props revert to 10.0.x dropped entries added by the Comet
feature. Restore them with their original stable values.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Bump CodeAnalysis to 4.14.0 and QRCoder to 1.7.0 centrally

Remove VersionOverride from Go. central versions now matchServer
what the code needs. Eliminates NU1109 downgrade conflicts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Restore VersionOverride on Go.Server packages

src/Go/ has its own global.json which breaks central package management
traversal. VersionOverride ensures correct resolution. Central versions
already aligned at 4.14.0/1.7.0 so no downgrade conflict.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Add QRCoder and CodeAnalysis to third-party signing list

New Go.Server dependencies need 3PartySHA2 signing entries.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Remove CodeAnalysis from  it's a Microsoft library3PartySHA2

Only QRCoder needs third-party signing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add Comet CI workflow with release artifact attachment

Build and test on macOS + Windows using .NET 11 preview SDK.
On release: attaches .nupkg to the GitHub Release.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Remove duplicate MicrosoftCodeAnalysisCSharp entries

Main branch already defines MicrosoftCodeAnalysisCSharpVersion (4.12.0)
and the PackageVersion for Microsoft.CodeAnalysis.CSharp. The MAUI Go
section duplicated both, causing NU1506 on merge. Comet opts out of CPM
so it doesn't need the repo-level entry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Bump MicrosoftCodeAnalysisCSharpVersion to 4.14.0

Microsoft.Maui.Go.Server transitively requires CodeAnalysis.CSharp >= 4.14.0.
The repo-wide CPM version must be at least this to avoid NU1109 downgrades.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Use Windows.Foundation types for Size/Rect in WinUI CometView

In .NET 11 preview, Microsoft.UI.Xaml.Size and Microsoft.UI.Xaml.Rect no
longer exist. Replace with Windows.Foundation.Size and
Windows.Foundation.Rect which are the canonical WinRT structs used by
the WinUI layout system.

Also add 'using Microsoft.UI.Xaml;' so UIElement resolves without
full qualification.

The CS0311 errors in NativeHostHandler.Windows.cs and
CometViewHandler.Windows.cs are  they occur becausecascading
CometView.cs failed to compile, leaving the Comet.Windows.CometView
type unresolvable. The MAUI ViewHandler constraint is still
FrameworkElement, and Grid still inherits from FrameworkElement via
Panel, so no handler-registration changes are needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix template validation tests to match actual template

- Template uses [Body] + View body() pattern, not Component<T> + Render()
- Template targets net11.0, not net10.0
- Template uses $(MauiVersion) MSBuild property, not MAUI_VERSION placeholder

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix Windows.Foundation namespace collision in Comet.Windows namespace

Use global:: qualifier for Windows.Foundation.Size and Rect to prevent
the compiler from resolving 'Windows' as 'Comet.Windows' within the
Comet.Windows namespace.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix: use global::Microsoft.UI.Xaml.Size/Rect for WinUI overrides

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix WinUI .NET 11: Size/Rect removed from Microsoft.UI.Xaml

Microsoft.UI.Xaml.Size and Microsoft.UI.Xaml.Rect no longer exist in
.NET 11 WinUI. The canonical types are Windows.Foundation.Size/Rect.

Use 'using WinSize = global::Windows.Foundation.Size' aliases to avoid
namespace collision with Comet.Windows/Comet.Handlers namespace.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Temporarily disable Windows TFM for Comet

WinUI .NET 11 preview has breaking API changes: Grid no longer descends
from FrameworkElement, and MeasureOverride/ArrangeOverride signatures
changed. This requires a fundamental rework of the Windows platform
views that can't be done without the .NET 11 WinUI SDK locally.

Disable the Windows TFM until the WinUI .NET 11 API stabilizes.
iOS, Android, and Mac Catalyst continue building and passing tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Enable Windows (net11.0-windows10.0.19041.0) platform build for Comet

- Uncomment Windows TFM in Comet.csproj
- Fix namespace collisions: Comet.Grid shadows Microsoft.UI.Xaml.Controls.Grid
  - Add WinGrid alias in CometView.cs, NativeHostHandler.Windows.cs
- Fix global namespace resolution for Windows.Foundation, Windows.ApplicationModel
  (Comet.Windows namespace shadows the global Windows namespace)
- Replace missing ColorHelper with direct Windows.UI.Color struct initialization
- Cast to IView for Background property to fix delegate type inference
- Update global.json to .NET 11 preview 3 SDK

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Suppress ~7,500 Comet build warnings

Comet was ported from an existing codebase without nullable annotations.
Disable nullable and suppress known warning categories across all three
Comet projects:

- Comet.csproj: Nullable=disable, suppress CS0649/CS0618/CS0108/CA1416
- Comet.Tests.csproj: Nullable=disable, suppress CS0219
- Comet.SourceGenerator.csproj: Nullable=disable, suppress RS1024/RS1032/RS2008/CS0649/CS0169
- Remove unnecessary System.Collections.Immutable package reference (NU1510)

Expected to reduce CI warnings from ~7,500 to near zero.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Revert root global.json to main's stable settings

Go and Comet have their own global.json for .NET 11 preview SDK.
The root should stay on latestMinor/allowPrerelease=false.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* revert: Restore root global.json with latestMajor + allowPrerelease

Comet CI needs this until the workflow is updated to use Comet's
own global.json for SDK resolution.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* cleanup: Remove unused Clancey.Comet package reference

Comet source is imported  the NuGet package is not referenceddirectly
by any project.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Revert root global.json to stable, scope Comet CI to src/Comet

Root global.json restored to main's settings (latestMinor,
allowPrerelease=false). Comet CI workflow now uses
working-directory: src/Comet so dotnet picks up Comet's own
global.json for .NET 11 preview SDK resolution.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* cleanup: Remove stale files from Comet import

Comet was imported from a standalone repo. These files are either
duplicates of root-level equivalents or stale:

- CODE-OF-CONDUCT.md,  duplicate of root repoLICENSE
- Comet.sln, Comet.Debug.sln, Comet.sln. stale,DotSettings
  contain broken external paths to sibling repos
- .editorconfig, .gitignore, . standalone repogitattributes
  boilerplate, root-level configs apply

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: Update Comet README for maui-labs context

- Remove stale badges (old dotnet/Comet repo)
- Add experimental status note at top
- Update build instructions with .NET 11 SDK requirement
- Add repo-root build command
- Replace standalone status section with contributing link

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* cleanup: Remove standalone repo artifacts from Comet import

Comet was imported from a standalone repo. These artifacts are not
functional in a subfolder of maui-labs:

- AGENTS. duplicates root AGENTS.md Squad governancemd
- COMET_INTEGRATION_EXAMPLES. aspirational DevFlow integrationcs
  code (follow-up issue filed for docs)
- . 31 generic Squad skills, not Comet-specificcopilot/
- . Squad workflows not executed from subfoldergithub/
- . full Squad team framework (17 dirs)squad/
- package.json, package-lock. Squad CLI toolingjson

191 files removed, ~21,800 lines deleted.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix: Update FindRepoRoot to use global.json instead of deleted Comet.sln

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* cleanup: Remove squad.agent.md  references deleted Squad filesshim

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* docs: Add maui go commands to CLI README

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* restore: Bring back Comet Squad, update docs with maui go

- Restore src/Comet/.squad/, .copilot/, .github/ (Squad team framework)
 comet-squad.agent.md
  to clarify it's scoped to Comet only
- Update comet-squad.agent.md description and content
- Add maui go commands to root README.md
- Add maui go and maui profile to AGENTS.md CLI description

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Amos <amos@squad.local>
Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
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.

2 participants