Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 109 additions & 4 deletions HANDOFF.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,114 @@
# Handoff β€” Windows COM-backend verification (`feat/com-backend`)
# Handoff β€” Windows COM-backend verification

**Date:** 2026-05-29 Β· **Branch:** `feat/com-backend` Β· **Host:** Windows 11 on **ARM64**, App Installer `Microsoft.DesktopAppInstaller 1.29.140.0` (Arm64), winget `v1.29.140-preview`.
**Latest:** session 3 Β· 2026-06-13 Β· branch `main` Β· Windows 11 **ARM64**, App Installer `1.29.250.0` (Arm64), winget `v1.29.250`.
**Originally:** session 2 Β· 2026-05-29 Β· branch `feat/com-backend` Β· App Installer `1.29.140.0`, winget `v1.29.140-preview`.

This was a human-in-the-loop Windows verification run against `WINDOWS-TESTING.md`. A human drove the
interactive TUI; the agent handled builds, non-interactive checks, diagnosis, and fixes.
Sessions 1–2 were human-in-the-loop (a human drove the interactive TUI; the agent handled builds,
non-interactive checks, diagnosis, fixes). Session 3 was fully autonomous (no human at the TUI), so it
resolved the headline question and exercised the COM backend via read-only diagnostics rather than the
interactive flows β€” see the session-3 block immediately below.

---

## βœ… SESSION 3 (2026-06-13) β€” headline question RESOLVED + a second COM bug found & fixed

**1. βœ…βœ… COM-on-AOT is SOLVED β€” Native AOT now activates the COM backend. AOT is the ship target.**
First the failure was isolated (fresh AOT `--comdiag` FAILED `0x80073D54` on both MTA threads; the same source
as a JIT self-contained build activated 3 catalogs β†’ genuine AOT-specific bug, not machine state). Then it was
**fixed** by switching to the **in-process** WinGet server:

| Build | `coreclr.dll` | `--comdiag` |
|-------|---------------|-------------|
| Native AOT, OOP activation (before) | absent | FAILED `0x80073D54` |
| JIT self-contained, OOP (control) | present | OK β€” 3 catalogs |
| **Native AOT, in-proc (the fix)** | **absent** | **OK β€” 3 catalogs, both MTA threads** |

**The fix** (`WingetTuiSharp.csproj` + new `app.manifest`, Windows TFM only):
- Add `Microsoft.WindowsPackageManager.InProcCom` (match ComInterop's version, `1.29.190-preview`) with
`ExcludeAssets="compile" NoWarn="NU1701"` β€” native-only package shipping `WindowsPackageManager.dll` (~7 MB)
+ `Microsoft.Management.Deployment.InProc.dll`. Keep ComInterop (managed projection).
- `<ApplicationManifest>app.manifest</ApplicationManifest>`; `app.manifest` transplants the InProc package's
`<file>` comClass/`activatableClass` block so `new PackageManager()` activates **in-proc**, not OOP.

**Why OOP failed under AOT:** the manual-activation shim `winrtact.dll`
(`WinGetServerManualActivation_CreateInstance`) was **dropped from ComInterop β‰₯ 1.10.x**
([winget-cli#5459](https://github.com/microsoft/winget-cli/issues/5459),
[#4839](https://github.com/microsoft/winget-cli/issues/4839)); AOT has no CsWinRT runtime fallback to reach the
registered OOP server (JIT does). In-proc needs neither the OOP server nor package identity β†’ activates under AOT.

Verified on the AOT build via `--comsmoke`: search / installed (299) / upgrades / versions (113) / installer-preview
(`Burn Β· arm64 Β· user`) / COM detail (Tags=10, Support, Docs) / Verify=Ok β€” all in-proc. Badge reads
**`COM Β· winget 1.29.190-preview`** (the bundled in-proc engine version). **Bonus:** in-proc sidesteps the OOP
server-wedge problem entirely. **Size:** AOT single-exe stays ~22.4 MB; +7.3 MB in-proc engine beside it (vs the
~112 MB JIT self-contained folder that was the abandoned fallback).

**Leads that did NOT work (don't retry):** CsWinRT 2.2.0 optimizer; `Microsoft.Windows.CsWinRT 3.0.0-preview`
(breaks at its own `cswinrt.exe` codegen + WinRT.Runtime conflict); bare `app.manifest` with only
`supportedOS`/`longPathAware` (no in-proc routing); warming the OOP server.

**2. πŸ› Second, independent COM bug FOUND & FIXED β€” `ComBackend.ConnectAsync` (`src/ComBackend.cs`).**
`ConnectAsync` set `reference.AcceptSourceAgreements = true` on the **composite** catalog reference, which
throws `E_ILLEGAL_STATE_CHANGE` (`set_AcceptSourceAgreements` on `IPackageCatalogReference3`). All three
composite-connect callers (search, list, find-by-id) hit it β€” so **every COM search/list/detail would have
thrown the instant COM activated.** It stayed latent because AOT always fell back to CLI, so the COM path
never actually ran in the app. `RemoteRefs` already sets `AcceptSourceAgreements = true` on each *source*
ref (the API-correct place) before compositing, making the composite set both redundant and illegal.
**Fix:** removed the set from `ConnectAsync` (comment explains why). After the fix, the full COM surface works.

**3. COM verification done on the JIT build (read-only, non-destructive) β€” all passing:**
- Badge / `DescribeAsync` β†’ **`COM Β· winget 1.29.250`** Β· `CanRepair` β†’ **True**
- `ListSourcesAsync` β†’ **`msstore, winget, winget-font`** (dynamic; picks up the custom `winget-font` source)
- `SearchAsync("powertoys")` β†’ **19** results (`PowerToys [Microsoft.PowerToys] 0.100.0 winget`)
- `ListInstalledAsync` β†’ **299** Β· `ListUpgradesAsync` β†’ **10** (`PostgreSQL 18 18.3-3 β†’ 18.4-1`, Available populated)
- `ListVersionsAsync(Microsoft.PowerToys)` β†’ **112** versions, newest-first
- `GetInstallerPreviewAsync(Microsoft.PowerToys)` β†’ **`Burn Β· arm64 Β· user`**
- `VerifyInstalledAsync(ajeetdsouza.zoxide)` β†’ **Ok** after the per-installer Verify fix (item 5). *(This is the package that surfaced the bug: before the fix it reported **Issues**, `1 of 3 checks failed` (`Registry entry β€” hr 0x8A150201`) β€” a non-installed manifest installer's "ARP entry not found", not a real problem. Post-fix, zoxide/PowerShell/7-Zip all verify **Ok**.)*
- `ShowAsync(Microsoft.PowerToys)` β†’ **Tags (10), Support, Documentation(Wiki), Author, Copyright, Privacy** all
Comment thread
harder marked this conversation as resolved.
populate β†’ **resolves the old `#17`** (ProductCode/FamilyName null is legit β€” PowerToys is a `burn` installer).
- **Operation + progress paths** (`--comop ajeetdsouza.zoxide`, on COM/JIT β€” these had NEVER run before):
- `DownloadAsync(zoxide)` β†’ **Success**, files actually landed in `%USERPROFILE%\Downloads\winget-tui`
(`zoxide_0.9.9_Arm64_portable_en-US.zip` 480 KB + `.yaml`; COM resolved the **arm64** installer). The
`IProgress<OpProgress>` callback fired (phase **Downloading**, fraction β†’ 1.00) β€” **the "live progress"
marshaling works on COM**, the path that resolves the old "CCW under AOT" unknown now that COM runs
under AOT in-proc. Cleaned up.
- `RepairAsync(zoxide)` β†’ **Success=False**, `Repair failed: RepairError (repairer 0, hr 0x8A15007C)`,
**no crash** β€” zoxide is a portable .zip with no repairer. NB this is the `RepairError` path, *distinct*
from `NoApplicableRepairer`; the message leaks the raw HRESULT. Possible follow-up: map portable/no-repairer
to the friendly "doesn't support repair." line. The `Verify(Issues) β†’ Repair β†’ Verify` sequence ran e2e.
- `dotnet test -f net10.0` β†’ **pass** (18 facts incl. all three P1.5 ports' logic).

**4. Still NOT verified (need a human at the interactive TUI, and/or are destructive):** actual
install/uninstall/upgrade *execution* (download + repair WERE exercised β€” see item 3); the **status-bar progress
render** + cooperative **Esc cancel**; the dialog/panel *rendering* (install preview, version-picker list,
advanced-install options, Verify→Repair-button flow); the three P1.5 ports' end-to-end terminal *interaction*
(mouse header clicks, `u`/`P`/`/` keypresses); pinning; the P2 thread-agility / unhealthy-source probes.
NOTE: COM now runs **under AOT in-proc** (see item 1), so the CCW progress-callback marshaling is in play on
the shipped AOT build and should be confirmed there β€” the `DownloadAsync` progress path already exercised it
cleanly. (The read-only verification in item 3 was first done on JIT, then re-confirmed on the AOT build via
`--comdiag`/`--comsmoke`.)

**5. Fixes committed (session 3).** Beyond the `ConnectAsync` COM-activation fix, this pass found and fixed,
from a real interactive COM run + the user's feedback:
- **Verify false "Issues"** (`src/ComBackend.cs` `VerifyInstalledAsync`): `CheckInstalledStatus` returns a block
per *manifest installer*; the non-installed ones report "ARP entry not found" (0x8A150201). Old code flattened
all installers and flagged Issues on any failure β†’ healthy multi-installer/portable packages looked corrupt.
Now grouped per installer: **Ok if any one installer's checks all pass**; the dialog shows that clean installer.
- **Narrow-terminal columns** (`src/App.cs`): Name/Id/Version shrink toward minimums so **Available** stays
visible instead of being pushed off-screen; reflows on resize via `ViewportChanged`.
- **Installed-in-Search** (`src/ComBackend.cs` `SearchAsync`, `DetailPanel.cs`, `Models.cs`): search rows read the
composite's correlated `InstalledVersion`; an installed row shows a **βœ“ Installed** badge and Uninstall/Upgrade
actions instead of a bare Install.
- **Op result through reload** (`src/App.cs` `TriggerRefresh`): the result line ("Done"/…) persists through the
post-op list reload instead of being masked by "Loading Installed…".
- **Bulk-select hint** (`src/Ui.cs`): the Upgrades status bar shows `Spc Select` / `U Upgrade sel`.

The temp `#if WINGET_COM` diagnostics (`--comdiag`/`--comshow`/`--comsmoke`/`--comverify`/`--comop`) were
**removed before commit** (re-add `--comdiag` from the appendix for the AOT activation work). Test dir
`bin\jit-x64-test\` and `bin\…\publish\` are build outputs (gitignored).

---

## (Session 2, 2026-05-29) original headline finding β€” superseded by session 3 above, kept for history

> **⚠️ If you are running on WSL / Linux:** you **cannot** run the Windows verification here.
> Native AOT codegen can't cross-compile from Linux, and the WinGet COM server + installs need
Expand Down
Loading
Loading