Codebase Course

The MSIX Identity Crisis

How PowerShell 7.6.0 changed its phone number and Windows Terminal couldn't find it anymore. A deep dive into MSIX packaging, Package Family Names, and what went wrong.

Issue #27064 PowerShell/PowerShell March 2026
Prerequisite

What Even Is an MSIX Package?

You know how when you install an app from the Microsoft Store, it just... works? No "Next → Next → Finish" wizard. That's MSIX — Microsoft's modern app packaging format.

Think of it like a zip file that contains three things:

Every MSIX has a Package Family Name (PFN). It's the identity other apps use to find your app on the system. It looks like this:

Stable Microsoft.PowerShell_8wekyb3d8bbwe
Preview Microsoft.PowerShellPreview_8wekyb3d8bbwe

The format is {IdentityName}_{PublisherIdHash}. The 8wekyb3d8bbwe part is a hash of Microsoft's publisher certificate — same for all Microsoft apps. The first part comes from the <Identity Name="..."> field in the manifest.

Think of the PFN as a phone number in a directory. Other apps look you up by this number. Change it, and nobody can find you.

Chapter 1

How Windows Terminal Finds PowerShell

When you open Windows Terminal, it auto-detects installed PowerShell versions and creates profiles for them. But here's the thing — it does this with hardcoded phone numbers.

microsoft/terminal — PowershellCoreProfileGenerator.cpp

static constexpr std::wstring_view POWERSHELL_PFN{
    L"Microsoft.PowerShell_8wekyb3d8bbwe"
};

static constexpr std::wstring_view POWERSHELL_PREVIEW_PFN{
    L"Microsoft.PowerShellPreview_8wekyb3d8bbwe"
};

Terminal searches for apps with exactly these two PFNs. If it finds one, it creates a profile (that's the entry you see in your Terminal dropdown with source: "Windows.Terminal.PowershellCore"). If it doesn't find a match — no profile.

How Terminal discovers PowerShell
flowchart LR T["Windows Terminal
starts up"] --> Q{"Check PFN
directory"} Q -->|"Microsoft.PowerShell
_8wekyb3d8bbwe"| Y["Profile created"] Q -->|"Microsoft.PowerShellPreview
_8wekyb3d8bbwe"| Y Q -->|"Any other PFN"| N["Not found"] style T fill:#6e8efb22,stroke:#6e8efb,color:#e2e2ea style Q fill:#1c1c26,stroke:#2a2a3a,color:#e2e2ea style Y fill:#4ade8018,stroke:#4ade80,color:#4ade80 style N fill:#f8717118,stroke:#f87171,color:#f87171

Terminal has exactly two contacts saved: "PowerShell" and "PowerShell Preview." It calls those numbers every time it starts. If nobody picks up at those numbers, Terminal assumes PowerShell isn't installed.

Chapter 2

What Broke in 7.6.0

PowerShell 7.6.0 was special. It was the first release that's both the current Stable release AND an LTS (Long-Term Support) release simultaneously. Previous LTS releases (7.2, 7.4) were always separate from the "latest" track.

The build pipeline reads a config file called tools/metadata.json:

tools/metadata.json (at build time)

{
  "LTSRelease":    { "Package": true  },  // ← build LTS MSIX
  "StableRelease": { "Package": true  }   // ← build Stable MSIX
}

When LTSRelease.Package is true, the pipeline passes -LTS to the MSIX builder function. That function has this logic:

tools/packaging/packaging.psm1 — New-MSIXPackage

if ($LTS) {
    $ProductName += '-LTS'   # "PowerShell" → "PowerShell-LTS"
}

This changes the identity baked into the manifest:

<Identity Name="Microsoft.PowerShell-LTS" ... />

Which produces the PFN:

LTS Microsoft.PowerShell-LTS_8wekyb3d8bbwe

Terminal doesn't have this number saved. It calls Microsoft.PowerShell_8wekyb3d8bbwe — nobody answers. PowerShell disappears from Terminal.

It's exactly like if your phone company changed your number from 555-1234 to 555-1234-LTS and didn't tell anyone who had your old number saved.

The identity mismatch
flowchart TB subgraph BUILD ["Build Pipeline"] M["metadata.json
LTSRelease.Package = true"] --> F["New-MSIXPackage -LTS"] F --> ID["Identity Name:
Microsoft.PowerShell-LTS"] end subgraph INSTALL ["Installed Package"] ID --> PFN["PFN: Microsoft.PowerShell-LTS_8wekyb3d8bbwe"] end subgraph TERMINAL ["Windows Terminal"] T1["Looking for:
Microsoft.PowerShell_8wekyb3d8bbwe"] T2["Looking for:
Microsoft.PowerShellPreview_8wekyb3d8bbwe"] end PFN -.- |"does NOT match"| T1 PFN -.- |"does NOT match"| T2 style BUILD fill:#1c1c26,stroke:#2a2a3a,color:#e2e2ea style INSTALL fill:#f8717118,stroke:#f87171,color:#e2e2ea style TERMINAL fill:#1c1c26,stroke:#2a2a3a,color:#e2e2ea style M fill:#22222e,stroke:#2a2a3a,color:#e2e2ea style F fill:#22222e,stroke:#2a2a3a,color:#e2e2ea style ID fill:#22222e,stroke:#f87171,color:#f87171 style PFN fill:#f8717133,stroke:#f87171,color:#f87171 style T1 fill:#22222e,stroke:#4ade80,color:#4ade80 style T2 fill:#22222e,stroke:#4ade80,color:#4ade80
Chapter 3

The Fix (PR #27056)

The fix was elegant: build TWO MSIX packages when a release is both LTS and Stable.

Before (7.6.0 release day)

One call to New-MSIXPackage -LTS

Produces:
  PowerShell-LTS-7.6.0.msix
  Identity: Microsoft.PowerShell-LTS

Terminal: "Who?"

After (the fix)

Two calls to New-MSIXPackage

Produces:
  PowerShell-7.6.0.msix (stable)
  PowerShell-LTS-7.6.0.msix (lts)

Terminal: "Found you!"

The pipeline logic now forks when both flags are true:

.pipelines/templates/packaging/windows/package.yml

$LTS    = $metadata.LTSRelease.Package
$Stable = $metadata.StableRelease.Package

# Build LTS package (with -LTS identity)
Start-PSPackage -Type msix -LTS:$LTS

# NEW: When both LTS + Stable, build a second MSIX with stable identity
if ($LTS -and $Stable) {
    Start-PSPackage -Type msix  # no -LTS → "Microsoft.PowerShell"
}

These get bundled into two separate .msixbundle files:

Stable PowerShell-7.6.0.msixbundle → Microsoft.PowerShell_8wekyb3d8bbwe
LTS PowerShell-LTS-7.6.0.msixbundle → Microsoft.PowerShell-LTS_8wekyb3d8bbwe

Now users who install the Stable bundle get the PFN that Terminal knows. Users who install the LTS bundle get a separate Store listing — but Terminal won't auto-detect it because it still only knows two PFNs.

The full packaging pipeline (post-fix)
flowchart TB META["tools/metadata.json
LTS: true, Stable: true"] --> PKG["package.yml"] PKG --> C1["Call 1: New-MSIXPackage -LTS"] PKG --> C2["Call 2: New-MSIXPackage (no -LTS)"] C1 --> M1["PowerShell-LTS-7.6.0-win-x64.msix"] C1 --> M2["PowerShell-LTS-7.6.0-win-arm64.msix"] C2 --> M3["PowerShell-7.6.0-win-x64.msix"] C2 --> M4["PowerShell-7.6.0-win-arm64.msix"] M1 & M2 --> B1["PowerShell-LTS-7.6.0.msixbundle"] M3 & M4 --> B2["PowerShell-7.6.0.msixbundle"] B1 --> STORE1["Store: LTS listing"] B2 --> STORE2["Store: Stable listing"] B2 --> TERM["Terminal finds it"] style META fill:#6e8efb22,stroke:#6e8efb,color:#e2e2ea style PKG fill:#22222e,stroke:#2a2a3a,color:#e2e2ea style C1 fill:#22222e,stroke:#fb923c,color:#fb923c style C2 fill:#22222e,stroke:#4ade80,color:#4ade80 style M1 fill:#1c1c26,stroke:#2a2a3a,color:#8888a0 style M2 fill:#1c1c26,stroke:#2a2a3a,color:#8888a0 style M3 fill:#1c1c26,stroke:#2a2a3a,color:#8888a0 style M4 fill:#1c1c26,stroke:#2a2a3a,color:#8888a0 style B1 fill:#fb923c18,stroke:#fb923c,color:#fb923c style B2 fill:#4ade8018,stroke:#4ade80,color:#4ade80 style STORE1 fill:#1c1c26,stroke:#2a2a3a,color:#8888a0 style STORE2 fill:#1c1c26,stroke:#2a2a3a,color:#8888a0 style TERM fill:#4ade8018,stroke:#4ade80,color:#4ade80
Chapter 4

The Remaining Gaps (What no-identd Is Saying)

The original symptom — Terminal can't find PowerShell — was fixed by PR #27056. But no-identd looked deeper and found four more problems that are all consequences of the LTS/Stable split being rushed out the door.

Issue 1

The LTS Download Link Is Stale

aka.ms/powershell-release?tag=lts still points to v7.4.14 (the previous LTS). Someone forgot to update the redirect config for 7.6.0.

High Impact
Issue 2

No LTS MSI Installer

Enterprises need MSI for Group Policy / SCCM / Intune deployments. LTS packages exist for Linux & macOS but no LTS-branded MSI for Windows.

Medium Impact
Issue 3

Windows Update Catalog Issues

PowerShell via Windows Update / WSUS has a long history of breaking. 7.2 LTS stopped appearing after v7.2.19. 7.4 LTS took months. Now 7.6.0 might be stuck too.

Medium Impact
Issue 4

x86 Builds Silently Dropped

Hashes file referenced x86 artifacts, but actual binaries were missing. Resolution: hashes removed instead of binaries added. No deprecation notice issued.

Lower Impact

And Then There's the Terminal PFN Gap

Even after the fix, there's a downstream problem: users who intentionally install the LTS-identity package still won't get a Terminal profile, because Terminal only knows two PFNs.

The fix would be adding a third PFN constant to Terminal's source:

PowershellCoreProfileGenerator.cpp (proposed addition)

static constexpr std::wstring_view POWERSHELL_PFN{
    L"Microsoft.PowerShell_8wekyb3d8bbwe"
};

static constexpr std::wstring_view POWERSHELL_PREVIEW_PFN{
    L"Microsoft.PowerShellPreview_8wekyb3d8bbwe"
};

static constexpr std::wstring_view POWERSHELL_LTS_PFN{
    L"Microsoft.PowerShell-LTS_8wekyb3d8bbwe"
};

This is what no-identd asked you to do: File an issue on microsoft/terminal requesting they add the LTS PFN to their discovery logic. It's a clear, well-scoped fix — about 3 lines of C++ — and it gets your name visible in the Terminal repo, not just PowerShell.

Chapter 5

Timeline of Events

March 18, 2026

v7.6.0 released. Pipeline built only LTS-identity MSIX. Terminal profiles break for Store/MSIX users.

March 19, 2026

PR #27056 merged. Dual MSIX build infrastructure added. Backported same day via #27069 and #27071.

March 20, 2026

PR #27077 merged. PhoneProductId corrected for LTS Store listing. Updated release assets now include both bundles.

March 22, 2026

Issue #27064 filed. User reports broken Terminal profile. Root cause already fixed but release assets not yet widespread.

March 27, 2026

no-identd's comment. Consolidates remaining issues: stale aka.ms redirect, missing LTS MSI, x86 dropped silently, no docs about the MSIX split.

March 28, 2026

Issue #27064 closed. Original symptom (Terminal profile) resolved. Remaining gaps tracked as separate concerns.

Chapter 6

Your Move

no-identd mentioned you because your earlier analysis on #27064 traced the root cause chain accurately. They're asking you to file an issue on microsoft/terminal requesting Terminal add the LTS PFN to its PowerShell discovery logic.

Why This Is a Great Opportunity

The full picture — what's fixed vs. what's left
flowchart LR A["metadata.json
LTS + Stable"] --> B["Build pipeline
creates 2 MSIXs"] B --> C["Stable PFN"] B --> D["LTS PFN"] C --> E["Terminal knows"] D --> F["Terminal doesn't
know"] F --> G["YOUR ISSUE:
Add LTS PFN
to Terminal"] style A fill:#4ade8018,stroke:#4ade80,color:#4ade80 style B fill:#4ade8018,stroke:#4ade80,color:#4ade80 style C fill:#4ade8018,stroke:#4ade80,color:#4ade80 style D fill:#fb923c18,stroke:#fb923c,color:#fb923c style E fill:#4ade8018,stroke:#4ade80,color:#4ade80 style F fill:#f8717118,stroke:#f87171,color:#f87171 style G fill:#fbbf2418,stroke:#fbbf24,color:#fbbf24