Patch Management

Overview

ET Ducky's Patch Management keeps the operating system and third-party applications current across your entire Windows and Linux fleet from a single policy engine. It covers the OS, the application catalog, and everything in between — winget and Windows Update on Windows; apt, dnf, zypper, snap, and flatpak on Linux; and vendor patch scripts for anything a package manager can't reach. The same policies, rings, and maintenance windows drive OS updates and app updates alike, so you configure intent once and let the agent execute it.

Patches are verified, not just installed

A clean installer exit code does not guarantee a healthy machine: a patch can report success and still leave a service stopped, send the patched application into a crash loop, or shift CPU, memory, or disk baselines. After each install, the agent uses the same kernel event stream it already runs for monitoring to check the host — whether critical services came back up, whether the patched application is crash-looping, whether resource baselines deviated, and whether any behavioral rule fired. Rollout gates consume those signals, so a patch is treated as successful only once the host is verifiably healthy afterward, not simply because the installer exited 0.

Tip: Before relying on automated rollout in production, validate your verification gate on a canary ring — deploy a patch you know breaks a service and confirm the wave pauses, the job is marked regressed, and the root-cause analysis identifying the failed service is attached.

Where to find it

Patch Management lives under Systems → Patch Management. The fleet summary stays pinned at the top, and the rest of the page is organized into four tabs so you're not scrolling one long column:

  • Updates — available updates across the fleet, per-agent patch status, and recent patch events. The day-to-day view.
  • Configuration — patch policies, rings and rollout waves, and the guided Set up patching flow.
  • Software Catalog — operator-curated entries for apps no package manager tracks, each with Draft update script.
  • Network — the Distribution Hub network-requirements / egress-allowlist card.

The approved / unapproved application lists (including the Available Managers column and Migrate to winget) are a separate card under Systems — see Approved Applications. Drafted vendor patch scripts are reviewed and approved under Integrations → Script Repositories in the built-in Patch Management repo.

The Staged Rollout Model

Patch Management ships as one deployment but turns on in ordered phases. Each phase has its own flag, and each flag is independently reversible — turning a flag off is the rollback for that phase. The phases build on each other from read-only visibility up to AI-assisted regression analysis. Understanding the phases helps you reason about exactly how much automation is active in your environment at any moment.

PhaseWhat it turns on
ScanRead-only visibility. Agents scan for available updates (winget / Windows Update / apt / dnf / zypper / snap / flatpak) and report them; the inventory diff records an application-change ledger (installed / removed / version-changed). You see what's available under Systems → Patch Management but nothing is installed. On by default.
ExecuteManual approve-and-install. You (or an auto mode, once enabled) approve a specific update; the agent installs it inside the maintenance window and reports a transcript-grade result. This is the authoritative kill switch — while it is off, no agent installs anything, even one configured to.
AutoPolicy automation. The server's evaluation loop resolves each agent's policy and auto-approves updates by classification, age (deferral), and exclusions/holds — no per-patch clicking. Vendor patch scripts become available as jobs here.
RingsStaged rollout plus post-patch verification. A version moves through ordered rings (canary → broad), promoted only after a soak period and a clean verification verdict. Regressions auto-pause the wave.
AIRegressed patches are persisted as incidents and fed into the troubleshooting and historical-analysis pipeline, so the AI knows "this KB broke the print spooler on this fleet last month."
HubCacheLAN-local installer caching. On multi-endpoint sites, an installer is staged once to a Distribution Hub and every agent fetches it locally (SHA-256 verified, pinned hub certificate) instead of each downloading from the internet.

Scan + Execute is the credible minimum. Many MSPs run there and approve manually. Rings is where the kernel-verified rollout story lands — turn it on after you've soaked the verification gate against a known-bad patch in a lab.

Patch Policies

A patch policy is the intent you express once and apply to many agents. An organization can have several policies; each agent resolves to exactly one. A policy is created disabled and carries the following settings.

OS update mode

  • manual — OS updates are scanned and surfaced but never installed without an explicit approval.
  • security_auto — updates classified as security/critical are auto-approved (subject to deferral); feature updates still require a human.
  • all_auto — every available OS update is auto-approved subject to the policy's deferral and exclusions.

App update mode

  • manual — application updates are surfaced but require approval.
  • policy_auto — application updates are auto-approved per the policy (again subject to deferral and exclusions).

Deferral — AutoApproveAfterDays

The deferral window is your safety buffer against bad vendor releases. An update is held for the configured number of days after it is first seen before an auto mode approves it — for example, "auto-approve security updates 3 days after publish." If a vendor pulls a broken patch within those days, you never installed it. Manual approval always bypasses the deferral clock.

Reboot policy

  • never — the agent never reboots on its own; an install that requires a reboot parks at awaiting_reboot and surfaces a badge for a human to action.
  • window_only — a required reboot happens only inside the maintenance window. The agent re-checks the window is still open at the moment it would reboot (a long install can outlast the window); if it closed mid-install, the job stays awaiting_reboot until the next cycle rather than rebooting late.
  • immediate_if_required — the host reboots as soon as an install reports a reboot is required, regardless of window.

When the agent does reboot, it does so once per batch (not once per patch) and gives any logged-on user a 5-minute warned grace period — a “this computer will restart in 5 minutes, please save your work” message — before the restart. (Reboot is performed by the agent, so a host on an agent build that predates reboot support will install but not auto-restart until it's updated.)

Maintenance windows

Maintenance windows define when work is allowed to dispatch and install. Each window is a set of days, a start time, and a duration in minutes — for example, days:[2], start:"02:00", durationMin:240 for a four-hour window beginning Tuesday at 02:00. The start time is interpreted in each agent's own local timezone (reported by the agent's OS), so “Tuesday 02:00” means 2 AM wherever each machine actually is — the right behavior for a fleet spread across regions. Agents whose timezone hasn't been reported yet fall back to UTC. Windows are midnight-wrap aware. Approved jobs sit as scheduled until the agent's local window opens.

Exclusions and holds

Exclusions pin or hold specific packages out of patching — a list of package keys, each with a reason and an optional "until" date. A held package is skipped by the policy evaluator even in an auto mode, so you can freeze a known-problematic application or a version your line-of-business software depends on, while everything else keeps flowing.

Holds are currently enforced server-side — the evaluator skips held packages. Pushing the hold down to the host (so a local admin sees apt-mark hold / dnf versionlock locally) is a planned follow-up.

How an Agent Resolves to a Policy

Policy assignment is deliberately simple and predictable: a tag assignment wins over the organization default.

  • A policy can be marked org default. Every agent that is not otherwise assigned falls under it.
  • A policy can be assigned to an agent tag. Any agent carrying that tag resolves to that policy instead of the default.

So to put a group of machines on a different patch cadence, you tag them and assign a policy to that tag — no per-agent configuration. An agent always resolves to exactly one policy: its tag-assigned policy if it has one, otherwise the org default.

Rings, Rollout Waves, and Promotion

Rings turn a single approved version into a controlled, staged rollout instead of a fleet-wide blast.

Rings are agent tags

A ring is a tag. Ring 0 is typically a canary tag (a handful of low-risk machines), and later rings are progressively broader. Because rings are just tags, all of your existing tag tooling — bulk assign, filters, saved selections — is the ring-management UI. Each ring within a policy has an order, a soak period, an auto-promote flag, and a verification gate.

Rollout waves

When a new version of a package needs to roll out, it travels through the policy's rings as a rollout wave. The wave tracks which ring it's currently in and keeps per-ring success/fail/regress counts so you can watch progress on a single row.

Starting a rollout

Start rollout kicks off a wave on demand: pick the policy, the source (winget, a Linux package manager, or a vendor script), the package key, and an optional target version (blank = latest). The package-key field has a type-ahead — start typing an app name and it suggests matching apps from your Approved Applications, resolving the friendly name to the real source key (for example 7-Zip7zip.7zip) and offering a dropdown of the versions your fleet's scans report as available. It creates the ring-0 (canary) jobs immediately, then promotes through the rings per the rules below.

Promotion

A wave is promoted from ring N to ring N+1 only when all of the following hold:

  • the ring's soak hours have elapsed (minimum time the version must bake in the current ring), and
  • the verification verdicts in the current ring satisfy the ring's gate (see below), and
  • either the ring is set to auto-promote, or a human clicks Promote.

This is the concrete meaning of "more automation than other RMMs": auto-approval by classification and age rather than per-patch clicking, and auto-progression through rings gated on kernel-verified health rather than timers alone.

Auto-pause on regression

Any regressed verdict in the current ring pauses the entire wave (state paused_regression) and fires a notification with the evidence attached — which service died, which baseline deviated, and the bracketed kernel events. The wave stops spreading until a human reviews it. This is the safety net that makes broad rings safe to automate.

Post-Patch Verification Gates

Every ring carries a verification gate that decides how thoroughly the agent checks the host after an install before marking the patch successful. The gate is what turns "the installer exited 0" into "the machine is verifiably healthy," and it determines whether the wave is allowed to promote to the next ring.

Gate levels

  • none — exit code only. Signals are still recorded, but the verdict is based solely on whether the installer succeeded.
  • basic (default) — for a verification window after the install (and any reboot), the agent confirms it heartbeats healthy, that there is no critical-service-down in heartbeat status, that the patched package's processes are not crash-looping (matched against the package's binaries via kernel process-exit events), and that no behavioral detection fired.
  • full — everything in basic plus no new performance inflection (a spike or sustained deviation) attributable to the patch window. On any deviation, the root-cause-analysis path runs and attaches an AI explanation to the job — for example, "CPU sustained +40% after the Chrome update; the spike brackets to GPU-process restarts." That text rides along in the auto-pause notification.

Signals each gate consumes

Depending on the level, verification draws on: heartbeat critical-service status, crash-loop detection (kernel process-exit events for the patched binaries), behavioral detections, performance inflections (spike / drop / sustained), and baseline deviation. These are the same kernel-level signals ET Ducky already collects for diagnostics — patch verification simply reads them in the post-install window.

Verdicts

  • verified — the host is healthy in the verification window; the job succeeds and the wave is eligible to promote.
  • regressed — a signal indicates the patch broke something. The job is not counted as succeeded, the wave is paused, and the incident feeds the AI history pipeline.
  • inconclusive — the agent went offline before the verification window elapsed. This counts as neither verified nor regressed for promotion and is flagged for review.

Rollback

On a regression, where the package manager supports a downgrade the agent can auto-rollback (for example, a winget --version pin back to the prior version). Where a clean downgrade isn't possible, the job is moved to an explicit manual-rollback-required state rather than pretending it rolled back — honesty over theater. You are never left guessing whether the previous version was actually restored.

Vendor Patch Scripts

Package managers cover most software, but not everything — some applications ship their own updaters, or need an installer flag, or live entirely outside any catalog. For those, ET Ducky uses vendor patch scripts: an approved script that performs the update, tied to a package key.

  • Approval-gated. A vendor patch script runs through the same command-validation and approval flow as any other script — risk scoring, hard-block checks, and an explicit approval status — before it can ever execute as a patch job.
  • Shareable. Vendor scripts are the sharing surface for patching. An MSP vets an updater once and promotes it to the whole workspace, exactly like a shared KB article or runbook, so every tenant benefits from the vetting done once.
  • Same execution path. A vendor-script patch job reuses the hub-backed script-fetch path end-to-end, so it benefits from LAN caching and integrity checks like any other script.

Vendor scripts also cover rollback where a package manager can't downgrade, and they are the intended mechanism for bootstrapping winget itself onto Windows Server SKUs that lack the App Installer.

Software Catalog

Some applications aren't tracked by any package manager — no winget, apt, dnf, or other line item exists for them. The Software Catalog is an operator-curated list of those apps, so ET Ducky can still know each one's current latest version and how to install it. The catalog lives under Systems → Patch Management on the Software Catalog tab, where admins can add, edit, and delete entries.

What a catalog entry records

FieldPurpose
Name (required)The application name, matched case-insensitively against the name agents report in inventory.
Latest version (required)The current shipping version. Version enrichment (below) compares each agent's installed version against this.
PublisherOptional vendor label.
Download URLWhere the installer is fetched from. Drives the deterministic update-script template (see below).
SHA-256Expected hash of the installer, for integrity verification.
Silent-install argsThe flags that make the installer run unattended — for example /S or /quiet.
Platformany, windows, or linux.
NotesFree-text for your own reference.

Name and latest version are the minimum. The download URL, SHA-256, and silent-install args are what make a fully deterministic update script possible — without them, drafting falls back to AI (see Drafting an update script).

Filling the form with AI (“Suggest with AI”)

The Set up patching dialog has a Suggest with AI button that pre-fills the latest version, download URL, and silent-install arguments so you're editing rather than starting blank. The suggestion is grounded, best source first, and the response tells you which source was used:

  • winget manifest (Windows). If the app is recognized by winget in your inventory, the version, installer URL, and a real SHA-256 are read straight from the public winget manifest. This is the most accurate path — and the only one that can return a genuine SHA-256.
  • Package manager (Linux). If the app is tracked by apt/dnf/snap/flatpak in your inventory, the dialog tells you the package manager owns its updates, so a vendor script usually isn't needed — patch it through the PM instead.
  • Web search. For apps no package manager tracks, ET Ducky searches the vendor's site and extracts the version/URL from real results instead of model memory. This requires a search API key (see below); without it this step is skipped.
  • Model knowledge (fallback). If nothing above applies, the model fills its best guess. The dialog flags these as unverified — the version may be stale and a SHA-256 is never produced.

Every suggestion is a starting point you must verify before approving — especially the download URL. For vendors whose installer sits behind a portal with rotating links (Citrix, AMD, and the like), the dialog deliberately returns no URL rather than a landing page; for those, a vendor script that resolves the latest at run time is the better fit.

Admin setup for web-search grounding. Web-search grounding stays off until an operator sets a search API key in the server config (PatchManagement:WebSearch:ApiKey; defaults target the Brave Search API). The server also needs outbound access to the search host. winget-manifest and Linux grounding need no key — only outbound access to GitHub.

Version enrichment

A background job (gated by the PatchManagement:CatalogEnrich flag) keeps the catalog connected to what's actually installed. It compares each agent's latest-inventory version of a cataloged app against the catalog's Latest version. When an agent's installed version is older — and the app isn't already being reported by a package manager — the app appears in the existing Packages Needing Updates list with a Source of vendor_script.

In other words, the catalog teaches ET Ducky the "current" version for software no package manager tracks, and enrichment turns that into the same needs-update signal you already get for winget and the Linux package managers. Because matching is by name, a catalog entry only enriches installs whose reported name matches the entry's Name.

Drafting an update script

Each Software Catalog entry has a Draft update script button. It builds a patch_vendor script that downloads, verifies, and silently installs the app, so a cataloged application can be updated through the same vendor-script path as anything else.

  • How it's drafted. When the entry has a download URL and silent-install args, the drafter uses a deterministic template — the same inputs always produce the same script. When those inputs are missing, it falls back to an AI-drafted script. The result is labelled either "Generated from template" or "AI-drafted — review carefully" so you know which path produced it.
  • Saved as pending-review. The drafted script is created with an approval status of pending_review, and the execution gate is enforced: a pending or rejected patch script will not run. Its vendor_script patch jobs are withheld from agents until it's approved, then dispatch automatically — the same gate that governs recorder-generated automations.
  • An admin reviews and approves it. Drafted scripts land in the built-in Patch Management repo under Integrations → Script Repositories, alongside Default, Agent Generated, and Imported. Open it, click View to read the content, then Approve (or Reject with a reason). The repo shows a pending-review count so nothing waits unnoticed. The View script button next to a drafted catalog entry jumps straight to this repo.

The review gate is the point. Drafting never produces something that executes on its own — an AI-drafted or templated script is a proposal. Read it, especially when it's AI-drafted, and approve it deliberately before it can ever run as a patch job.

Distribute installers through the Distribution Hub

For an app with no package manager, each agent would otherwise download the installer from the vendor itself. If the workspace has a Distribution Hub configured, you can instead publish the installer to the hub once and have every other agent install it from the hub over the local network. The vendor is contacted a single time, agents fetch the bytes locally, and in a locked-down environment only the hub agent needs outbound access to the vendor.

Seeding the installer to the hub

Set a download URL on the catalog entry, then use Save and distribute via hub in the Set up patching dialog (or seed an existing entry from the Software Catalog). This dispatches a one-time job to the hub-host agent, which downloads the installer, records its SHA-256, and caches it on the hub. The entry shows a seed status of seeding, then seeded once the hub holds the file (or failed if the download did not complete). If no Distribution Hub is configured, seeding is skipped and agents fall back to downloading directly.

Installing from the hub

Installs create a binary patch job per agent. Each agent requests a short-lived, certificate-pinned grant, fetches the cached installer from the hub, verifies it against the recorded SHA-256, and runs it with the catalog entry's silent-install arguments (msiexec /i for an MSI, the installer directly otherwise on Windows; an executable run unprivileged on Linux). If the hub cannot be reached, the agent falls back to the direct download URL and verifies the same SHA-256, so an install never depends on the hub being up.

The hub guarantees consistency, not authenticity. Every agent gets byte-identical, hash-verified bits from the hub, but the trust anchor is the first fetch from the vendor URL. Confirm the download URL points at the official vendor installer (and, where the vendor publishes one, check the SHA-256 against their checksum) before distributing it to the fleet.

Network requirements for the hub

Because the hub host is the one machine that reaches the internet for these downloads, the Patch Management page's Network tab includes a Distribution Hub network requirements card. It lists the outbound endpoints the hub agent needs (the control plane, the LAN hub port, the winget / Microsoft set, common Linux mirrors, and the vendor hosts your cataloged apps download from, derived from your Software Catalog) and has a copy button to build a firewall allowlist, so you can lock down every other agent to the hub. Verify the Microsoft and Linux sets against current vendor documentation; they change over time.

Migrate an app to package-manager management

If an app was installed manually but is also available in a package manager (winget on Windows, apt / dnf / zypper on Linux), you can move it under that manager so it patches automatically and you stop maintaining a download URL for it. On the Software Catalog, the Migrate to winget action shows a suggested package id (detected from what winget recognizes across your fleet) for you to confirm, lets you pick which agents to migrate, and offers an "uninstall the existing copy first" option.

By default migration adopts the app in place: the agent runs the package-manager install over the existing app so the manager takes ownership, with no removal step. Uninstall-first is there for apps that need a clean swap. After migrating, the app reports as managed by winget (or the Linux manager) and is patched through the normal pipeline, so it no longer needs a vendor script.

Linux note: the migration install is not covered by the default upgrade-only sudoers rule, so a Linux host needs an updated /etc/sudoers.d/etducky-rmm entry permitting the install before migration can run; until then the agent reports that sudo was refused.

Platform Specifics

Windows

Windows has two engines working together under one policy:

  • Applications — winget. The agent scans with winget upgrade and installs with a silent, non-interactive winget upgrade --id <Id> --version <v> under the service context. Where winget is absent (some Server 2016/2019 hosts without App Installer), the scan records a capability flag and those hosts rely on vendor scripts.
  • Operating system — Windows Update (WUA). The agent talks to the in-box Windows Update Agent COM API directly (no PSWindowsUpdate dependency) to search, classify (security / critical / feature), and install updates by KB. When an install reports a reboot is required, the job parks at awaiting_reboot and obeys the reboot policy and maintenance window. WSUS-managed hosts are detected and their OS updates are marked externally-managed rather than fought.

Linux

On Linux, OS and applications share one engine — the platform's native package manager:

  • Scan and install via apt, dnf, or zypper for system packages, plus snap and flatpak for applications. Security classification comes from each manager's update metadata (the Debian -security pocket, dnf updateinfo, etc.).
  • The narrow sudoers requirement. The Linux agent runs unprivileged. To install packages it relies on a tightly-scoped sudoers drop-in that grants passwordless permission for exactly the upgrade-only package-manager invocations — full-path and argument-anchored, never blanket sudo. This drop-in ships inside the agent package, so enabling Linux patch execution requires rebuilding and reinstalling the .deb/.rpm. Until the package is rebuilt, Linux package installs fail cleanly with a "sudo refused" message rather than silently doing nothing.

If unattended-upgrades is enabled on a Linux host, the agent detects and reports it so your policy doesn't double-drive the same updates.

Security Model

Patch Management inherits ET Ducky's tenancy and integrity invariants. There is no new attack surface introduced by the feature.

  • Org-private data. Patch jobs and available-update history are organization-private, enforced by row-level security (RLS) at the database. A tenant can never read another tenant's patch history.
  • No server free-text into commands. The agent constructs every package-manager invocation from structured job fields — package key and version — not from free-text supplied by the server. A compromised dashboard session cannot inject a command, because there is no free-text command path for winget / WUA / package-manager installs.
  • Unverifiable installer = failed job. Hub-cached and vendor-script installers are SHA-256 verified, and Windows executables may additionally pin an expected publisher. An installer that cannot be verified is a failed job — there is no override flag, matching ET Ducky's verify-or-withhold stance on agent self-updates.
  • Agent-pulled dispatch. Jobs are pulled by the agent over its existing channel; there is no new inbound port or listener on the endpoint.

Set Up Patching from the Dashboard

Patching is configured under Systems → Patch Management on the Configuration tab — the operator surface for everything below: policies, rings, rollout waves, and turning scanning and execution on at the agents.

1. Create a policy with “Set up patching”

Click Set up patching on the Patch Configuration card to open the guided form. It walks through the policy in order:

  • Scope — choose Org default (applies to every agent not assigned through a tag) or Tag (applies only to agents carrying the chosen tag). A tag assignment wins over the org default.
  • OS update mode and App update modemanual, security_auto/all_auto for the OS, and manual/policy_auto for apps.
  • Maintenance window (optional) — pick the days, a start time (interpreted in each agent's local timezone; UTC fallback if the agent's zone is unknown), and a duration in minutes. Approved jobs wait as scheduled until the agent's local window opens.
  • Reboot policynever, window_only, or immediate_if_required.
  • Deferral — the auto-approve after (days) field holds an update for that many days before an auto mode approves it.

Org-default + auto-mode guard: if you set an org-default policy to an automatic update mode, the dashboard asks you to confirm, because that mode auto-approves patches for every untagged agent — your whole fleet by default. Scope it to a tag instead if you want a smaller blast radius.

2. Manage policies

The Policies list shows each policy's scope, OS/app modes, reboot policy, and deferral, with Edit, Rings, and Delete actions. Deleting a policy also removes its tag assignments and rings.

3. Edit rings

Click Rings on a policy to open the rings editor. Each ring row has an order, the agent tag it targets, a soak (hours) value, an auto-promote checkbox, and a verification gate (none / basic / full). Add or remove rings and save. Ring orders must be unique. Rings target agent tags, so create the tags first.

4. Roll out a version with waves

Under Rollout waves, click Start rollout to ring out a specific package version: pick the policy, the source (winget, Windows Update, apt, dnf, zypper, snap, flatpak, or vendor script), the package key, and an optional target version. The wave appears in the list showing its current ring and state; while it's active you can Promote it to the next ring or Abandon it.

5. Enable scanning / execution on agents

The Enable scanning / execution on agents control pushes the per-agent flags. Pick agents from the list — filter by name or ID, use Select all (filtered), or Select by tag to check every agent carrying a tag. Then choose what to enable:

  • Enable scanning pushes PatchScanEnabled — the host starts reporting available updates.
  • Enable execution pushes PatchExecuteEnabled — the host is allowed to install approved updates.

Click Push to agents to apply the selected flags; the control reports how many agents succeeded and lists any failures.

Recommended ramp: create a conservative policy (manual or security-auto with a few days of deferral), push scanning to a handful of agents and review what comes back, then enable execution. Introduce rings and rollout waves only once you trust the verification gate. Unapproved third-party installs you find along the way can be reviewed and allowlisted under Approved Applications.

Troubleshooting

SymptomCause & fix
No available updates show for an agentThe scan flag hasn't reached the agent — PatchScanEnabled is not yet pushed/active on that host. Confirm the agent is online and has received its config; available updates appear after the next scan cycle.
Linux job fails with "sudo refused; rebuild the agent package"The upgrade-only sudoers drop-in ships in the agent package. Rebuild and reinstall the .deb/.rpm (an agent release that carries the drop-in), then retry. This is expected on a host whose package predates patch execution.
Agent installs nothing even though it's configured toThe server-side Execute flag is the authoritative kill switch — while it's off, the jobs endpoint returns empty and no agent installs anything. Confirm the phase flag is enabled.
Job stuck at awaiting_reboot badgeThe install succeeded but needs a reboot, and the reboot policy is never or window_only (window not yet open). Action the reboot manually, or adjust the reboot policy / wait for the maintenance window.
Job stuck at scheduledThe job is approved but waiting for the next maintenance window to open. Check the policy's window days, start time, and duration — remember the start is the agent's local time, so confirm against that host's timezone (and that the agent has reported a timezone; otherwise it falls back to UTC).
Install needs a reboot but the host never restartsEither the reboot policy is never (parks by design), the window_only window closed during the install (parks until the next cycle), or the host is on an agent build that predates agent-side reboot support — update the agent. Reboots fire after a 5-minute warned grace.
OS updates marked externally-managed and not installedThe host is WSUS-managed (or, on Linux, has unattended-upgrades enabled). ET Ducky reports these rather than fighting the existing management; manage them where they're configured, or remove the external management.
Verdict comes back inconclusiveThe agent went offline before the verification window elapsed. It counts as neither verified nor regressed for promotion and is flagged for review — bring the host back online and let it re-verify.

Related

See Agent Tags for the tagging that drives policy assignment and rings, Approved Applications for reviewing and allowlisting unapproved third-party installs, Behavioral Detections and Health Monitoring for the signals verification consumes, Distribution Servers for LAN-local installer caching, Automations for the application-change ledger triggers, and Security for the wider tenancy and integrity model.