MicroVM placement wait reason names KVM
## Defect
Epic 10020's quality bar: "no Linux-specific wording on a Mac or Windows node." The mark path already uses a per-OS sentence (`apps/api/app/microvm_mode.py:65-72` `prereq_sentence`, `PREREQ_SENTENCES`), but the placement wait reason does not: `apps/api/app/microvm_placement.py:63-64` `no_kvm()` returns "<node>'s KVM isn't usable", used at `microvm_placement.py:116` for every OS. A marked macOS node (Virtualization.framework, no KVM) whose hypervisor reports unusable shows a task waiting with "mac-1's KVM isn't usable" — wrong and not actionable. Task 10060 named this as deferred.
Reproduction (read): `capacity_of(node)` with `node.os="macos"`, facts `kvm_usable=false` → reason "…'s KVM isn't usable".
## Fix
In `capacity_of`, when the node is not `usable`, pick the reason per OS: Ubuntu keeps `no_kvm(node.name)`; any other OS returns a node-named sentence built from `microvm_mode.prereq_sentence(node)` (or a neutral "<node>'s hypervisor isn't usable" when that returns None/NO_REPORT). No new vocabulary home: reuse `PREREQ_SENTENCES`; do not copy its strings.
## Acceptance
- Ubuntu node, unusable → reason unchanged ("…'s KVM isn't usable"). Oracle: unit test.
- macOS node, unusable → reason contains no "KVM"/"Linux" and names the node. Oracle: unit test.
- Windows node with `microvm_prereq="wsl_no_kvm"` → reason carries the wsl_no_kvm sentence (it names WSL, which is correct on Windows). Oracle: unit test.
- `./dc check quick` green.
Out of scope: the mark-path sentences, sizing, egress, any runtime code in apps/jaahd, the UI.
Done means:
- The three unit tests above pass in `apps/api/tests` beside the existing `microvm_placement` tests.
- PR merged to develop through the merge lane; Jaah Deploy green.
Outcome
A MicroVM wait reason on a Mac or Windows node now names that OS's prerequisite (or says the node's hypervisor isn't usable) instead of KVM. Ubuntu wording is unchanged. Three unit tests and the quick gate pass. PR #7041 is queued in the merge lane. Memory: none applied.
Artifacts
Activity
- Ready
- Runner started
- Runner ended (done)