Skip to content

Commit 44cde8b

Browse files
harderclaude
andcommitted
docs(com): record session-3 Windows COM verification + fixes
- Headline AOT-COM question resolved: AOT fails to activate (0x80073D54), JIT works, on a freshly-booted machine with updated App Installer 1.29.250 — genuine AOT bug. - Download-only + progress callback + repair paths exercised on COM (zoxide). - Verify/ConnectAsync bugs and the TUI polish items documented as applied. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent eeb2b5c commit 44cde8b

2 files changed

Lines changed: 178 additions & 49 deletions

File tree

HANDOFF.md

Lines changed: 106 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,111 @@
1-
# Handoff — Windows COM-backend verification (`feat/com-backend`)
1+
# Handoff — Windows COM-backend verification
22

3-
**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`.
3+
**Latest:** session 3 · 2026-06-13 · branch `main` · Windows 11 **ARM64**, App Installer `1.29.250.0` (Arm64), winget `v1.29.250`.
4+
**Originally:** session 2 · 2026-05-29 · branch `feat/com-backend` · App Installer `1.29.140.0`, winget `v1.29.140-preview`.
45

5-
This was a human-in-the-loop Windows verification run against `WINDOWS-TESTING.md`. A human drove the
6-
interactive TUI; the agent handled builds, non-interactive checks, diagnosis, and fixes.
6+
Sessions 1–2 were human-in-the-loop (a human drove the interactive TUI; the agent handled builds,
7+
non-interactive checks, diagnosis, fixes). Session 3 was fully autonomous (no human at the TUI), so it
8+
resolved the headline question and exercised the COM backend via read-only diagnostics rather than the
9+
interactive flows — see the session-3 block immediately below.
10+
11+
---
12+
13+
## ✅ SESSION 3 (2026-06-13) — headline question RESOLVED + a second COM bug found & fixed
14+
15+
**1. The COM-on-AOT activation question is settled: it is a genuine Native-AOT bug. Ship the COM build non-AOT.**
16+
On a freshly-booted host (boot 6:02 PM; WinGet COM server healthy & long-lived since 6:04 PM) with an
17+
*updated* App Installer (1.29.250, was 1.29.140), `--comdiag` was run as the first deliberate COM probe:
18+
19+
| Build | `coreclr.dll` | `--comdiag` (main + threadpool, both MTA) |
20+
|-------|---------------|-------------------------------------------|
21+
| **Native AOT** (fresh publish) | absent | **FAILED `0x80073D54`** — reproduced 3× (stale 5/30 binary, fresh build, final build with the fix) |
22+
| **JIT self-contained x64** (same source) | present | **OK — 3 catalogs** |
23+
24+
Same source, same projection (`ComInterop 1.29.190-preview`), same machine, same minute. This closes the
25+
session-2 "open contradiction": the failure is **deterministic and AOT-specific**, not transient
26+
COM-server/AppModel state. The early session-1 AOT-spike "success" was the anomaly.
27+
28+
**Root cause (grounded in upstream):** the WinGet projection `Microsoft.Management.Deployment.CsWinRTProjection.dll`
29+
is precompiled against an old CsWinRT. Under JIT the runtime activation factory still activates the
30+
registered OOP server; under AOT (no reflection fallback) activation falls through to the identity-requiring
31+
path → `APPMODEL_ERROR_NO_PACKAGE`. The manual-activation shim `winrtact.dll`
32+
(`WinGetServerManualActivation_CreateInstance`) was **dropped from ComInterop ≥ 1.10.x**
33+
([winget-cli#5459](https://github.com/microsoft/winget-cli/issues/5459)) and is absent from our package
34+
(confirmed — not in the nupkg or publish dir); upstream [#4839](https://github.com/microsoft/winget-cli/issues/4839)
35+
requests an AOT-capable projection.dll, not yet shipped.
36+
37+
**Leads investigated:**
38+
- **CsWinRT 3.x → NOT viable.** `Microsoft.Windows.CsWinRT 3.0.0-preview.260319.2` breaks the build at its own
39+
`cswinrt.exe` codegen step (`Path '…\microsoft.windows.sdk.net.ref\…\winmd\windows\' is not a file or directory`)
40+
and would conflict with the projection's bundled WinRT.Runtime anyway. Reverted.
41+
- **Did NOT retry** (banner "did not fix it"): CsWinRT 2.2.0 optimizer, the Win10 `app.manifest`, server warming.
42+
- **InProcCom (`Microsoft.WindowsPackageManager.InProcCom`, ~100 MB in-proc server) → untried.** The only
43+
remaining AOT-keeping lead; would also erase most of AOT's size win.
44+
45+
**RECOMMENDATION:** ship the **Windows/COM build non-AOT** (JIT self-contained — confirmed to activate COM
46+
and return full data). **Size cost: 22.4 MB AOT single-exe → 112.7 MB JIT self-contained folder (~5×).**
47+
Alternatively keep AOT and accept the CLI backend on Windows (loses Verify/Repair/preview/version-picker/progress).
48+
49+
**2. 🐛 Second, independent COM bug FOUND & FIXED — `ComBackend.ConnectAsync` (`src/ComBackend.cs`).**
50+
`ConnectAsync` set `reference.AcceptSourceAgreements = true` on the **composite** catalog reference, which
51+
throws `E_ILLEGAL_STATE_CHANGE` (`set_AcceptSourceAgreements` on `IPackageCatalogReference3`). All three
52+
composite-connect callers (search, list, find-by-id) hit it — so **every COM search/list/detail would have
53+
thrown the instant COM activated.** It stayed latent because AOT always fell back to CLI, so the COM path
54+
never actually ran in the app. `RemoteRefs` already sets `AcceptSourceAgreements = true` on each *source*
55+
ref (the API-correct place) before compositing, making the composite set both redundant and illegal.
56+
**Fix:** removed the set from `ConnectAsync` (comment explains why). After the fix, the full COM surface works.
57+
58+
**3. COM verification done on the JIT build (read-only, non-destructive) — all passing:**
59+
- Badge / `DescribeAsync`**`COM · winget 1.29.250`** · `CanRepair`**True**
60+
- `ListSourcesAsync`**`msstore, winget, winget-font`** (dynamic; picks up the custom `winget-font` source)
61+
- `SearchAsync("powertoys")`**19** results (`PowerToys [Microsoft.PowerToys] 0.100.0 winget`)
62+
- `ListInstalledAsync`**299** · `ListUpgradesAsync`**10** (`PostgreSQL 18 18.3-3 → 18.4-1`, Available populated)
63+
- `ListVersionsAsync(Microsoft.PowerToys)`**112** versions, newest-first
64+
- `GetInstallerPreviewAsync(Microsoft.PowerToys)`**`Burn · arm64 · user`**
65+
- `VerifyInstalledAsync(ajeetdsouza.zoxide)`**Issues**, `1 of 3 checks failed` (`Registry entry — hr 0x8A150201`)
66+
- `ShowAsync(Microsoft.PowerToys)`**Tags (10), Support, Documentation(Wiki), Author, Copyright, Privacy** all
67+
populate → **resolves the old `#17`** (ProductCode/FamilyName null is legit — PowerToys is a `burn` installer).
68+
- **Operation + progress paths** (`--comop ajeetdsouza.zoxide`, on COM/JIT — these had NEVER run before):
69+
- `DownloadAsync(zoxide)`**Success**, files actually landed in `%USERPROFILE%\Downloads\winget-tui`
70+
(`zoxide_0.9.9_Arm64_portable_en-US.zip` 480 KB + `.yaml`; COM resolved the **arm64** installer). The
71+
`IProgress<OpProgress>` callback fired (phase **Downloading**, fraction → 1.00) — **the "live progress"
72+
marshaling works on COM** (the old "CCW under AOT" unknown is moot: COM doesn't run under AOT). Cleaned up.
73+
- `RepairAsync(zoxide)`**Success=False**, `Repair failed: RepairError (repairer 0, hr 0x8A15007C)`,
74+
**no crash** — zoxide is a portable .zip with no repairer. NB this is the `RepairError` path, *distinct*
75+
from `NoApplicableRepairer`; the message leaks the raw HRESULT. Possible follow-up: map portable/no-repairer
76+
to the friendly "doesn't support repair." line. The `Verify(Issues) → Repair → Verify` sequence ran e2e.
77+
- `dotnet test -f net10.0`**pass** (18 facts incl. all three P1.5 ports' logic).
78+
79+
**4. Still NOT verified (need a human at the interactive TUI, and/or are destructive):** actual
80+
install/uninstall/upgrade *execution* (download + repair WERE exercised — see item 3); the **status-bar progress
81+
render** + cooperative **Esc cancel**; the dialog/panel *rendering* (install preview, version-picker list,
82+
advanced-install options, Verify→Repair-button flow); the three P1.5 ports' end-to-end terminal *interaction*
83+
(mouse header clicks, `u`/`P`/`/` keypresses); pinning; the P2 thread-agility / unhealthy-source probes.
84+
NOTE: the "live progress under **AOT**" CCW-marshaling item is **moot** — COM doesn't run under AOT; under JIT
85+
(the COM ship vehicle) the callback path is standard and was confirmed via `DownloadAsync`.
86+
87+
**5. Fixes committed (session 3).** Beyond the `ConnectAsync` COM-activation fix, this pass found and fixed,
88+
from a real interactive COM run + the user's feedback:
89+
- **Verify false "Issues"** (`src/ComBackend.cs` `VerifyInstalledAsync`): `CheckInstalledStatus` returns a block
90+
per *manifest installer*; the non-installed ones report "ARP entry not found" (0x8A150201). Old code flattened
91+
all installers and flagged Issues on any failure → healthy multi-installer/portable packages looked corrupt.
92+
Now grouped per installer: **Ok if any one installer's checks all pass**; the dialog shows that clean installer.
93+
- **Narrow-terminal columns** (`src/App.cs`): Name/Id/Version shrink toward minimums so **Available** stays
94+
visible instead of being pushed off-screen; reflows on resize via `ViewportChanged`.
95+
- **Installed-in-Search** (`src/ComBackend.cs` `SearchAsync`, `DetailPanel.cs`, `Models.cs`): search rows read the
96+
composite's correlated `InstalledVersion`; an installed row shows a **✓ Installed** badge and Uninstall/Upgrade
97+
actions instead of a bare Install.
98+
- **Op result through reload** (`src/App.cs` `TriggerRefresh`): the result line ("Done"/…) persists through the
99+
post-op list reload instead of being masked by "Loading Installed…".
100+
- **Bulk-select hint** (`src/Ui.cs`): the Upgrades status bar shows `Spc Select` / `U Upgrade sel`.
101+
102+
The temp `#if WINGET_COM` diagnostics (`--comdiag`/`--comshow`/`--comsmoke`/`--comverify`/`--comop`) were
103+
**removed before commit** (re-add `--comdiag` from the appendix for the AOT activation work). Test dir
104+
`bin\jit-x64-test\` and `bin\…\publish\` are build outputs (gitignored).
105+
106+
---
107+
108+
## (Session 2, 2026-05-29) original headline finding — superseded by session 3 above, kept for history
7109

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

0 commit comments

Comments
 (0)