Skip to content

Specification: UserMessages manifest field#6201

Open
denelon wants to merge 2 commits intomicrosoft:masterfrom
denelon:denelon/user-messages-spec
Open

Specification: UserMessages manifest field#6201
denelon wants to merge 2 commits intomicrosoft:masterfrom
denelon:denelon/user-messages-spec

Conversation

@denelon
Copy link
Copy Markdown
Collaborator

@denelon denelon commented May 3, 2026

📖 Description

Adds the full specification for the UserMessages manifest field, covering how messages are shown during install, upgrade, uninstall, and download flows. The spec includes the flow behavior matrix, CLI arguments, settings, PowerShell cmdlet integration, and an update to doc/specs/spec-template.md.

Created with GitHub Copilot assistance.

🔗 References

Resolves #3483

🔍 Validation

  • Specification content reviewed by Trenly.

✅ Checklist

📋 Issue Type

  • Bug fix
  • Feature
  • Task

@microsoft-github-policy-service microsoft-github-policy-service Bot added the Issue-Feature This is a feature request for the Windows Package Manager client. label May 3, 2026
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

Comment thread doc/specs/#3483 - UserMessages.md Outdated
Comment thread doc/specs/#3483 - UserMessages.md Outdated
Comment thread .github/instructions/specs.instructions.md Outdated
@github-actions

This comment has been minimized.

@denelon denelon marked this pull request as ready for review May 3, 2026 21:33
@denelon denelon requested a review from a team as a code owner May 3, 2026 21:33
@Trenly Trenly force-pushed the denelon/user-messages-spec branch from 9b713bc to 77b3d97 Compare May 3, 2026 23:58
Add specification for UserMessages manifest field (microsoft#3483). Includes:
- New UserMessages manifest field for displaying messages to users
- Flow behavior matrix for install, upgrade, uninstall, and download
- CLI arguments for UserMessages settings overrides
- Settings object for global UserMessages configuration
- PowerShell cmdlet integration details
- Deprecation path and schema impact guidance

Also updates spec-template.md with Deprecation Path section and
settings/arguments guidance.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@denelon denelon force-pushed the denelon/user-messages-spec branch from 77b3d97 to 8c80355 Compare May 4, 2026 03:19
@denelon denelon removed the Issue-Feature This is a feature request for the Windows Package Manager client. label May 4, 2026
@microsoft-github-policy-service microsoft-github-policy-service Bot added the Issue-Feature This is a feature request for the Windows Package Manager client. label May 4, 2026
@denelon denelon removed the Issue-Feature This is a feature request for the Windows Package Manager client. label May 4, 2026
@microsoft-github-policy-service microsoft-github-policy-service Bot added the Issue-Feature This is a feature request for the Windows Package Manager client. label May 4, 2026
Comment thread doc/specs/#3483 - UserMessages.md
Comment thread doc/specs/#3483 - UserMessages.md
Comment thread doc/specs/#3483 - UserMessages.md Outdated
Comment thread doc/specs/#3483 - UserMessages.md Outdated
Comment thread doc/specs/#3483 - UserMessages.md
Comment thread doc/specs/#3483 - UserMessages.md Outdated
Comment thread doc/specs/#3483 - UserMessages.md Outdated
Comment thread doc/specs/#3483 - UserMessages.md
Comment thread doc/specs/#3483 - UserMessages.md Outdated
Comment thread doc/specs/#3483 - UserMessages.md Outdated
Comment thread doc/specs/#3483 - UserMessages.md
Comment thread doc/specs/#3483 - UserMessages.md Outdated
Comment thread doc/specs/#3483 - UserMessages.md Outdated
Comment thread doc/specs/#3483 - UserMessages.md Outdated
denelon added a commit that referenced this pull request May 4, 2026
## 📖 Description
Adds `.github/instructions/specs.instructions.md` for specification
authoring guidance and updates `.github/copilot-instructions.md` to
reference it. This was split from #6201 to keep the specification
content separate from tooling guidance.

Created with GitHub Copilot assistance.

## 🔗 References
Resolves #6204

## 🔍 Validation
- Reviewed the instruction content and the related Copilot instruction
update.

## ✅ Checklist
- [x] Signed the [Contributor License
Agreement](https://cla.opensource.microsoft.com)
- [x] Linked to an issue
- [ ] Updated [Release Notes](../doc/ReleaseNotes.md) (if applicable)
- [x] Updated documentation (if applicable)
- [x] Updated [Copilot instructions](.github/copilot-instructions.md)
(if build, architecture, or conventions changed)

## 📋 Issue Type
- [ ] Bug fix
- [x] Feature
- [ ] Task

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add PreRepair/PostRepair dedicated fields (8 fields total)
- Nest settings under userExperience section
- Add --show-user-messages CLI override
- Standardize table language (Displayed/Suppressed/Prompted)
- Clarify no cross-field fallback between operations
- Define uninstall message sourcing (target → latest → none)
- Schema versions align with client versions
- may → should for backward compat guidance
- Add automation impact callout
- Remove --silent from behavior matrix
- Bulk operations present pre-messages upfront
- Simplify interaction table
- COM API section goes vague
- Add consideration for exposing settings via COM
- Replace Show-WinGetPackage with Find-WinGetPackage
- Add locale translation validation note
- Remove rendering validation item
- disableInstallNotes also suppresses PostInstall

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

github-actions Bot commented May 6, 2026

@check-spelling-bot Report

🔴 Please review

See the 📂 files view, the 📜action log, or 📝 job summary for details.

Unrecognized words (2)

sourced
sourcing

These words are not needed and should be removed AAD ABCD abi ACL'd AMap Amd appdata ARMNT asan Baz bitmask bluetooth boundparms brk Buf certs cgi CMSG codepage commandline constexpr Cov cswinrt CTL Dbg Dcom decompressor dedupe DEFT devhome Dns dsc ERANGE errcode errmsg errstr filemode Finalizers FULLWIDTH fuzzer GES github Hackathon HINSTANCE hlocal hmac Hyperlink ICONDIR icu idx img inet Intelli iwr JDK LCID lhs LONGLONG LPBYTE LPCWSTR LPDWORD LPSTR LPVOID LPWSTR MAJORVERSION MAXLENGTH maxvalue MDs MINORVERSION mta nlohmann NONAME NOUPDATE NTFS ofile oid oop OPTOUT outfile OUTOFMEMORY PARAMETERMAP pdb PDWORD pid PKCS pkix placeholders positionals posix pscustomobject pseudocode PSHOST publickey qword redirector regexes remoting reparse REQS rhs rowid RTTI runspace runtimes SARL savepoint Scm sid sqlite subdir subkey trimstart ttl typedef uninitialize uninstallation UNMARSHALING userprofile versioned Webserver website wildcards winreg workaround Wpp wsl

To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the git@github.com:denelon/winget-cli.git repository
on the denelon/user-messages-spec branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/v0.0.26/apply.pl' |
perl - 'https://github.com/microsoft/winget-cli/actions/runs/25450249340/attempts/1' &&
git commit -m 'Update check-spelling metadata'
If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

For uninstall operations, `PreUninstall` and `PostUninstall` are sourced as follows:

- If the package is correlated to a specific installed version, use that version's manifest messages.
- If the package is correlated but no target version manifest exists, use the latest available version's messages.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could we try to find what the "closest" version is instead of using the latest?
For example, if the user has v1.2 and we have manifests for v1.1 and v2.0, the notes from v1.1 are probably more relevant.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Closest in your example is tough to say, maybe the thing worth mentioning was introduced in 1.2 and continues in 2.0. But similarly, maybe it existed in 1.*, but 2.0 fixes it. Tough call.

| WinGet Configuration (DSC) | Displayed in log output, no prompt | Displayed in log output | Configuration is inherently non-interactive |
| `winget install` | `PreInstall` Displayed; Prompted (Y/n) | `PostInstall` Displayed | Standard single-package install |
| `winget upgrade <package>` | `PreUpgrade` Displayed; Prompted (Y/n) | `PostUpgrade` Displayed | Single-package upgrade |
| `winget upgrade --all` | All `PreUpgrade` messages Displayed together; Prompted (Y/n) once | Each `PostUpgrade` Displayed | See "Bulk Operations" below |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I assume "All messages displayed together, prompted once" also applies to other commands when passing multiple packages, like winget install app1 app2?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would also assume that all bulk operations behave the same. We probably want an additional message in bulk operations (maybe operation dependent) that indicates how the user should move forward if they want to opt-out of a single of the package operations (install -> remove from list, upgrade -> pin the package, etc.).

Comment on lines +191 to +194
| `--show-user-messages` | `Pre*` Displayed; Prompted (Y/n) in interactive mode | `Post*` Displayed | Overrides settings that suppress messages for this invocation |
| `--ignore-user-messages` | Suppressed; Prompt Suppressed | `Post*` Suppressed | CLI argument overrides settings for this invocation |
| `--ignore-pre-action-messages` | Suppressed; Prompt Suppressed | `Post*` Displayed | CLI argument overrides `userExperience.userMessages.disablePreActionMessages` |
| `--ignore-post-action-messages` | `Pre*` Displayed | `Post*` Suppressed | CLI argument overrides `userExperience.userMessages.disablePostActionMessages` |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have global show/ignore options, and ignore options for pre/post messages. Why not show option for pre/post?

| `--ignore-post-action-messages` | `Pre*` Displayed | `Post*` Suppressed | CLI argument overrides `userExperience.userMessages.disablePostActionMessages` |
| `winget validate` | Suppressed | Suppressed | Validation checks schema correctness only; messages are not rendered |

#### Bulk Operations (`upgrade --all`, `import`)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

install, upgrade, etc also have bulk operations

Comment on lines +191 to +194
| `--show-user-messages` | `Pre*` Displayed; Prompted (Y/n) in interactive mode | `Post*` Displayed | Overrides settings that suppress messages for this invocation |
| `--ignore-user-messages` | Suppressed; Prompt Suppressed | `Post*` Suppressed | CLI argument overrides settings for this invocation |
| `--ignore-pre-action-messages` | Suppressed; Prompt Suppressed | `Post*` Displayed | CLI argument overrides `userExperience.userMessages.disablePreActionMessages` |
| `--ignore-post-action-messages` | `Pre*` Displayed | `Post*` Suppressed | CLI argument overrides `userExperience.userMessages.disablePostActionMessages` |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I assume we have some rules about mutual exclusivity for these?

Comment on lines 375 to +377
#### `winget repair`

The `repair` command reuses `PreInstall` and `PostInstall` messages. The behavior is identical to `install` — pre-message with prompt in interactive mode, post-message after success.
The `repair` command uses the dedicated `PreRepair` and `PostRepair` fields. Its behavior mirrors the other operation-specific flows — pre-message with prompt in interactive mode, post-message after success.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This could be removed since it is covered already

3. **Transition-period duplication.** During the transition, manifest authors must duplicate their install note in both `InstallationNotes` and `UserMessages.PostInstall`. This is a known trade-off for backward compatibility and is temporary.

4. **Content moderation burden.** The winget-pkgs community reviewers now have six new fields to review per manifest. Automated tooling to flag suspicious content in these fields would reduce this burden.
4. **Content moderation burden.** The winget-pkgs community reviewers now have eight new fields to review per manifest. Automated tooling to flag suspicious content in these fields would reduce this burden.
Copy link
Copy Markdown
Member

@florelis florelis May 6, 2026

Choose a reason for hiding this comment

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

Maybe we could have a special value that means "reuse the install message". For example, if the message is to alert the user that the installer will reboot the device, it would be the same for install/upgrade/repair and manifest authors shouldn't need to repeat it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Or change the design from object to array with usage:

UserMessages:
  - Use: [PreInstall, PreUpgrade, PreRepair]
    Message: PreMessage
  - Use: [PostInstall, PostUpgrade, PostRepair]
    Message: PostMessage

Obviously this has an easier time of creating use overlap, but validation can easily catch that and local use can ignore the conflicts if present.

Comment on lines +192 to +193
| `--ignore-user-messages` | Suppressed; Prompt Suppressed | `Post*` Suppressed | CLI argument overrides settings for this invocation |
| `--ignore-pre-action-messages` | Suppressed; Prompt Suppressed | `Post*` Displayed | CLI argument overrides `userExperience.userMessages.disablePreActionMessages` |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: It feels like we are giving the messages two names - "action messages" and "user messages" and that may be confusing.

Comment on lines +192 to +193
| `--ignore-user-messages` | Suppressed; Prompt Suppressed | `Post*` Suppressed | CLI argument overrides settings for this invocation |
| `--ignore-pre-action-messages` | Suppressed; Prompt Suppressed | `Post*` Displayed | CLI argument overrides `userExperience.userMessages.disablePreActionMessages` |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nit: Maybe use "hide", "suppress" or "disable" instead of "ignore"? To me "ignore" doesn't necessarily mean that it won't be shown, just that it won't affect anything. Same as if we disable interactivity for pre* messages

| `userExperience.userMessages.disablePostActionMessages` enabled | `Pre*` Displayed | `Post*` Suppressed | New setting for new fields |
| `userExperience.userMessages.disablePreActionMessages` enabled | Suppressed; Prompt Suppressed | `Post*` Displayed | Suppresses both display and prompt |
| `--show-user-messages` | `Pre*` Displayed; Prompted (Y/n) in interactive mode | `Post*` Displayed | Overrides settings that suppress messages for this invocation |
| `--ignore-user-messages` | Suppressed; Prompt Suppressed | `Post*` Suppressed | CLI argument overrides settings for this invocation |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This sounds like it will suppress all output from winget. It may be good to have that since people have asked for it, but it may be confusing if ignoring "user messages" only includes "pre/post action messages"

For uninstall operations, `PreUninstall` and `PostUninstall` are sourced as follows:

- If the package is correlated to a specific installed version, use that version's manifest messages.
- If the package is correlated but no target version manifest exists, use the latest available version's messages.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Closest in your example is tough to say, maybe the thing worth mentioning was introduced in 1.2 and continues in 2.0. But similarly, maybe it existed in 1.*, but 2.0 fixes it. Tough call.


- If the package is correlated to a specific installed version, use that version's manifest messages.
- If the package is correlated but no target version manifest exists, use the latest available version's messages.
- If the package is not correlated (for example, it was not installed through WinGet), no uninstall message is displayed.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So no request to store the manifest/uninstall messages and display them if the version remains unchanged.

| WinGet Configuration (DSC) | Displayed in log output, no prompt | Displayed in log output | Configuration is inherently non-interactive |
| `winget install` | `PreInstall` Displayed; Prompted (Y/n) | `PostInstall` Displayed | Standard single-package install |
| `winget upgrade <package>` | `PreUpgrade` Displayed; Prompted (Y/n) | `PostUpgrade` Displayed | Single-package upgrade |
| `winget upgrade --all` | All `PreUpgrade` messages Displayed together; Prompted (Y/n) once | Each `PostUpgrade` Displayed | See "Bulk Operations" below |
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I would also assume that all bulk operations behave the same. We probably want an additional message in bulk operations (maybe operation dependent) that indicates how the user should move forward if they want to opt-out of a single of the package operations (install -> remove from list, upgrade -> pin the package, etc.).

3. **Transition-period duplication.** During the transition, manifest authors must duplicate their install note in both `InstallationNotes` and `UserMessages.PostInstall`. This is a known trade-off for backward compatibility and is temporary.

4. **Content moderation burden.** The winget-pkgs community reviewers now have six new fields to review per manifest. Automated tooling to flag suspicious content in these fields would reduce this burden.
4. **Content moderation burden.** The winget-pkgs community reviewers now have eight new fields to review per manifest. Automated tooling to flag suspicious content in these fields would reduce this burden.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Or change the design from object to array with usage:

UserMessages:
  - Use: [PreInstall, PreUpgrade, PreRepair]
    Message: PreMessage
  - Use: [PostInstall, PostUpgrade, PostRepair]
    Message: PostMessage

Obviously this has an easier time of creating use overlap, but validation can easily catch that and local use can ignore the conflicts if present.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Issue-Feature This is a feature request for the Windows Package Manager client.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make InstallationNotes flow-dependent

4 participants